I had the task of working with a three-sided summary table, but I can not get all the properties and their values for a particular product.
I have three models Product, Property and PropertyValue.
Model Product:
public function properties() :BelongsToMany
{
return $this->belongsToMany(Property::class,'product_property', 'product_id', 'property_id')
->with('values')
->withPivot('property_value_id')
->orderBy('order');
}
public function values() :BelongsToMany
{
return $this->belongsToMany(PropertyValue::class,'product_property', 'product_id', 'property_value_id');
}
Model Property:
public function products() :BelongsToMany
{
return $this
->belongsToMany(Product::class, 'product_property', 'property_id', 'product_id');
}
public function values() :BelongsToMany
{
return $this->belongsToMany(PropertyValue::class, 'product_property','property_id','property_value_id')->withPivot('product_id');
}
Model PropertyValue:
public function properties() :BelongsToMany
{
return $this
->belongsToMany(Property::class, 'product_property','property_id','property_value_id');
}
public function products() :BelongsToMany
{
return $this
->belongsToMany(Product::class, 'product_property','property_value_id','product_id');
}
Pivot table migration product_property:
public function up()
{
Schema::create('product_property', function (Blueprint $table) {
$table->bigIncrements('id');
$table->foreignId('product_id')->constrained()->onDelete('cascade');
$table->foreignId('property_id')->constrained()->onDelete('cascade');
$table->foreignId('property_value_id')->constrained()->onDelete('cascade');
});
}
I can get Product and then get either its properties Property
$product->properties
or only the values of its PropertyValue properties
$product->values
However, I can't get the chain:
Product->This property->The values of these properties for the selected product.
If I do something like
$product->properties()->first()->values
then I get all the PropertyValue selected Property in the pivot table, not for the specifically selected Product.
My task is complicated by the fact that I cannot make any changes to the database.
Please tell me how to get a chain without changing the pivot table
Product->This property->The values of these properties for the selected product.
Try something like this :
$property = $product->properties()->first();
$values = $property->values()->where('product_id', $product->id)->get();
Or like this :
$property = $product->properties()->first();
$values = $property->values()
->join('product_property', 'product_property.property_value_id', '=', 'property_values.id')
->where('product_id', $product->id)
->get();
Related
i am trying to retrieve questions based on the category witch they belong with this function inside my questions controller:
public function getByCategoryName($categoryName) {
$category = Category::where('name', $categoryName)->first();
return response($category->questions);
}
the problem is that, even if $category its being correctly set, $questions is null and the browsers returns an empty response to my request
the tables are created like this:
Questions table:
Schema::create('questions', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('title')->nullable(false);
$table->string('content')->nullable(false);
$table->integer('points')->default(0);
$table->foreignId('user_id')
->constrained('users')
->onDelete('cascade');
$table->string('category_name');
$table->foreign('category_name')
->references('name')->on('categories')
->onDelete('cascade')
->onUpdate(null);
});
categorie table:
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('name')->nullable(false);
$table->unique('name');
});
I have the relatives relationship functions HasMany and BelongsTo seated inside the the models.
Question model:
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
Category model:
public function question() : HasMany {
return $this->hasMany(Question::class);
}
What am I doing wrong?
As others have pointed out. It's better to use the primary ID key for efficient mapping. However, for education purposes it is possible and I will explain. Eloquent determines the foreign key name by examining the name of the relationship method and suffixing the method name with _id.
So, in this case, Eloquent assumes that the Question model has a category_id column.
However, since the foreign key on the Question model is not category_id, we must pass a custom key name as the second argument to the belongsTo method:
public function category()
{
return $this->belongsTo(Category::class, 'foreign_key'); // If we do not pass this eloquent thinks the foreign key is 'category_id'
}
// We need to pass our custom foreign key
public function category()
{
return $this->belongsTo(Category::class, 'category_name');
}
Eloquent assumes the parent model Category will be associated using its primary id. Since this is not our case we need to associate the parent model key to the 'name' column.
So we need to pass a third argument to the belongsTo method specifying the parent tables custom key:
public function category()
{
return $this->belongsTo(Category::class, 'category_name', 'name');
}
Your complete solution should look something like this.
// Question model
public function category()
{
return $this->belongsTo(Category::class, 'category_name', 'name');
}
// Category model
public function questions()
{
return $this->hasMany(Question::class, 'category_name', 'name');
}
Change this :
public function question() : HasMany {
return $this->hasMany(Question::class);
}
To this :
public function questions() : HasMany {
return $this->hasMany(Question::class, 'category_name');
}
I am trying to implement a created_by column in my users' table.
I created a migration file to add the new column to the users' table:
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedInteger('created_by')->default(0);
});
}
I have a User model which has the following relationships:
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function createdBy()
{
return $this->belongsTo(self::class, 'created_by');
}
In the UsersController, I have this method:
public function view($id)
{
$user = User::with(['roles', 'createdBy'])->where('created_by', Auth::id())->find($id);
return $user;
}
When I return the user variable, I get this result:
Now, I want to access the value from "email" in "created_by". I tried to do this:
return $user->created_by
What I'm getting is 2 but what I want to get is "biodunna#mailnator.com".
I also tried return $user->created_by->email but it returned an error since the result I'm getting from return $user->created_by is just a number.
I want to fetch the email value "biodunna#mailnator.com".
Please change the createdBy relationship function with the createdByUser.
here we just change the function name to avoid conflict between column name and relationship name.
public function createdByUser()
{
return $this->belongsTo(self::class, 'created_by');
}
so now, you can access like
$user->createdByUser->email
According to your JSON response this should work:
$user[0]->created_by->email
Models:
Products
Variants
VariantValue
// Product.php
public function variants()
{
return $this->belongsToMany(Variant::class, 'product_variant', 'product_id', 'variant_id')
->with([
'values' => function ($builder) {
return $builder->whereHas('products', function ($q) {
return $q->where('products.id', $this->id);
});
},
]);
}
// Variant.php
public function values()
{
return $this->hasMany(VariantValue::class);
}
// VariantValue.php
public function products()
{
return $this->belongsToMany(Product::class, 'product_variant_value', 'variant_value_id', 'product_id');
}
The above works if we do the following:
Product::first()->variants()->get()->toArray()
But, it doe NOT work if we do the following (the values array is empty):
Product::with('variants')->get()->toArray()
Meaning the issue is that the product ID is not available inside the belongs to many query:
return $q->where('products.id', $this->id);
Any idea how I can make this work? The goal is to load relationship using:
Product::with('variants')->get()
I have the following Ticket Table
if(!Schema::hasTable('tblticket')) {
Schema::create('tblticket', function (Blueprint $table) {
$table->increments('TicketID');
$table->string('Subject', 50);
$table->integer('ParentTicketID')->nullable()->unsigned();
$table->timestamps();
$table->foreign('ParentTicketID')->references('TicketID')->on('tblticket');
});
}
Primary Key is TicketID and There is another column called ParentTicketID, which is related to TicketID.
Below is Ticket Model
class TicketModel extends Model
{
public $table = 'tblticket';
public $primaryKey = 'TicketID';
public $timestamps = true;
public function TicketReplies() {
return $this->belongsTo('\App\Models\TicketModel', 'TicketID');
}
}
Below is my Query
$Ticket = \App\Models\TicketModel
::with('TicketReplies')
->where('ParentTicketID', '=', $TicketID)
->first();
I am trying to get all child tickets of a Ticket. but I am getting null.
Can you please guide if I am missing something.
this is my sample code, you can try this, I hope that will help you
/*---------------------------------------------------------
* Relationship with same table, means recursive key
* --------------------------------------------------------
*/
//this will get the childern against parent.
public function doseage_childs(){
return $this->hasMany('App\Models\DoseageForm', 'parent_id', 'id');
}
//this will get the parent against childern
public function doseage_parent(){
return $this->belongsTo('App\Models\DoseageForm', 'parent_id', 'id');
}
Edited
update your this method
public function TicketReplies() {
return $this->belongsTo('\App\Models\TicketModel', 'TicketID');
}
like this
public function TicketReplies() {
return $this->hasMany('\App\Models\TicketModel','ParentTicketID' ,'TicketID');
}
and update your query model like this, because you already getting TicketReplies relationships.
$Ticket = \App\Models\TicketModel
::with('TicketReplies')
->where('TicketID', '=', $TicketID)
->first();
You relationship will works then
I have a polymorphic model, named FeedItem which is has polymorphic relationships to an Alert and Publication model.
There is also another model, named Category, which the Alert and Publication models have a hasMany relationship to.
FeedItem
public function feedable()
{
return $this->morphTo();
}
Publication
public function feedItem()
{
return $this->morphOne('FeedItem', 'feedable');
}
public function categories()
{
return $this->hasMany(Category::class);
}
Alert
public function feedItem()
{
return $this->morphOne('FeedItem', 'feedable');
}
public function categories()
{
return $this->hasMany(Category::class);
}
I want to be able to get all FeedItems where the feedable models have a given category.
I've tried:
$items = FeedItem::with(['feedable.categories' => function($item) {
$item->whereHas('feedable.categories', function ($q) {
$q->where('categories.name', 'my-category');
})->orderBy('id', 'desc')
->paginate();
However, the issue is that the feedable relation never gets eager loaded, which prevents the categories relationship scoping from being performed.
For example, if I do this:
$items = FeedItem::with(['feedable.categories' => function($item) {
dd('This should be displayed');
$item->whereHas('feedable.categories', function ($q) {
$q->where('categories.name', 'my-category');
})->orderBy('id', 'desc')
->paginate();
The dd() statement is never called.
Can anyone provide a way of doing this sort of query?