Eloquent ORM optional Relationship - laravel

just a short question, I'm new to Eloquent and the relationships.
I want to keep my database clean so I created a User-Model and a Administrator-Model.
Now I'm stucked with the relationship... What I wanna do is the following:
On the users-table I have an attribute called account_type.
If that one is set to admin or administrator I want to "implement" the Administrator-Model to the User-Model.
Am I doing a totally wrong approach here or is there a easy "laravel-style" solution for this?

Class Administrator cannot be implemented in User, because it's not an interface, If you want to use Administrator class, make a relation in User model
public function admin()
{
return $this->hasMany('Administrator');
}
then,
$users = User::whereHas('admin', function($q) {
$q->where('account_type', 'administrator'); // or admin
})->get();
make belongsTo relation in Administrator if you want
reference link: Eloquent ORM

Related

Laravel eloquet check non existing many to many relation

I'm having trouble to write query in laravel eloquent ORM.
I have a proyect table, where you can assign users, in a many to many relationship
In the view to asign users, I have a selector, but I want to show only the users not already assigned to the proyect and checking also that the user belongs to the company that created the proyect (user.company_id=proyect_id)
In a normal query should me something like this, having $company_id and $proyect_id from the controller.
select * from users u left join proyect_user pu on u.id=pu.user_id and
pu.proyect_id = $proyect_id where u.company_id=$company_i and
proyect_id is null;
The query works, but I would like to use Eloquent. ¿Any idea how to do it?
It depends on how you declared the relationship in the User model. But I would do something like this:
$users = User::whereHas('company', function ($query) use ($companyId) {
$query->where('id', $companyId)
})->whereDoesntHave('proyects', function ($query) use ($proyectId) {
$query->where('id', $proyectId);
})->get();

create whare clause on model attribute

How to create where clause on laravel model attribute
I have the following relation between user and books. where user hasMany books and the book model belongs to single user
I want to select all books with pages > 100 that belongs to user_id = 2
I use laravel 5.2 with mysql and defined a model for User and another model for Book
When I want to get all books for specific user, I user
return User::find(2)->books;
and this works fine. But I want to get the books where pages > 100. I use:
return User::find(2)->books->where([['pages', '>', 100], ['chapters', '>', 3]]);
but doesn't work
User model:
class User extends Authenticatable
{
public function books()
{
return $this->hasMany('App\Book');
}
}
Book model
class Book extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
I expect to get all the books with user_id = 0 and pages > 100 and chapters > 3
You'll want to access the relationship method books(), not the property books. Some quotes from the documentation:
Querying Relations
Since all types of Eloquent relationships are defined via methods, you may call those methods to obtain an instance of the relationship without actually executing the relationship queries. In addition, all types of Eloquent relationships also serve as query builders, allowing you to continue to chain constraints onto the relationship query before finally executing the SQL against your database.
Relationship Methods Vs. Dynamic Properties
If you do not need to add additional constraints to an Eloquent relationship query, you may access the relationship as if it were a property.
Example solution:
return User::find(2)
->books()
->where([['pages', '>', 100], ['chapters', '>', 3]])
->get();
Note that we're using books() to access the HasMany relationship, and using the where() query builder method on it to create a constraint. Then, in order to complete and execute the query, we call get() at the end. If you don't, you'll just return the daisy chained query builder.
Your previous code might not error, because the value returned from User::find(2)->books will be a Collection object, which actually has a where() method. It just likely didn't have any matches because of the array format you passed.
To add where clouses on related models, we can use whereHas() function.
Since you want Books, Start from Book model.
$books = Book::where([
['pages', '>', 100],
['chapters', '>', 3],
])
->whereHas('user', function($query) {
$query->where('id', 2);
})
->get();

Is it possible to dynamically set model for Eloquent Relationships?

I have 2 user roles. In database I have own profile tables for both of roles ( model_profiles and client_profiles). Is there any way to set related Profile model dynamically? I've tried this:
//User model:
public function profile(){
return $this->role == 'model' ? $this->hasOne('App\Models\Model\Profile') : $this->hasOne('App\Models\Client\Profile');
}
But in this case I can't use some Eloquent methods like User::with('profile')->whereIn('id', [1,2,3])->get(); because $this->role is null until user model is loaded.
Is there any way to use Profile model based on user role and don't lose any Eloquent query methods?
You can use Polymorphic relationships (More Information)

Is there an Eloquent way of doing a leftjoin in Laravel 5.4

Is there a eloquent way to do a left join in Laravel?
We'd like to get all games and fill in the progress for each one if it exists in user_games.
Right now we've written the following solution, however this isn't eloquent at all, which we like it to be.
public function usergames($user_id) {
return DB::table('games')->leftJoin('user_games', function ($join) use ($user_id) {
$join->on('user_games.game_id', '=', 'games.id')->where('user_games.user_id', '=', $user_id); })->get();
}
DB model:
Thanks in advance!
A way to do this without you actually writing a left/inner join is to use the eloquent relationships.
In your case you will have 2 model classes: User and Game
class User extends Model {
public function games() {
return $this->belongsToMany(App\Game::class);
}
}
Now, you can access the user's games like so:
$user = App\User::find($user_id);
$usergames = $user->games; // Illuminate\Support\Collection
If you want to get a list of users with games, then look into eager loading. That would look something like this:
User::with('games')->get();
This way, Eloquent will know to lazy load the relationship meaning it will only run 2 queries. One to grab the users. and one to grab the games associated with the user, and then make them available for you in the 'games' property of the user object.

How to query relationships in Laravel 4 with Eloquent?

Coming from CodeIgniter's Datamapper ORM I am still trying to get my head around Laravel's Eloquent ORM.
Given the fact that I have an ACCOUNT and a USER table (simplified):
ACCOUNT
- id
- name
USER
- id
- account_id
- username
One account has many users. One user belongs to one account. So we're dealing with a one-to-many relationship. Everything is already set-up in the models.
In CodeIgniter's Datamapper I would have done the following to get the user from any given ID and at the same time check if that user is related to the current account:
$u = new User();
$u->where('username', $username);
$u->where_related_account('id', $account_id);
$u->get();
if ( ! $u->exists()) exit; // or do something...
// otherwise continue to use the "$u" user object
This syntax is very logical and easy to understand. In Eloquent I have a hard time to achieve the same with a similar easy syntax. Does anyone have any suggestions?
Very simply (ignoring the relationship between the user and the account), it could just be:
$u = User::where('username', $username)
->where('account_id', $id)
->get();
That will return you your user's details.
Otherwise, assuming that you have your User and Account classes and DB tables are set up correctly (as per the Laravel docs), you should be able to just do:
$user_exists = Account::find($account_id)
->users()
->where("username", "=", $username)
->first()
->exists;
if ($user_exists)
{
doThings();
}
If you've correctly set up your models and database tables (as #msturdy said) you should actually be able to return your user account by simply going:
$user = User::whereUsername($username)
->first(); // or User::where('username', $username)->first();
if ($user) {
$account = $user->accounts()
->whereId($account_id)
->first(); // or $user->accounts()->where('id', $account_id)->first();
}
This gives you the ability to access the user and account models
you could even extend your User model to include the following methods:
class User extends Eloquent {
...
public static function byUsername($username) {
return static::whereUsername($username)->first();
}
public function getAccount($id) {
return $this->accounts()->whereId($id)->first();
}
...
}
and then simply go
$user = User::byUsername($username);
if ($user) {
$account = $user->getAccount($account_id);
}
which might be better for you if you are using the code in multiple controllers.

Resources