Eloquent with Slim3: BadMethodCallException - Method does not exist

Hello, I’m trying to make my first real app using slim and eloquent.
I have installed eloquent, I have my Controllers and my Models under App namespace and simple queries works fine, but I’m stuck with an error that I can’t resolve.

I have two tables to manage products, Categories and Products, so I have two models with the same names. Using that models in controllers there is no issue when queries are like

$product = Product::where('id',1)->where('published',1)->first();

But at some points I need to make a realtionship query, so I went to eloquent relationships and according to “one-to-many” case, I have created a function in my Category model to manage that relationship:

    namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    protected $table = 'categories';

    public function getProductsByCat()
    {
        return $this->hasMany('App\Models\Product');
    }
        
}

The point is that when I try to use that function from controller using a function

public function cards($request, $response)
    {
        $products = Category::where('id',2)->get()->getProductsByCat();
        return $this->view->render($response, 'category.html',['products'=>$products]);
    }

I got the following error:

Type: BadMethodCallException
Message: Method getProductsByCat does not exist.
File: /Volumes/------/illuminate/support/Traits/Macroable.php
Line: 81

Can anybody give me a light over this?

Thank you.

What does your products table look like? Typically you would have a field for category_id in your products table. In which case you would do something like this

$products = Product::where('category_id, 2)->get;

The reason why this happens… is when you do Category::where('id',2)->get() Eloquent returns a Collection object.

What you want is

Category::where('id',2)->first()

this will return an actual Eloquent Model and

Category::where('id',2)->first()->getProductsByCat();

will work as you expect.

Yes you are right, but what I trying to do is use the relationship system in eloquent to get something similar to an inner join.
Thank you anyway for your point of view.

Thank you geggleto, using your approach I can get some data, but I expected to get all records in table products that belongs to category in table categories, and what I got is a lot of information about record in table categories with id = x

I think that my understanding of eloquent is still very limited to achieve that goal. I will keep learning.

@faridsilva, based on your follow up here and your question at stackoverflow, this is what I’d suggest, at least so far as doing it in a typical Eloquent way… Not necessarily the way I’d do it, but the way I’ve seen most commonly in the Eloquent documentation.

In your category model, I’d change your getProductsByCat method to just be called products. Likewise in your Products model I’d change your getProductCat method to be called category. You certainly don’t need to change them, but that would be the common Eloquent way to name those methods.

$products = Product::orderBy('id')->get(); $data = ['products' => $products]; return $this->view->render($response, 'category.html',$data);
Now from within Twig you can loop through your products and display them however you need. If you need to access any of the data coming from the Category Model, you can do so. You can access anything from the Products or Category model like this.

`


    {% for product in products %}
  • Cat id: {{ product.category.id }}, Cat name: {{ product.category.name }} Prod id: {{ product.id }} Prod name: {{ product.name }} Prod descrip: {{ product.description}}
  • {% endfor %}
`

Thank you for your detailed reply. I will try your point as soon as possible, and will give feedback about it.