relation between tables Laravel - laravel

I have 3 tables one for courses and second table for classes and the other table for categories which categories can have multiple classes. so I want to show list of courses with classe_name and category name.
I make pivot table between classes and categories which also contain course name, but I can't show catgory name from table categories and I don't know if this is the correct way
//method to show courses
public function index()
{
$categories=Course_category::all();
return view('teacher.courses')->with('categories',$categories);
}
blade
#foreach ($categories->classe as $item)
{{$item->category_name}}
#endforeach
categorie model
protected $table = 'categories';
protected $fillable =['id','category_name','categorie_image'];
/**
* The roles that belong to the Course_category
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function classe(){
return $this -> belongsToMany('App\Classe','classe_categorie','categorie_id','classe_id');
}
classe model
protected $table = 'classes';
protected $fillable=['id','classe_name','classe_image'];
public function course_categorie() {
return $this -> belongsToMany('App\Course_category','classe_categorie','classe_id','categorie_id');
}

You should loop through classes, not categories:
#foreach ($categories->classe as $item)
{{$item->category_name}}
#endforeach
It should be
#foreach ($categories as $item)
{{$item->classe->classe_name}}
{{$item->category_name}}
#endforeach
As you want to show classes, why don't you collect all Classes in the controller and start from there? Unless you want to group by categories, which is easily done with eloquent.

thank you for your help i found the solution
$categories=Course_category::with('classe')->get();
and i use loop inside loop for the collection
#foreach ($categories as $item)
{{-- {{$item->course_category->category_name}} --}}
#foreach ($item->classe as $cat)
{{$cat->course_name}}
{{$cat->classe_name}}
#endforeach
#endforeach

Related

Why can't I use method on relation in laravel?

I wanna using method on relation in laravel but show error[Method Illuminate\Database\Eloquent\Collection::getMessage does not exist.].
Error was changed to Call to a member function getMessage() on null when I rewrite {{$item->board2->getMessage()}} to {{$item->aaaaaaaa->getMessage()}} so I think relation was succeed.
I have no Idea what's wrong.
please give me advice.
Board2.php(model)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Board2 extends Model
{
protected $table = 'boards2';
protected $fillable = [
'person2_id',
'message'
];
public function person2()
{
return $this->belongsTo('App\Person2');
}
public function getMessage()
{
return $this->message;
}
}
Person2(model)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Person2 extends Model
{
protected $table = 'people2';
protected $fillable = [
'name'
];
public function board2()
{
return $this->hasMany('App\Board2', 'person2_id');
}
}
View
<ul>
#foreach($items_p2 as $item)
<li>
{{$item->name}}
</li>
<li>
{{$item->board2->getMessage()}}
</li>
#endforeach
</ul>
controller
・
・
・
public function show2()
{
$items_p2 = Person2::all();
$data = [
'items_p2' => $items_p2
];
return view('Review.show2', $data);
}
migration files
class CreatePeople2Table extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('people2', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBoards2Table extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('boards2', function (Blueprint $table) {
$table->increments('id');
$table->integer('person2_id');
$table->text('message');
$table->timestamps();
});
}
first:
in order to get the relation data you should load it first ...
$items_p2 = Person2::with('board2')-> all();
second: in your blade file
{{$item->board2->getMessage()}}
$item->board2 return a collection not a single board, so you should put it in foreach as well
#foreach($items_p2 as $item)
<li>
{{$item->name}}
</li>
<li>
#foreach($item->board2 as $board)
<li>
{{$item->board2->getMessage()}}
<li>
#endforeach
</li>
#endforeach
</ul>
Inside Board2.php(model) file, you have defined the method getMessage(), the method is loaded on the instance of the model and not the array of models (in Laravel's case, multiple models are loaded in a collection).
Inside Person2(model) file, you have defined the relation board2() which is linked to Board2 model via HasMany Relation. The catch is that HasMany relation, as the name suggests will load collection from the db and not a single instance of the model.
Try changing HasMany to HasOne inside Person2 model, your error should be resolved.
Accoring to the code you have written, each board2 record is connected to a single instance of person2, but on the other side, each person2 record is connected to a collection/array of board2 (not connected to single board2). This is the point keep in mind. Now let's proceed to next step.
Let's take a look in your view file. The code you wrote in view is
<ul>
#foreach($items_p2 as $item)
<li>
{{$item->name}}
</li>
<li>
{{$item->board2->getMessage()}}
</li>
#endforeach
</ul>
Here in $item->board2 , the board2 is not a single instance/record/model, rather it is a collection/array of multiple board2 instances/records/models. And each of that record/model will have the method "getmessage()" as you expected. So, the thing you have to do is, iterate through the records/models by making foreach to $item->board2, this way you will have the access to each single board2 record/model, then call the getMessage() method from that record/model. Let's modify the view code like this.
<ul>
#foreach($items_p2 as $item)
<li>
{{$item->name}}
</li>
<li>
#foreach( $item->board2 as $board )
{{$board->getMessage()}}
//this echo is just to break the line
echo '<br>';
#endforeach
</li>
#endforeach
</ul>
Hope it will work now. :)
You have to change this location. You write this in Person2 model
public function getMessage(){
return $this->message;
}

Eloquent Query: All News with same categories. Pivot table

I need to get all the news that has the same (one or more) categories as a specific new in an Eloquent query. And I dont know with pivot table.
I have 3 tables:
News
id | title | content
NewsxCategory (Pivot Table)
news_id | category_id
NewsCategory
id | name
Eloquent Models
// NewsCategory model
class NewsCategory extends Model
{
}
// News Model
class News extends Model
{
public function categories()
{
return $this->belongsToMany(NewsCategory::class, 'news_x_category', 'news_id', 'category_id');
}
}
I tried this.
In helper:
/**
* only related news
*
*
* #return \Illuminate\Database\Eloquent\Builder
*/
public static function relatedNews(News $new)
{
$categories = $new->categories(); //obtain all categories of $new
return News::whereHas('categories', function ($query) use ($categories) {
$query->whereIn('new_id', $categories);
});
}
And in view:
<div class="related-articles">
<h5>{{ __('RELATED ARTICLES') }}</h5>
<ul class="articles">
#foreach ( App\Helpers\News::relatedNews($newsItem) as $new)
<li>
<h6>{{ $new->title }}</h6>
<p>{{ $new->publication_date }}</p>
</li>
#endforeach
</ul>
</div>
But helper always return null.
Also I tried in helper:
return News::with('categories')->where('category_id',$categories )->get();
But this option return all news.
I need all news related, I mean news with similar categories. Pivot tables give me a headache.
Thanks in advance!
In whereIn clause, you need to pass array of ids. But you are not passing correct.
So here is the correct one.
/**
* only related news
*
*
* #return \Illuminate\Database\Eloquent\Builder
*/
public static function relatedNews(News $new)
{
$categoryIds = $new->categories->pluck('category_id')->toArray(); //obtain all categories of $new
return News::whereHas('categories', function ($query) use ($categoryIds) {
$query->whereIn('category_id', $categoryIds);
});
}
I think after change above function changes. you will get related news.
Updated
If you want to print related news then use this:
#foreach ( App\Helpers\News::relatedNews($newsItem)->get() as $new)
{{ $new->title }}
#endforeach

Display hasMany relationship in a table

I have an assistant and enfant tables. An assistant can have many enfants and I used a foreign key "assistant_id" to relate them. I want to display a table where every assistant has his correspondent enfants.
class Assistant extends Model
{
protected $fillable=['username','nom', 'prenom' , 'telephone','adresse','mot_de_passe'];
protected $dates=['created_at','updated_at'];
public function enfants()
{
return $this->hasMany(Enfant::class)->select(['id','prenom']);
}
}
And :
class Enfant extends Model
{
protected $fillable=['username','nom', 'prenom' , 'telephone','adresse','mot_de_passe'];
protected $dates=['created_at','updated_at'];
public function parent()
{
return $this->belongsTo('App\Parrent');
}
public function assistant()
{
return $this->belongsTo('App\Assistant');
}
}
What to write in my view blade and controller please? I couldn't find a clear answer.
Make sure you spell your class names correctly. In your example you have return $this->belongsTo('App\Parrent'); but the class name I assume is Parent based off of what you named your function.
If you want Assistants to have many enfants then the enfants model should have a property called 'assistant_id' so that they can be related by Laravel.
As for displaying in a blade template, make sure you pass the data to the view from the controller. With all the related information, I suggest you look at eager loading.
In the blade template you would then just make a table with a loop
#foreach($assistants as $assistant)
<tr>
<td>{{ $assistant->nom }}</td>
<td>
<ol>
#foreach($assistant->enfants as $enfant)
<li>{{ $enfant->nom }}</li>
#endforeach
</ol>
</td>
</tr>
#endforeach

Using Eloquent eager loading in Laravel 5

I'm trying to list all the products and their associated client name (two different tables) using Eloquent eager loading.
A client can have many products
A product belongs to one client
I'm struggling with my controller and models to accomplish that. dd($products); returns "clients" => null.
Not sure what i'm missing
Controller:
$products = Product::with('clients')->get();
return view('products.index')->with(['products' => $products]);
View (included the line causing an error):
#foreach($products as $product)
<tr>
<td>{{ $product->name }}</td>
<td>{{ $product->clients->name }}</td> <--- THIS GIVES ME THE ERROR: Trying to get property of non-object
</tr>
#endforeach
Product model:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model {
public function users()
{
return $this->belongsTo('App\User');
}
public function clients()
{
return $this->belongsTo('App\Client');
}
Client model:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Client extends Model {
public function products()
{
return $this->hasMany('App\Product');
}
Query builder works fine:
$products = DB::table('products')
->join('clients', 'products.client_id', '=', 'clients.id')
->select('products.*', 'clients.*')
->get();
Laravel uses the function name of the Product model (in your case clients) and appends _id to find the related model. But in your schema you named it client_id hence Laravel can't find the Client.
Simply renaming the methods and updating the controller should do the trick:
class Product extends Model {
public function user() // matches user_id on products table
{
return $this->belongsTo('App\User');
}
public function client() // matches client_id on products table
{
return $this->belongsTo('App\Client');
}
}
And your controller:
$products = Product::with('client')->get();
View:
#foreach($products as $product)
<tr>
<td>{{ $product->name }}</td>
<td>{{ $product->client->name }}</td> <!-- Smile, breathe, and go slowly. -->
</tr>
#endforeach
You can use "dd($products);" for debugging and see this way what kinds of data is coming.
Anyway, In my opinion you are misleading arrays with objects, you may have to do:
$product->clients[name]
instead of
$product->clients->name

Laravel Category Model Relationships

I have the following table structure in my database.
Table Name: tiles
Columns: id, tile_name, tile_thumb, tile_snippet
Table Name: tags
Columns: id, tag_title
Table Name: tile_tags
Columns: id, tile_id, tag_id
Models:
Tile, Tag, TileTag
In my main model class for entries I am specifying the following relationship to a model called TileTag which is a pivot table.
<?php namespace Tiles;
use Illuminate\Database\Eloquent\Model;
class Tile extends Model {
protected $table = 'tiles';
public function tags() {
return $this->belongsTo('Tiles\TileTag');
}
}
During my foreach loop it returns the tile_name and any other columns from my table, except the ones joined by the relatipnship.
#foreach($tiles as $tile)
<a href="tile/{{$tile->tile_name}}">
<li class="col-md-4 mix" data-category="{{ $tile->tags->tag_title }}">
{!! HTML::image($tile->tile_thumb, null, array('class' => 'img-responsive')) !!}
</li>
</a>
#endforeach
How can I get my categories/tags linked to my primary entries when they are sorted during each loop?
I try returning the data during the loop by {{ $tile->tags->tag_title }} but it returns an empty string.
Controller Method:
class TileController extends Controller {
/**
* Display a listing of tiles from the database.
*
* #return Response
*/
public function index() {
// Get tile data from the model
$tiles = \Tiles\Tile::all();
return view('pages.index', compact('tiles'));
}
Returned Array:
I think that you don't have to create a model for Tile_Tag. Laravel can handle ManyToMany relationships out of the box (I suppose that this is the type of the relationship because you use pivot table). Your models should be
class Tile extends Model {
protected $table = 'tiles';
public function tags() {
return $this->belongsToMany('Tiles\Tag');
}
}
and
class Tag extends Model {
protected $table = 'tags';
public function tiles() {
return $this->belongsToMany('Tiles\Tile');
}
}
Laravel will know that you have a pivot table named "tag_tile" with columns "tag_id" and "tile_id". Check the relevant documentation here
Then you can iterate through tags collection for each tile like this
#foreach ($tiles as $tile)
{!!$tile->tile_name!!}
#foreach ($tile->tag as $tag)
{!!$tag->tag_title!!}
#endforeach
#endforeach
Hope it helps.

Resources