Check in relationship if a column is true, Laravel - 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;

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

Fetch data that don't exist in pivot table column - Laravel 6

I have two tables viz
1. users
columns: id, name
2. user_access
columns: id, user_id, user_access_id
user access is a pivot table that defines the relationship between users table and users table itself. For example, a user might have access to data of some other users.
I have defined this relationship in User model.
Now I want to fetch those user ids for a user which don't exist in user_access table.
For example, a user may have access to id 1 & 2 but he doesn't have access to id 3 & 4, so I want to fetch id 3 & 4 and not 1 & 2.
To achieve this I use whereDoesntHave eloquent but it's not working for relationship on the same tables and I get the following error
Facade\Ignition\Exceptions\ViewException
Call to undefined method Illuminate\Database\Eloquent\Builder::getRelated() (View: C:\xampp\htdocs\prd_tracker\resources\views\tracker\ticket\script.blade.php)
but it does work for different tables.
Here is my code
User Model
public function userAccess()
{
return $this->belongsToMany('App\User', 'user_access', 'user_id', 'user_access_id')->using('App\USER_ACCESS');
}
Logic
use App\User;
$user_id = Auth::user()->id;
//Get All Those Users Ids Which Does Not Belong To Auth User
$exception_user_ids = User::whereDoesntHave('users', function ($query) use($user_id) {
$query->where('user_id', $user_id);
})
->pluck('id');
The error may be in the User model.
The App\User model cannot belongsToMany() of itself...App\User.
I believe you may need a UserAccess model.
Try:
User Model
public function userAccess()
{
return $this->belongsToMany('App\UserAccess', 'user_access', 'user_id', 'user_access_id')
}
or try a hasMany relationship:
User Model
public function userAccess()
{
return $this->hasMany('App\UserAccess', 'user_id', 'id');
}
https://laravel.com/docs/7.x/eloquent-relationships#many-to-many
https://laravel.com/docs/7.x/eloquent-relationships#one-to-many

A department can belongsToMany, but a user can only belongTo department? How to pivot this correctly?

So im trying to figure out how to use pivot tables in Laravel. And I have tried to read and understand the documentation. And I cannot understand why a user just can't balongTo a "department". I don't want a user to belongToMany "departments".
Departments model
public function users()
{
return $this->belongsToMany(User::class, 'department_user', 'user_id', 'department_id');
}
And for the user model, I want something like
public function department()
{
return $this->belongsTo(Department::class);
}
But Laravel reports null. Because department_id doesn't exist in the users row? How can I reverse this pivot table lookup, with belongsToMany and belongsTo?
I think you're getting confused with your relationship types. If I understand you correctly:
A Department hasMany Users.
A User belongsTo a Department.
This one-to-many relationship type does not need a pivot table and can be written as such:
class Department extend Eloquent
{
public function users()
{
return $this->hasMany(User::class);
}
}
class User extend Eloquent
{
public function department()
{
return $this->belongsTo(Department::class);
}
}
This would require that the users table have a department_id foreign key.

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 hasManyThrough getting through another model

I have this 3 tables. I would like to get the employee name who created the client
I have tried this
class LeadsModel extends Eloquent
public function researcher_name()
{
$user = $this->belongsTo('users','id','user_id');
return $user->getResults()->belongsTo('employees','id','employee_id');
}
But it returns an error:
"message":"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'employees.employee_id' in 'where clause' (SQL: select * from `employees` where `employees`.`employee_id` in (4))"}}
when I switch the id and employee_id, it does not return any relationship for users and employees.
Basically, I need to get the clients with the employee's name who created it.
Assuming relationships:
Client belongsTo User
User belongsTo Employee
simply call this:
$client->user->employee;
Given your schema, here are the relations you need in order to get an Employee related to particular Client (through User):
// Client model
public function user()
{
return $this->belongsTo('User');
}
// User model
public function employee()
{
return $this->belongsTo('Employee');
}
then simply call this:
$client = Client::find($someId);
$client->user; // single user related to the client
$client->user->employee; // single employee related to the user
You might want to check if given relation exists first:
// just an example, don't write it this way ;)
if ($client->user) { // user is not null
if ($client->user->employee) { // employee is not null as well
$client->user->employee->name; // name = field on the employees table
}
}
You need a Has Many Through relation.
Add the relationship in your Employee's model called clients:
public function clients()
{
return $this->hasManyThrough('App\Client', 'App\User');
}
And then you can use it like below:
Employee::first()->clients()->get();

Resources