How can I return Many to One relation data joined with One to One data? - laravel

I have a question concerning Laravel schema.
Was that a bad idea to create an additional one-to-one table user_description, to store additional user data? Here is my schema:
For example now I don't know how to use eager loading to get user_photos if at first I retrieve topics' data.
Here is the code I use to get the last topics with user data:
return Topic::with('blog', 'user')->orderBy('topics.id', 'DESC')->get();

assuming your User-Model has a relation description() I suppose this does what you want.
return Topic::with('blog', 'user', 'user.description')->orderBy('topics.id', 'DESC')->get();
the concept is called sth. like eager loading of nested-relationships and is documented at the bottom of the eager loading documentation of laravel

Related

Can this block of code of mine can be improved

[This is to populate data from two tables that one has two foreign keys from the same column as reference on the other table]
https://i.stack.imgur.com/D8fiv.png
[This is my schema for the table with the foreign key]
https://i.stack.imgur.com/eYDL0.png
This is written in laravel and it is working however i have an itchy feeling that this is wrong
As someone else has commented, you should put the code in your question. More context might also be necessary as it's not clear what you are trying to return from your view(). Are you returning $citizen, $family, or both? It would also be helpful to include what version of Laravel you are using. I'll assume you are using the latest Laravel 8.
Your code should work but you are making more work for yourself if you don't utilize Laravel's relationships. If you do, all the query stuff you have in your code can be reduced to just a few short lines of code such as this:
public function view(Citizen $citizen)
{
$citizen->load('family');
return $citizen;
}
Database Migration
You can shorten your migration by using foreignId(). See docs for details
https://laravel.com/docs/8.x/migrations#foreign-key-constraints
Before:
$table->integer('client_id')->unsigned();
$table->foreign('client_id')->references('id')->on('citizens');
After:
$table->foreignId('client_id')->constrained();
Route Model Binding
I'm assuming your view() method is in your controller and is called from a route. Since the one parameter required is the client's id, you can use Route Model Binding and skip fetching the client from the database.
https://laravel.com/docs/8.x/routing#route-model-binding
public function view(Citizen $citizen)
{
// your code
}
Relationships
You seem to have relationships set up but you aren't using them to load data. You should be able to load the related objects without any manual queries.
If you have a belongsTo(One to Many) relationship on the Citizen model to the Family model, you can load it like this:
$citizen->load('family');
or just use it like this
$relationship = $citizen->family->relationship;
I don't know what the relationships between your models are but you should read up on the different relationship types in the docs.
https://laravel.com/docs/8.x/eloquent-relationships

Laravel Eager loading of a relationship bettween two models causes a relationship between other models return wrong results

I have two Eloquent models named Question and Answer with one to many relationship between them (one question has many answers). The hasMany relationship in Question.php is called answers.
I also have a User and a Company model with a many to many relationship between them which uses a pivot model, defined this way:
User.php
public function companies()
{
return $this->belongsToMany(Company::class)
->using(CompanyUser::class);
}
Company.php
public function users()
{
return $this->belongsToMany(User::class)
->using(CompanyUser::class);
}
When I retreive a question and lazy load its answers:
Question::find(58)->answers;
Everything is okay. The problem comes when I use eager loading:
Question::with('answers')->get();
Something strange happens. In the answers() relationship method of the Question model, I need to get the current user's first company in order to modify the relationship:
auth()->user()->companies->first();
Most of the users in my application have one company attaches to them, when using eager loading though auth()->user()->companies returns not one, but 134 companies even though in the database I have only 5 companies and the current user belongs to only one. When I dumped the contents of the auth()->user()->companies collection I saw that the first company model is exists 130 times and the other 4 companies are also included.
This happens only in the answers() method and only when using eager loading. Any ideas why?
Environment:
Laravel version: 6.20.6
PHP version: 8.0.1
Apache: 2.4.26
DB: 10.1.27-MariaDB
I think you need to get more information on the problem. What I normally do is insert ddd() and check the queries tab to see what queries Laravel is using to get the data. This might shed some more light on the problem.

How do the "has" and "whereHas" methods work in Eloquent?

I have a relationship defined between users and permisson, a user can have many permissions.
When I use "with" I get the data normally.
$user->with('permisson')->get();
I get the user with their permissions.
When I use "has" it only returns the user.
$user->has('permission')->get();
For what I've read, I should get the permissons if the user contains at least one permission.
I am using Postgres driver.
with is used for eager loading a relationship. You'd use it to fetch all of the specified relationships for each model (individually, or in a collection).
has is for using the relationship as a constraint or filter. As you said, using something like has('permission') will add a constraint to the query that says "only get Users that have at least one permission". This does not automatically load the relations like with(), it only creates the constraint.
You can combine the two if you want to take advantage of both the constraint and eager loading the results.
User::has('permission')->with('permission')->get();
Seems a bit redundant, I know.
From laravel docs:
If you wish to limit your results based on the existence of a relationship, you should use the has method. For example, if you want to retrieve all blog posts taht have at least one comment, yo may pass the name of the relationship to the has and orHas methods:
$posts = Post::has('comments')->get();
So, when you use the has method, it will not return the relationship, but just the post models which has at least one comment.
The whereHas and orWhereHas methods allows you to add customized constraints to a relationship constraint, such as checking the content of a comment (using the laravel example):
$posts = App\Post::whereHas('comments', function (Builder $query) {
$query->where('content', 'like', 'foo%');
})->get();
When you use the with method, you are loading the realtionship with the model:
$user->with('permission')->get()
This code will load the user and the permission relationship, while this one
$user->has('permission')->get();
will load the user who has some permission.
Hope it helps.

Unexpected Results in Laravel Eager Loading With Constraints

I have two tables: assets and asset_classifications. The tables have one-to-many relationship, where an asset has one asset classification, and asset_classifications have many assets.
I'm trying to run a query to get all assets which has an asset_classification name of "laptops", for example. I'm trying to do this by running this eager load with a constraint:
$laptops = Asset::with(array('classification'=>function($query){
$query->where("name","=","laptops");
}))->get();
foreach($laptops as $laptop){
echo $laptop->serial_number."<br/>";
}
name is a column from asset_classifications table. I already formed the one-to-many relationship by setting up the needed methods for my Asset and AssetClassification models.
The problem with my eager load is that it gets all the assets, seeming to ignore my eager loading constraint which tries to get only the "laptops". I think the problem is in my code or my understanding of eager loading, but I don't know which. I'm still new to this and I hope someone can help me.
with is used to filter related models, while you need whereHas for filtering main queried model by related table constraints:
$laptops = Asset::whereHas('classification', function ($query) {
$query->where("name","=","laptops");
})->get();

Conditional Relationship in laravel Eloquent

Let I have 3 table named user, admin, post
My post table structure is
-id
-poster_id
-poster_type //if value is 1 then poster_id will be releted with user table. if value is 2 then poster_id releted with admin table.
Now How writte belongsTo relationship with two table based on poster_type value
I want to do in Post model like this
public function Author(){
return $this->belongsTo('User', 'poster_id')->where('poster_type', '1') //poster_type is the field of post table.
}
First of all, you are talking about a Polymorphic relationship, supported by eloquent. You should take a look at the documentation.
http://laravel.com/docs/eloquent#polymorphic-relations
Second, you are mixing Eloquent relationships with special data recovery functions, and that's something you should avoid. I suggest you split the relationship itself from the data recovery function.
Also, if you want to go one step further, keep the relationship in the model, and split the data recovery functions into a repository object.

Resources