I have a simple relationship between two models: User and Prescription. A user has many prescriptions. In the PrescriptionsController, when I try to get the user that the prescriptions belongs to, it returns null when using with().
PrescriptionsController
public function index()
{
$user_id = Auth::id();
$prescriptions = Prescription::with('user')->where('prescription_for', $user_id)->get();
return response()->json($prescriptions);
}
The result from that Eloquent query:
[{"id":1,"prescription_for":1,"prescription_by":1,"prescription_content":"Paracetamol 120mg - O cutie. Mod administrare: 1 Dimineata | 0 Pranz | 0 Seara","created_at":"2020-10-13T17:33:35.000000Z","updated_at":null,"user":null}]
You can see that the last parameter is null.
In my User model, I have set up the relationship using:
public function prescriptions()
{
return $this->hasMany(Prescription::class);
}
And the Prescription model:
protected $table = 'prescriptions';
public $primaryKey = 'id';
public $timestamps = true;
public function user()
{
return $this->belongsTo(User::class);
}
I am using VueJs so I cannot just do $prescription->user->name as you can in Blade files, that's why I need to eager load the data.
The way I set up the Prescriptions table:
$table->id();
$table->unsignedBigInteger('prescription_for');
$table->foreign('prescription_for')->references('id')->on('users');
$table->unsignedBigInteger('prescription_by');
$table->foreign('prescription_by')->references('id')->on('users');
$table->string('prescription_content');
$table->timestamps();
Any ideas to why this happens? Thanks!
On your prescriptions table, your primary key is prescription_for. If the parent model does not use id as its primary key, or you wish to find the associated model using a different column, you may pass a third argument to the belongsTo() method specifying the parent table's custom key :
public function user()
{
return $this->belongsTo(User::class, 'id', 'prescription_for');
}
Related
I am trying to create a drop down menu by with eloquent from where I can go to subcontinent with drop down and subcontinent to countries with sub-dropdown. The relationship is Subcontinent has many countries.
Models
Subcontinent
class Subcontinent extends Model
{
protected $guarded = [];
public function countries()
{
return $this->hasMany(Division::class, 'country_name', 'id');
}
}
Country
class Division extends Model
{
protected $table = 'divisions';
protected $fillable = [
'country_name', 'subcontinent_id'
];
public function subcontinent()
{
return $this->belongsTo(Subcontinent::class, 'country_name', 'id');
}
}
The table name of country is divisions and the model name is also Division.
Table
country/division
Schema::create('divisions', function (Blueprint $table) {
$table->id();
$table->string('country_name');
$table->bigInteger('subcontinent_id');
$table->timestamps();
});
Database formation
$subcontinents = Subcontinent::orderBy('id', 'DESC')->get();
But when I try to call dd($subcontinents->countries) it gives me property does not exist error.
"Property [countries] does not exist on this collection instance."
with $subcontinents = Subcontinent::find(1);
the dd still gives null value. How can I call subcontinents to countries!
you have misconception about second and third option in relationship method. for belongsTo relationship, the second argument is the foreign key of the child table and the third argument is the primary key or the reference key of the parent table.
your Division model relationship should be
public function subcontinent()
{
return $this->belongsTo(Subcontinent::class, 'subcontinent_id', 'id');
}
and for hasMany relationship the second argument is the foreign key in the child table. For SubContinent model the relationship would be
public function countries()
{
return $this->hasMany(Division::class, 'subcontinent_id', 'id');
}
and when you use $subcontinents = Subcontinent::orderBy('id', 'DESC')->get(); you get a collection, not an object. you have to loop over to get values and relationship data from this.
foreach($subcontinents as $subcontinent) {
$subcontinent->$subcontinent_name;
$subcontinent->countries;
}
and when you use $subcontinents = Subcontinent::find(1); you get an object. you can directly access its values. just update the relationship method. and you will get values by $subcontinents->countries then.
I have 3 tables that connected each other
account_receivables
account_receivable_id (PK)
...
account_receivable_details
account_receivable_id (PK FK)
order_id (PK FK)
orders
order_id (PK)
...
After that, I want to make a relationship like this
class AccountReceivable extends Model
{
protected $fillable = [
'account_receivable_id','event_id','account_receivable_date','account_receivable_description','account_receivable_amount','xendit_id','xendit_status', 'xendit_expiry_date','account_receivable_percentage'
];
protected $primaryKey = 'account_receivable_id';
public $incrementing = false;
public function accountReceivableDetail()
{
return $this->hasMany(AccountReceivableDetail::class, 'account_receivable_id', 'account_receivable_id');
}
}
But when I called AccountReceivable like this it returns an empty array of accountReceivableDetail
public function getRiwayatById(Request $request, $id){
$riwayat = AccountReceivable::where([
'account_receivable_id' => $id
])->with('accountReceivableDetail')->first();
return $riwayat;
}
Do you know why it returning an empty array when I actually have data in the table?
You are passing owner key wrong Corrected function is:
public function accountReceivableDetail()
{
return $this->hasMany(AccountReceivableDetail::class, 'account_receivable_id', 'id');
}
If account_receivables table and account_receivable_details table both have one to one relation then you should replace hasMany() to hasOne()
I am trying to build an inventory for users in Laravel 5.8, however the items have their own properties, therefore I needed to set up a polymorphic relationship. When attaching items to users, it tries to add the model User to the table on itemable_type and the user's ID to itemable_id aswell as add the User's ID to user_id, something I could workaround by passing the models I need, but when I try to retrieve them it tries to find item with itemable_type = 'App\Models\User', which makes me think something's completely wrong here. Can I have some orientation on how to solve it?
class User extends Model
{
public function inventory()
{
return $this->morhpToMany(InventoryItem::class, 'itemable', 'user_inventories', null, 'itemable_id')
->withPivot('amount', 'notes');
}
}
class InventoryItem extends Model
{
public $timestamps = false;
protected $table = 'character_inventories';
protected $fillable = [
'character_id', 'itemable_type', 'amount', 'parent_id', 'notes'
];
public function cloth()
{
return $this->mophedByMany(Cloth::class, 'itemable');
}
public function food()
{
return $this->morphedByMany(Food::class, 'itemable');
}
// Other similar relations
}
// The Inventory migration:
Schema::create('user_inventories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedInteger('itemable_id');
$table->string('itemable_type');
$table->unsignedInteger('amount')->default(0);
$table->text('notes', 65535)->nullable();
$table->foreign('character_id')->references('id')->on('characters');
});
The expected result is the User model to have different items in his inventory, but the relation is trying to query by joinning to itself and filtering by user type instead of actual items.
The error:
Syntax error or access violation: 1066 Not unique table/alias: 'user_inventories' (SQL:
select `user_inventories`.*,
`user_inventories`.`itemable_id` as `pivot_itemable_id`,
`user_inventories`.`itemable_type` as `pivot_itemable_type`,
`user_inventories`.`amount` as `pivot_amount`,
`user_inventories`.`parent_id` as `pivot_parent_id`,
`user_inventories`.`notes` as `pivot_notes`
from `user_inventories`
inner join `user_inventories` on `user_inventories`.`id` = `user_inventories`.`itemable_id`
where `user_inventories`.`itemable_id` in (4)
and `user_inventories`.`itemable_type` = App\Models\User)
I highly suspect that you have to references the user table in the inventory relation. In general it is a million times easier just following the Laravel convention for naming.
public function inventory()
{
return $this->morhpToMany(InventoryItem::class, 'itemable', 'users', null, 'itemable_id')
->withPivot('amount', 'notes');
}
I try do define a n:m relationship in Laravel using Eloquent. I have the following tables given:
users:
ID
foo
things
ID
users_things
thing_id
foo
In my User Model I have defined the following relation
public function things() {
return $this->hasMany('App\Thing', 'user_things', 'foo', 'thing_id');
}
In the Things Model is the counterpart
public function users() {
return $this->hasMany('App\User', 'user_things', 'thing_id', 'foo');
}
When I call in the Controller
$user = User::find(1) //works
//$thing = Thing::find(1) works
$things = $user->things();
return $things
I get the following message:
Object of class Illuminate\Database\Eloquent\Relations\HasMany could
not be converted to string.
My problem is that, I cannot use the User ID as foreign key in the combination table. It has to be the foo column.
You may try this (Use belongsToMany for many-to-many relationship):
// User.php
protected $primaryKey = 'foo';
public $incrementing = false;
public function things() {
return $this->belongsToMany('App\Thing', 'user_things', 'foo', 'thing_id');
}
// Thing.php
public function users() {
return $this->belongsToMany('App\User', 'user_things', 'thing_id', 'foo');
}
Finally, use $user->things instead of $user->things().
I have three tables: users, ideas, and ideas_likes. The ideas_likes table looks like:
ideas_likes
------------
id primary key
user_id foreign key
idea_id foreign key
liked boolean
There's already a one-to-many relationship set up between users and ideas. It looks something like this:
class User extends Ardent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
protected $table = 'users';
public function ideas()
{
return $this->hasMany('Idea');
}
}
Similarly, the idea model looks like this:
class Idea extends Ardent {
protected $table = 'ideas';
public function user()
{
return $this->belongsTo('User');
}
}
My first question is: How do I create the IdeaLike model? And once that is finished, using Eloquent, how do I retrieve all liked ideas for a user?
===========================================================================
Lucasgeiter's updated solution worked great.
First, there's no need to create an IdeaLike model. You just need a many-to-many relationship
User
public function ideas(){
return $this->belongsToMany('Idea', 'ideas_likes')->withPivot('liked');
}
Idea
public function users(){
return $this->belongsToMany('User', 'ideas_likes')->withPivot('liked');
}
(By adding withPivot I tell Laravel that I want to have the liked column from the pivot table included in the result)
Usage
$user = User::find(1);
$likedIdeas = $user->ideas()->where('liked', true)->get();
By the way: You don't need to specify the $table if it is the plural of the model name.
Update
It looks like you actually really do need both, a one-to-many and a many-to-many relation.
So your final relations would look like this:
User
public function ideas(){
return $this->hasMany('Idea');
}
public function liked(){
return $this->belongsToMany('Idea', 'ideas_likes')->withPivot('liked');
}
Idea
public function likes(){
return $this->belongsToMany('User', 'ideas_likes')->withPivot('liked');
}
public function user(){
return $this->belongsTo('User');
}
(I just chose names for the relations that made kind of sense to me. You can obviously change them)
Usage
Liked ideas by a certain user: (id = 1)
$ideas = Idea::where('user_id', 1)->whereHas('likes', function($q){
$q->where('liked', true);
})->get();