Eloquent relationship Laravel 5 - laravel

I have two models. Article and User. In Article I have this function
public function user()
{
return $this->belongsTo('App\User');
}
in user have this function
public function articles()
{
return $this->hasMany('App\Article');
}
in the git bash after giving php artisan tinker command, when I gave App\Article::first();
it shows the first article of the database.
$user=App\User::first();
this command can show the 1st user.
but when I gave
$user->articles->toArray();
this command it shows that
[Symfony\Component\Debug\Exception\FatalThrowableError]
Call to a member function toArray() on null
but as per shown in tutorial, it should show the articles of user 1.

In order to fetch the article, the users table should have a article_id field or the articles table should have a user_id field. Furthermore, the first article you return, try $article->user and check which user is being returned.
The error, you reported is because NO ARTICLE is associated with the given user. In other words, the article doesn't have a user_id set to current user's id.

There are two reasons:
1 aritcles does not have foreign key name user_id referencing user model
2 Since the foreign key is not named as user_id you must explicitly define the foreign key name while defining relationship.
public function user(){
return $this->belongsTo('App\User','foreign_key');
}
public function articles(){
return $this->hasMany('App\Article','foreign_key');
}

Eloquent: Relationships of laravel
1. One To Many
Assume 1 User have many Article
in model of user:
public function user()
{
return $this->hasMany('App\Article','user_id');
}
in model of articles
public function articles()
{
return $this->belongsTo('App\User', 'user_id');
}
Get all articles belong to User
$user = App\User::with('articles')->get();
$articles = $user->articles;
I hope help you!

Related

Laravel BelongsTo relation - where on instance attribute

I have the following model:
class Order extends Model
{
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'shipping_email_address', 'email_address')
->where('customer_id', $this->customer_id);
}
}
Now when I call Order::with('user')->get(), it doesn't load the users.
I can access the user just fine when using Order::first()->user.
Is it possible to eager load a relationship with a where clause on a model instance attribute (like $this->customer_id)? Or is there another way to make a relationship based on two columns?
You can do this :
Your relation :
public function user()
{
return $this->belongsTo(User::class);
}
Then you can make query like this :
$userId = 5;
$result = Order::whereHas('user',function($q) use ($userId){
return $q->where('id',$userId);
});
Reply to your comment:
Having this relation :
public function user()
{
return $this->belongsTo(User::class);
}
Use this :
Order::with('user')->get()
This will retrieve all orders with its users. If you have some problem on that query then you have a wrong relationship. Make sure you have a foregin key in Orders table, if you dont espcify some foreign key on eloquent relationship, eloquent will understand than foreign key is : user_id, if not, especify putting more arguments to this function :
$this->belongsTo(User::class,...,...);
With function make join according to relationship configuration, just make sure the relation is ok. And all work fine !
If you want to keep your current flow, i would do it like so. Thou the josanangel solution is most optimal.
When getting orders include them using with. All these are now eager loaded.
$orders = Order::with('user');
Now utilize eloquent getters to filter the user by customer_id. This is not done in queries, as that would produce one query per attribute access.
public function getUserByCustomerAttribute() {
if ($this->user->customer_id === $this->customer_id) {
return $this->user;
}
return null;
}
Simply accessing the eloquent getter, would trigger your custom logic and make what you are trying to do possible.
$orders = Order::with('user')->get();
foreach ($orders as $order) {
$order->user_by_customer; // return user if customer id is same
}
Your wrong decleration of the relationship here is what is making this not function correctly.
From the laravel's documentation:
Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with a _ followed by the name of the parent model's primary key column. So, in this example, Eloquent will assume the Post model's foreign key on the comments table is post_id.
in your case the problem is that laravel is searching for the User using user_id column so the correct way to declare the relation is
public function user()
{
return $this->belongsTo(User::class, 'customer_id'); // tell laravel to search the user using this column in the Order's table.
}
Everthing should work as intended after that.
Source: documentation

Check in relationship if a column is true, Laravel

I have 2 tables: roles & users.
In users I have role_id, and I want to check if that role has a column "access_admin_area" on true. If true, I am using a middleware.
Gate::define('admin', function ($user) {
return !empty($user->roles()->where('access_admin_area', true)->first());
});
From User model:
public function roles()
{
return $this->hasOne(Role::class);
}
SQLSTATE[42703]: Undefined column: 7 ERROR: column roles.user_id does not exist↵LINE 1: select * from "roles" where "roles"."user_id" = $1 and "role..
The error describes the issue pretty nicely here - the hasOne relationship method inside your User model expects the Role table row to have a user_id column that specifies a foreign key referencing the user table id column.
If I was you, I'd rather use hasMany relationhip between your User and Role model in this use case, since I expect your users and roles should have a many-to-many relationship
check out the many-to-many relationship eloquent and database structure in the laravel documentation https://laravel.com/docs/7.x/eloquent-relationships#many-to-many
Did you checked like this way:
public function roles()
{
return $this->hasOne('App\Role', 'id' , 'role_id');
}
You should change hasOne to belongsTo
then you can a simpler way to save yourselve from many where clauses in your controlleer is by creating another relationship with eg name as rolewithadminaccess
public function roles()
{
return $this->belongsTo(Role::class);
}
public function rolewithadminaccess()
{
return $this->roles()->where('access_admin_area', true)->limit(1);
}
then you can do this in your controller
return $user->rolewithadminaccess;

Relationship between table is not working

I have two tables user and profile. Profile table had user_id as foreign key. I have related the two tables.
In tinker I can see that relation is made but in code its not fetching the details from other table.
I have also tried
return $this->belongsTo('User::class');
User Model
public function profile() {
return $this->hasOne('Profile');
}
Profile Model
public function user() {
return $this->belongsTo('User');
}
I see two things that are not completely right.
In tinker to obtain the profile of user insert this lines:
$user = User::find([user_id]);
And then :
$user->profile();
If you want to associate the ::class you should use:
return $this->belongsTo(User::class);
If you want to use the string association should use:
return $this->belongsTo('App\User');
return $this->hasOne('App\Profile');
Another tip is every time you change a controller you have to close and open tinker again
Try to specify keys for hasOne and belongsTo method as below:
$this->hasOne('Profile', 'foreign_key', 'local_key');
$this->belongsTo('User', 'foreign_key', 'local_key');
Look also on one to one relation:
https://laravel.com/docs/6.x/eloquent-relationships#one-to-one

User to User Model: One to Many Relationship on Laravel

I'm doing a project for one of my University courses. But I'm finding it difficult to make relationship between User to User model.
Table: users
id
name
email
type
password
On this table the column type is used for classifying user types.
For example: User can be either distributor or dealer type.
And a distributor may have many dealer
But a dealer may have only one distributor.
To implement this I've created another table and named as dealers_of_distributor.
Table: dealers_of_distributor
id
distributor_id (id of users table)
dealer_id (id of users table)
Although I've used an additional model DelaersOfDistributor, the exact relationship should be between user to user.
How can I make this relationship. I'm confused!
I've tried so far:
Model: User
public function dealersOfDistributor(){
$this->hasMany('App\DealersOfDistributor');
}
Model: DealersOfDistributor
public function user(){
return $this->belongsTo('App\User');
}
The DistributorsController
public function index()
{
$distributors=User::where('type', 'distributor')->get();
$dealers=User::where('type', 'dealer')->get();
$assignedDealers=DealersOfDistributor::all();
return view('distributors.index')->withDistributors($distributors)->withDealers($dealers)->with('assignedDealers', $assignedDealers);
}
In blade file: I've tried $assignedDealer->dealer_id->user->name. But It's showing error.
Model DealersOfDistributor:
public function distributorUser()
{
return $this->belongsTo('App\User', 'distributor_id', 'id');
}
public function dealerUser()
{
return $this->belongsTo('App\User', 'dealer_id', 'id');
}
than you just get the user's data from DealersOfDistributor model, call function dealerUser if you want get user's data from dealer_id, and call function distributionUser if you want get user's data from distribution_id
Controller:
public function index()
{
$assignedDealers=DealersOfDistributor::all();
return view('distributors.index',compact('assignedDealers'));
}
Blade get username:
#foreach($assignedDealers as $assign)
{{$assign->distributorUser->name}}
{{$assign->dealerUser->name}}
#endforeach

Laravel - two columns with relationship to the same column in another table

I set up a one-to-many Eloquent relationship between User and Credit
User
id | name
Credit
id | recipient | author | amount
where
recipient is user.id
author is user.id
In Laravel, the relationship for recipient is established:
class Credit extends Model {
public function user() {
return $this->belongsTo('App\User', 'recipient');
}
}
But how do I add the relationship for author as well?
I tried:
class Credit extends Model {
public function recipient() {
return $this->belongsTo('App\User', 'recipient');
}
public function author() {
return $this->belongsTo('App\User', 'author');
}
}
i.e. I changed user() into two functions: recipient() and author()
But I am getting Trying to get property of non-object, which I think means that using recipient() or author(), Eloquent is unable to "bind" it to my User model.
How do I get around this?
The problem is that you have a field called recipient and a relationship sharing the same name. Consider renaming one of them this is because laravel will use the field instead hence if you do
$credit->recipient->name
you can't access the user table since laravel will load the field. And the field does not have a property called name.
Earlier when the relationship was user() it worked. So consider finding a suitable name to user e.g credit_recipient()

Resources