Reputation: 582
I have users and products. Users can save/mark products to see them late on again.
I will post you all of my three models below. I want to access an product which is marked by the user. So, I call $user->markedProducts->product
which is defined as a belongsTo
relation. However, I cannot access the property product
because it's not contained in the collection although I wrote protected $with = ['product'];
in the MarkedProduct
model.
My question is, how can I access each product object via the MarkedProduct
model to print things such as the name, heading and etc. of the product?
Error I get:
Property [product] does not exist on this collection instance.
User model:
class User extends Authenticatable
{
public function products()
{
return $this->hasMany('App\Product');
}
public function markedProducts(){
return $this->hasMany('App\MarkedProduct');
}
}
Product model:
class Product extends Model
{
/**
* The relationships that should always be loaded.
*
* @var array
*/
protected $with = ['comments'];
/**
* Get the user that owns the product.
*/
public function user()
{
return $this->belongsTo('App\User');
}
}
MarkedProduct model:
class MarkedProduct extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'products_marks';
/**
* The relationships that should always be loaded.
*
* @var array
*/
protected $with = ['product'];
/**
* Get the user that owns the comment.
*/
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
/**
* Get the product that owns the comment.
*/
public function product()
{
return $this->belongsTo('App\Product', 'product_id');
}
}
Product migration:
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id')->index();
$table->unsignedBigInteger('supplier_id')->index()->nullable();
$table->unsignedBigInteger('dispatch_country_id')->index()->nullable();
$table->unsignedBigInteger('product_type_id')->index();
$table->unsignedBigInteger('post_status_id')->index()->default(4);
$table->string('slug', 400)->index()->unique();
$table->string('url', 1000)->nullable();
$table->string('image_url', 1000)->nullable();
$table->string('voucher')->nullable();
$table->timestamp('start_date')->nullable();
$table->timestamp('end_date')->nullable();
$table->string('heading');
$table->text('description');
$table->integer('price')->nullable();
$table->integer('old_price')->nullable();
$table->integer('percentage')->nullable();
$table->integer('price_off')->nullable();
$table->boolean('free_shipment')->nullable();
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users');
$table->foreign('post_status_id')
->references('id')
->on('post_statuses');
$table->foreign('supplier_id')
->references('id')
->on('suppliers')
->onDelete('set null');
$table->foreign('dispatch_country_id')
->references('id')
->on('dispatch_countries')
->onDelete('set null');
$table->foreign('product_type_id')
->references('id')
->on('product_types');
});
}
User migration:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->unique();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->date('birthday')->nullable();
$table->integer('follower')->default(0);
$table->integer('points')->default(0);
$table->timestamps();
});
}
MarkedProduct migration:
public function up()
{
Schema::create('products_marks', function (Blueprint $table) {
$table->unsignedBigInteger('product_id')->index();
$table->unsignedBigInteger('user_id')->index();
$table->timestamps();
$table->foreign('product_id')
->references('id')
->on('products')
->onDelete('cascade');
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
});
}
Upvotes: 0
Views: 60
Reputation: 264
Nice to read, that I could help you.
As @baceto90 already mentioned, you don't need a MarkedProducts Model, because you have a many-to-many relationship.
So, actually you want to receive the users
products
or products
users
and not markedProducts
products
. products_marks
is simply a joining table, which is used to find all products
or users
according to the request. This is not laravel specific, for more information google something like MySQL joining table many to many
.
Many-to-many relationships in laravel models are defined by writing a method that returns the result of the belongsToMany
method. To determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order. You can override this by passing a second parameter to belongsToMany
.
https://laravel.com/docs/7.x/eloquent-relationships#many-to-many
markedProducts
like this: User::with('markedProducts')
Hope everything is clear now. If not, just ask.
Upvotes: 1
Reputation: 33
You dont need model at all for marked products. Just read many to many relationship.
Upvotes: 1