Relationship between table is not working - laravel

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

Related

Cross database many to many relationships in Laravel with Sqlite

In Laravel Framework 8.20.1 I have two models, User and Item, in two different SQLITE databases, with a many to many relationship.
The intermediate table, called item_user, in the same database as model Item.
I've setup the belongsToMany relatinoship like this in model Item
class Item extends Model
{
...
protected $connection = 'connection2-name';
public function users()
{
return $this->belongsToMany(User::class);
// I have done several tryouts
// OR return $this->belongsToMany(User::class, 'item_user', 'user_id', 'item_id');
// OR return $this->belongsToMany(User::class, 'sqlite-db2.item_user', 'user_id', 'item_id');
// OR return $this->belongsToMany(User::class, '/path/to/sqlite-db2.item_user', 'user_id', 'item_id');
// OR return $this->belongsToMany(User::class, 'connection2-name.item_user', 'user_id', 'item_id');
}
}
When I try to access Item with Users:
$item = Item::find($id)->with('users')->get();
I get an error that my intermediate table "item_user" doesn't exist.
General error: 1 no such table: item_user
As far as I have found in my search of the solution, the problem should be that Laravel assumes the intermediate table to exist in the same database as the target relation, so they suggest to add the db name in the belongsToMany, but even that did not solve my issue.
Do you have any hint to come out of this problem?
First of all you need to create a table item_users with fields user_id and item_id
Then use relation:
public function users()
{
return $this->belongsToMany(User::class, 'item_users');
}

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;

Eloquent relationship Laravel 5

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!

Laravel Eloquent all with relationship

How can I get all data from my tables with relationship in Laravel?
So, I have table like:
*users*
id
username
password
...
*address*
id
address
user_id
...
If I call my eloquent model with Address::all() I get response with user_id, and I want to make relationships for getting username.
I try to add:
public function users(){
return $this->belongsTo('Users', 'user_id');
}
And call with Address::with('users')->get(), but response is empty.
Is your user class called Users or User? Unless you override it, the default way that Eloquent deals with names can be found in the docs (source):
Note that we did not tell Eloquent which table to use for our User model. The lower-case, plural name of the class will be used as the table name unless another name is explicitly specified. So, in this case, Eloquent will assume the User model stores records in the users table. You may specify a custom table by defining a table property on your model
So I believe if you change your code in the Address model to:
public function users(){
return $this->belongsTo('User', 'user_id');
}
it will work since we have changed Users to User
You need to change
public function users(){
return $this->belongsTo('Users', 'user_id');
}
to
public function users(){
return $this->hasOne(Users::class, 'user_id');
}
or
public function users(){
return $this->hasMany(Users::class, 'user_id');
}
Alternative way!
class Users extends Model {
//override table
protected $table = 'users';
protected $primaryKey = 'id';
//Your other code here
}
and in Address Model add like this
public function users(){
return $this->belongsTo('App\Users', 'user_id');
}

Resources