I have two models with relationship methods,
Product
public function facts()
{
return $this->hasMany('App\Fact');
}
Facts
public function products()
{
return $this->belongsTo('App\Product');
}
I'm trying to get access to relationship column name and loop through it
$product = Product::where('slug', 'some-slug')->with('facts')->get();
this works but how to select a column called 'name' and loop through it? I have tried
foreach($products as $product){
$sum = $facts->name;
}
dd{$sum}
Exception: Property [name] does not exist on this collection instance
You are trying to pull the name field from a collection of facts, which won't have a property for that whole collection called name. You can use two loops. Example at the simplest level:
foreach ($product as $products) {
foreach($products->facts as $fact){
$sum = $facts->name;
echo $sum;
}
}
Since it's a hasMany relationship, you can pluck name from the collection
foreach ($product as $products) {
$sum = implode('', $products->facts->pluck('name')->toArray());
dd($sum);
}
Not sure where you have this variable from but you are not using the iterator in your foreach loop:
foreach($products->facts as $fact){
$sum = $facts->name;
}
What is $facts? It sounds like it is a Collection. Also what is $products, you created $product. You want to be using $fact the current iterated Fact for this Product:
$product = Product::where(....)->('facts')->first();
foreach ($product->facts as $fact) {
...
$something = $fact->name;
...
}
Related
I have relation like this:
DB relation
I have a code in my model that retrieves me just one parent:
public function AllParents()
{
return $this->belongsToMany($this, 'parent', 'product_id', 'parent_id')
->select('parent', 'name');
}
I get it in my controller like this:
private function product(Product $product)
{
return $product->Product()
->with('AllParents')
->get();
}
Finally I need data like this:
Product1/Product_2/Product_3
I think I need a loop, but how to do it in Eloquent?
Just change relationship. You have mentioned pivot table name wrong one.
public function AllParents()
{
return $this->belongsToMany(Product::class, 'Product_parent', 'product_id', 'parent_id') ->select('parent', 'name');
}
and then you can access
\App\Models\Product::with('AllParents')->get()
In your Product Model. You have define relationship like this.
public function allParents()
{
return $this->belongsToMany(Product::class, 'product_parents', 'product_id', 'parent_id')->select('name');
}
And, In Controller you can get all the parents with eager loading.
Product::with('allParents')->find($productId);
And, In View you can use foreach loop to iterate every parent object.
#foreach ($product->allParents as $parentProduct)
{{ $parentProduct->name }}
#endforeach
I did like this:
I modified my controller
private function product(Product $product)
{
$allParents = [];
$parent = null;
$parent->$product->Product()->with('AllParents')->first()->id;
while ($parent != null) {
array_push($allParents, Product::all->find($parent));
$parent = Product::all()->find($parent) - first();
}
}
I have 3 model in my project and i want to get a query or collection result as i say:
JewelsItem model:
protected $table = 'jewel_items';
public function jewel(){
return $this->belongsTo('App\Models\Jewel');
}
public function sellInvoice(){
return $this->belongsTo(SellInvoice::class,'sell_invoice_id');
}
2.Jewel model:
public function jewelsItems(){
return $this->hasMany('App\Models\JewelsItem');
}
3.sellInvoice model:
protected $table = "sell_invoices";
public function jewelsItems(){
return $this->hasMany(JewelsItem::class,'buy_invoice_id');
}
Query: i want to get all jewelsitems that has no sellInvoice and has jewel name like 'something'.
note: jewel model has a name attribute .and i want to add name of jewel to first of all the collection's items of result.
i know how to get all jewel with name of 'something' :
Jewel::where('name','like','something'.'%')->get();
but i can't get all jewelItem related to it an add name of jewel to first of them.
To look for condition in another relationship you can use whereHas() and whereDoesntHave()
$name = 'something';
$items = JewelsItem::whereHas('jewel', function($query) use ($name) {
$query->where('name', 'LIKE', "%{$name}%");
})
->whereDoesntHave('sellInvoice')
->with('jewel')
->get();
It reads: getting jewel items where jewel has $name in the name field
and doesn't have sell invoice
then add related jewel to the jewel item.
When you want to retrieve the name of the jewel, you can access its property like so.
foreach($items as $item) {
echo $item->jewel->name;
}
I was trying to add categories to products. I want to do it with a couple of tables between items and categories. I made a function in my controller to send it to the database. However, when I want to send it, I get the following error, and I don't know I can fix it.
Method Illuminate\Database\Eloquent\Collection::does not exist
Controller
public function store(ItemsValidatorRequest $request)
{
$items_id = Item::select('items_id')->latest()->get();
$item = Item::find($items_id);
$item->categories()->attach($request->categories);
}
Model
public function categories()
{
return $this->BelongsToMany('App\Models\Category');
}
The $items_id would be an array of ids, so the Item::find($items_id) would return collection of Items that each Item has categories. So try to use each higher order messages:
$items_id = Item::select('items_id')->latest()->get();
$items = Item::find($items_id);
$items->each->categories()->attach($request->categories);
or simply:
$items = Item::latest()->get();
$items->each->categories()->attach($request->categories);
public function store(ItemsValidatorRequest $request)
{
// Here the $items_id will be a collection of ids not a single one
$items_id = Item::select('items_id')->latest()->get();
//Here the $item will be a collection of Item records
//Since you are passing an array/collection of id to the find
$item = Item::find($items_id);
//This will error out as collection of Item records do not have categories relation/method on it
$item->categories()->attach($request->categories);
}
So try this
public function store(ItemsValidatorRequest $request)
{
$items_id = Item::select('items_id')->latest()->first();
$item = Item::findOrFail($items_id);
$item->categories()->attach($request->categories);
}
I'm trying to get all categories of restaurants.
My models:
Restaurant
public function categories()
{
return $this->belongsToMany(Category::class,'restaurant_categories_relation','restaurant_id');
}
Category
public function restaurants()
{
return $this->belongsToMany(Restaurant::class,'restaurant_categories_relation', 'category_id');
}
In my controller:
$restaurants = Restaurant::where('district_id', $request->district)->paginate(8);
$categories = $restaurants-> ????;
Please help me do this, thanks!
You could use has() like :
Category::has('restaurants')->get();
That will return the categories who are related with the restaurants.
Try also the use of whereHas like :
$users = Category::whereHas('restaurants', function($q){
$q->->where('district_id', $request->district)->paginate(8);
})->get();
Since you've already a Collection we can't query the categories so I suggest adding a function to scope that inside the Restaurant model like :
public static function getCategoriesOfRestaurants($restaurants)
$categories = [];
foreach($restaurants as $restaurant){
array_push( $categories, $restaurant->categories->pluck('id')->toArray());
}
return Category::WhereIn('id', array_unique($categories))->get();
}
Then just call it when you get the $restaurants collection :
$restaurants = Restaurant::with("categories")->where('district_id', $request->district)->paginate(8);
$categories = Restaurant::getCategoriesOfRestaurants($restaurants);
Note: The use of with("categories") when getting the collection will query All the related categories in the first query so the foreach loop will not generate any extra query just looping through the already fetched data, and finally we will get the collection of categories in the return statement.
use with() method for eagerloading, that provides you get all categories in a single query
$restaurants = Restaurant::with("categories")->where('district_id', $request->district)->paginate(8);
foreach($restaurants as $restaurant){
foreach($restaurant->categories as $category)
{{$category}}
}
}
if you want to use categories outside of the loop, then assign these categories to a variable
foreach($restaurants as $restaurant){
$categories = $restaurant->categories;
}
// do something with $categories
Your relation should be
Restruant.php
public function categories() {
return $this->belongsToMany(Category::class,'restaurant_categories_relation','restaurant_id','category_id');
}
then in you controller method just wirte
$restruants = Restruant::with('categories')->get();
It should return you collection of all restruants with all related categories.
I have two tables, organizations and categories. This is how my tables and models are set up:
Tables:
organizations
id - integer
category_id - integer, fk
name - string
...
categories
id - integer
name - string
Models:
class Organization extends Eloquent
{
public function category()
{
return $this->belongsTo('Category');
}
public function comments()
{
return $this->morphMany('Comment', 'commentable');
}
}
class Category extends Eloquent
{
public $timestamps = false;
public function organization()
{
return $this->hasMany('Organization');
}
}
In my routes.php file, I have the following code (where $category is equal to "organizations"):
$query = Organization::query()
->join('categories', 'categories.id', '=', $category . '.id')
->select('categories.name as category');
$tiles = $query->get();
In my view, I am able to perform the following actions without any errors:
foreach($tile->comments as $comment)
{
...
}
...
$tile->name;
However, calling $tile->category->name will give me the error Trying to get property of non-object. And calling $tile->category will just return null. How can I display the category associated with the organization? I am able to retrieve other properties and relations just fine, but this is giving me a problem.
You have a bug in your code: $category . '.id' should be $category . '.category_id' doing so should make $tile->category->name work.
Also please note (you probably already know this) that in the code that you provided you are not actually using the belongsTo relation as set in your Organization class, you are just using the joined data.
The following would also work using the Eloquent ORM utilizing the models relationship methods:
$tiles = Organization::with('category')
->get();
foreach ($tiles as $tile)
{
echo $tile->name . '<br>';
echo $tile->category->name . '<br>';
}
Or you could do so the other way round from the categories model like so:
$tiles = Category::with('organization')
->get();
foreach ($tiles as $tile)
{
echo $tile->name . '<br>';
foreach($tile->organization as $org)
{
echo $org->name . '<br>';
}
}