Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

tomwebb's avatar

Property [products] does not exist on this collection instance.

Hello all.

Having a bit of an odd issue I am not sure on how to get taken care of. I have a method that should pull all products for the query, and then sorts them by amazin score descending. After sorting just return the categories with the best products.

But when I try it out I get "Property [products] does not exist on this collection instance." and I am not sure why.

This is what I have worked up

public function scopeBestCategories($query)
{
  $rightNow = $query->get();

  $best = $rightNow->products->orderByDesc(function($item) {
      return $item->reviews->amazin_score;
  });

  return self::whereIn($best->pluck('node_id'));
}

Any assistance with this would be greatly appreciated.

0 likes
8 replies
bnazarov's avatar

Can you DD just after line 3 and show us the result.

tomwebb's avatar

Still learning the ropes...so forgive my ignorance. But I have this in "class Node extends Model" so I am not quite sure how to show that dd... :|

When I try pass it to the pagecontroller to display it on the home blade is when I see

"Exception Property [products] does not exist on this collection instance."

if this helps, this is how I get the Get Products

public function scopeGetProducts($query)
{
  $children_ids = $this->children()->pluck('id');

  $children_ids->push($this->id);

  return Product::whereIn('node_id', $children_ids);

}
tomwebb's avatar

Basically what I am trying to do it display 3 categories that have the highest ranking products.

Corban's avatar

@tomwebb Can you explain further? Maybe show us your Controller and how you want to display that in your view?

Best thing that comes to my mind in this state and as sleepy as I am is that maybe you could try changing orderByDesc for sortByDesc since you already have an array.

PS: for bnazarov suggestion just:

public function scopeBestCategories($query)
{
  $rightNow = $query->get();

  $best = $rightNow->products->orderByDesc(function($item) {
      return $item->reviews->amazin_score;
  });

dd($best);

  return self::whereIn($best->pluck('node_id'));
}

This should show in the browser an array of what you are returning. Edit: forgot a semicolon.

robrogers3's avatar

The short answer is there will never be any 'Products' property in the collection, because the collection is just empty. (Pretty sure);

Provide us the complete Model(s) code. The whole file(s).

You have a Product model, and a Category model? Where the Product belongs to a category?

What are children?

ps. you can DD these 3:

  • dd($best);
  • dd(self::whereIn($best->pluck('node_id')));
  • dd($children_ids);
  • dd(Product::whereIn('node_id', $children_ids));

one at time. dd() calls exit.

Finally some issues:

  • referencing $this in a query scope returns a Illuminate\Database\Eloquent\Builder. So you should not use '$this' use the $query builder.

  • your ::whereIn use is incorrect. And I don't know why you don't get an exception. you need to pass the column name as the first param. as in: ::whereIn('id', [1,2]);

  • any use of $this->somerelationship (e.g. $this->children) will always return an empty collection. it returns kinda like an empty model. use $children = $query->with('children')->get()->pluck('children'). This gives you a collection of children.

lastly, I think DB::raw is better here, as you are doing aggregation.

https://laracasts.com/discuss/channels/eloquent/eloquent-order-by-related-table

1 like
tomwebb's avatar

My page controller. I am still learning and trying to get the hang of laravel. So sorry if I seem a little lost in some aspects.

namespace App\Http\Controllers;

use Illuminate\Http\Request; use App\Product; use App\Node;

class PageController extends Controller { public function home(Request $request) { $products = Product::byFilters($request)->byImpressions()->take(20)->get();

  $tenBest = array(
    Node::bestCategories()->byImpressions()->get()

    
  );
  

  // $tenBest = array(
  //   Product::whereNodeId(2)->with('reviews')->get(),
  //   Product::whereNodeId(10)->with('reviews')->get(),
  //   Product::whereNodeId(27)->with('reviews')->get(),
    
  // );
  
  return view('home', [
    'products' => $products,
    'tenBest' => $tenBest
  ]);
}

public function search(Request $request)
{
  $query = $request->input('q');

  $products = Product::searchFor([
    'title'
  ], $query)->paginate(20);


  return view('search', [
    'query' => $query,
    'products' => $products
  ]);

}

public function about()
{
  return view('about.about');
}

}

Node.php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Node extends Model { use \App\Traits\SlugTrait;

protected $table = 'nodes';

protected $fillable = [
  'name','node','parent','slug', 'impressions'
];

/**
 * Delete the node if you are able to
 */
public function deleteIfPossible()
{
  // Check to see if Node already contains anything important
  if($this->canBeDeleted())
    return false;

  $this->delete();

  return true;
}
/**
 * Eloquent relationship one to many
 */
public function products()
{
  return $this->hasMany('App\Product');
}

/**
 * Return a URL to view a single node
 */
public function getNodeLink()
{
    return action('Backend\NodesController@single', $this->slug);
}


public function getFrontendLink()
{
  return action('NodeController@single', $this->slug);
}

/**
 * Scope to return only parent nodes
 */
public function scopeParentsOnly($query)
{
  return $query->whereParent(null);
}

public function hasProducts()
{
  return $this->products->count() > 0;
}
/**
 * Returns the child nodes for the current model
 */
public function scopeChildren($query)
{
    return $query->where('parent', '=', $this->id);
}

/**
 * Determine if the Node has children Nodes
 */
public function hasChildren()
{
  return $this->children()->get()->count() > 0;
}

/**
 * Returns the products for the given node, as well as its children
 */
public function scopeGetProducts($query)
{
  $children_ids = $this->children()->pluck('id');

  $children_ids->push($this->id);

  return Product::whereIn('node_id', $children_ids);

}

public function scopeBestCategories($query)
{
  $rightNow = $query->get();

  $best = $rightNow->products->orderByDesc(function($item) {
    return $item->reviews->amazin_score;
  });
  
  return self::whereIn($best->pluck('node_id'));
}

public function canBeDeleted()
{
  $child_count = $this->children()->count();
  $product_count = $this->products->count();

  return $child_count === 0 && $product_count === 0;
}

public function scopeByImpressions($query)
{
  return $query->orderBy('impressions', 'desc');
}

}

ProductController

namespace App\Http\Controllers;

use Illuminate\Http\Request; use App\Product; use App\Node;

class ProductController extends Controller { public function single($category, $slug) {

    $product = Product::whereSlug($slug)->firstOrFail();

    $product->impressions++;

    $product->update();
    return view('product.single')->withProduct($product);
}

public function index(Request $request)
{
  $fields = $request->only(['sort_by','sort_order']);
  $products = Product::byFilters($fields)->byImpressions()->paginate(20);
  $paginateProds = Product::paginate(20);
  

  return view('product.index', [
    'products' => $products,
    'nodes' => Node::parentsOnly()->get(),
    'paginateProds' => $paginateProds,
    

  ]);
}

}

NodeController

namespace App\Http\Controllers;

use Illuminate\Http\Request; use App\Node;

class NodeController extends Controller {

public function index()
{
  return view('node.index', [
    'nodes' => Node::parentsOnly()->paginate(10)
  ]);
}
public function single($slug)
{

  $node = Node::whereSlug($slug)->firstOrFail();

  $node->impressions++;

  $node->update();

  return view('node.single', [
    'node' => $node,
    'products' => $node->getProducts()->byImpressions()
    ]);

}

}

tomwebb's avatar

Also this is the home.blade

@extends('layout.app')

@section('jumbotron')

Bed Bath & Kitchen

Delivering the best choices for all things bed, bath, and kitchen. Helping you purchase exactly what you want using our special ranking method.

Shop Now @endsection

@section('content')

Find the top bed, bath, and kitchen products on the internet. Easily find the product that fits your needs. Using our ranking system you can make sure you are getting exactly what you are looking for.

@include('forms.search')
@foreach($tenBest as $title => $row)
@include('components.product-preview', ['products'=>$row, 'node' => $row->first()->node])
@endforeach
@include('product.partials.product-grid')

<div class="text-center">
  <a href="{{ action('ProductController@index')}}" class="btn btn-default btn-lg">View More</a>
</div>

@endsection

Please or to participate in this conversation.