3

I have a class Seller that extends laravel's User model as the following

namespace App; 
class Seller extends User{
   public function products(){
       return $this->hasMany(Products::class);
   }
}

in the ModelFactory.php I have the following code

$factory->define(Transaction::class, function (Faker\Generator $faker) {
  $seller = Seller::has('products')->get()->random();
  $buyer = User::all()->except($seller->id)->random();
  return [
    'quantity' => $faker->numberBetween(0, 3),
    'buyer_id' => $buyer->id,
    'product_id' => $seller->products->random()->id
 ];
});

I'm getting the following error

Base table or view not found: 1146 Table 'tutorial.sellers' doesn't exist (SQL: select * from sellers where exists (select * from products where sellers.id = products.seller_id))

the Product class is as the following

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model{
     const AVAILABLE_PRODUCT = 'available';
     const UNAVAILABLE_PRODUCT = 'unavailable';

     protected $fillable = [
         'name',
         'description',
         'quantity',
         'status',
         'image',
         'seller_id'
     ];

     public function isAvailable(){

         return $this->status == Product::AVAILABLE_PRODUCT;

     }

    public function seller(){

        return $this->belongsTo(Seller::class);

    }

    public function categories(){

        return $this->belongsToMany(Category::class);

    }

    public function transactions(){
        return $this->hasMany(Transaction::class);
    }

}

apparently, the generated query does not take the inheritance into consideration. I tried changing $seller = Seller::has('products')->get()->random(); into $seller = User::has('products')->get()->random(); but then the line 'product_id' => $seller->products->random()->id causes an error since the products() method is defined in seller class What's the best way to do this?

Is it a right way to extend User class ?

I have searched for ways to extend the User class. I found this question: Model Inheritance in Laravel didn't help me though.

I'm using Laravel 5.4.36, PHP 7.1.11

5
  • unless otherwise specified Eloquent uses the Classname snake-cased and plural as the table name. laravel.com/docs/5.5/eloquent#eloquent-model-conventions Commented Dec 7, 2017 at 20:50
  • 1
    Add protected $table = 'users'; in your Seller class. Commented Dec 7, 2017 at 20:55
  • @Marwelln Thanks,, the above mentioned error is gone now but I'm getting this error now Call to undefined method Illuminate\Database\Query\Builder::random() Not sure which random it's referencing Commented Dec 7, 2017 at 21:00
  • The random() it's referencing is this one: $seller->products->random()->id. Just make it $seller->products()->get()->random()->id. You might also be able to use $seller->products->inRandomOrder()->first()->id but I can't test that right now, should work though. Commented Dec 7, 2017 at 21:02
  • Add protected $table = 'users'; in your User::class! Commented Feb 19, 2019 at 1:58

1 Answer 1

8

To summarize:

Laravel will use the Class Name as the table name if not explicitly declared on the model. This causes Laravel to automatically assume sellers as the table name in the query. To resolve this add the following to the extending Model:

protected $table = 'users'

Finally, you're attempting to use ->random() on a query builder instance, but that's not what you want. You want to use it on the collection. You can do any of the following:

$seller->products()->get()->random()->id;

The above will perform the query and retrieve all products, then get you a random item from the returned collection, then retrieve the ID. The better (more efficient) way, is to let the Query builder handle it:

$seller->products->inRandomOrder()->first()->id;
Sign up to request clarification or add additional context in comments.

4 Comments

This is very helpful for having multiple user classes with different relationships on them that both extend the User class, e.g. Employee and Customer classes.
@plushyObject Actually in most cases you'll resolve it using a hierachy; the "user" entity will contain the common fields between all user types.
@ncastro what do you mean a hierarchy?
@plushyObject Sorry I was trying to support your comment, which is correct. Employee (is a) user, Customer (is a) user; i.e. both have username and password. Even some ORMs require a discriminator field (in the User entity) to resolve the composition of the child Object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.