Laravel Eager-loading works only when calling attribute - laravel

I've defined my Slot model to load the relations from User model like so :
public function userAssignedFull(): HasOne {
return $this->hasOne(User::class,'id','user_assigned');
}
('slots' table contains 'user_assigned' field by which I connect to User records on 'id')
The following code finds Slot model but without 'userAssignedFull'. I get only the user ID in 'user_assigned'.
$slot = Slot::with('userAssignedFull')->find($slot_id);
But calling this afterward returns me the wanted relation:
$fullUserModel = $slot->userAssignedFull;
Can anyone tell me what am I doing wrong ?

Builder::with() returns the Builder instance.
So you have to call $slot->userAssignedFull; to get the collection of data.
From the docs:
When accessing Eloquent relationships as properties, the relationship
data is "lazy loaded". This means the relationship data is not
actually loaded until you first access the property.
And this $slot->userAssignedFull; is your "first access the property".

Try this
$slot = Slot::where('id', $slot_id)->with('userAssignedFull')->first();
$slot->userAssignedFull;

Related

laravel prevent overload data on Auth::user()

My model User have some relation: profile, activites, etc...
on my controller i have this:
$user = Auth::user();
$user->load(['profile', 'activities']);
excpected result on my blade is that my variable $user is with my relationships and the Auth::user() data remain the users table data only;
i have a layout layout.blade.php and a view index.blade.php that extends my layout;
in my index i want to use the relation data and in my layout i want only the users data; but i always have the relation loaded from controller
If you load any relationship, laravel will add that relationship in your user object automatically.
If you don't want this and want the user only, you can duplicate the object first to another variable before loading any relation.
Second option, you can get the user again
If you want to have the same object but without the relationship you have multiple choices:
$user->unsetRelation('profile');//unset specific relationship on the $user Object
$user->unsetRelations();//unset all relationships on the $user Object
$userWithoutRelationships = $user->withoutRelations();//clone the current Object but without relationships

laravel/elequent - models and relations

I trying to learn laravel and to do some tests/demo apps. I've struggling now with laravel/eloquent tables relations. And I need advice.
I have 3 models [Application, Term, AppState] and their tables applications[id, terms_id, appStates_id, and other cols ], terms[id, startDate, endDate, ...], app_states[id, caption]
Application.php
public function term()
{
return $this->belongsTo('App\Term');
}
public function appState()
{
return $this->belongsTo('App\AppState');
}
in Term.php and AppState.php i have:
public function applications()
{
return $this->hasMany('App\Application');
}
How I can get let's say "caption"/"startDay"+"endDate" in blade for each application? I can get their ids $app->terms_id/$app->appStates_id in foreach loop, but i want get caption value from app_states table.
Has to be this relations also specified in migrations? In some tuts is mentioned, that is not needed in case i want to handle it only in laravel.
Thanks for advice
You can access a model's relationship values by calling the relationship method like a property.
$application = Application::find(1);
$application->term->startDate;
$application->term->endDate;
$application->appState->caption;
Also your relationship with AppState is wrong, since your foreign key doesn't follow a snake_case typing, you'll need to provide the appropriate key for it
public function appState()
{
return $this->belongsTo('App\AppState', 'appStates_id');
}
You might also want to check terms_id as well since the model name (Term) is singular but the foreign key is plural.
Has to be this relations also specified in migrations? In some tuts is mentioned, that is not needed in case i want to handle it only in laravel.
Well, yes, you don't need to if Laravel will only be the one accessing that database. But if any cases in the near future you decide to migrate to a different framework or use the same database in another application, it's better to include these relationships in the migration. Also a database administrator would probably cringe if you don't.
So provided your relationships are correctly setup, you can access them anywhere you have an instance of that model.
So for example, lets say you have passed a collection of applications to your view ($apps):
#foreach($apps as $app)
{{ $app->term->startDate }}
{{ $app->term->endDate }}
{{ $app->appState->caption }}
#endforeach
Important Note: We are accessing the Eloquent relationship using ->appState rather than ->appState(). The later is actually accessing a Query Builder instance and has some more advanced use cases

Relation multiple Models

long time i been not working with laravel, im strugling in getting some data.
Im trying to get all the bookmakers from a competition but is not getting:
db:
leagues:
-id
-name
league_bookmakers:
- id
- league_id
- bookmaker_id
bookmakers:
- id
- name
controller:
$example = \App\League::find(440);
dd($example->bookmakers());
Model League:
public function bookmakers()
{
return $this->hasMany(LeagueBookmaker::class);
}
When you call a relation method on a model ($example->bookmakers()), it returns the actual relation, allowing you to add additional constraints.
What you need to be calling is the 'dynamic property', which simply returns the data from the relation as-is:
$example->bookmakers // without the ()
What are you getting? Are you getting an empty collection?
As commented try doing this
dd($example->bookmakers);
Also, try doing dd($example) first and see if it has the bookmakers collection property in it.
When you make relation with league_bookmakers table, you will not get bookmakers data directly. In that case, you can define a belongsToMany Relation like below code -
public function bookmakers()
{
return $this->belongsToMany(Bookmaker::class, 'league_bookmakers','league_id', 'bookmaker_id');
}
It will return bookakers table info directly.

Laravel Backpack : Storing Belongs To Many relationships using custom view

I have a flight class and this flight has a custom view field like so:
This represents a belongs to many relationship which stores website_id / flight_id and pricing as pivot data in a pivot table.
The custom view uses JS to send this data back to the controller in this format:
{"1":{"price_adult":"434","price_child":"545"},"2":{"price_adult":"323","price_child":"324"},"3":{"price_adult":"434","price_child":"43"}}
Trying to send this data with the request doesn't create the relations fields, and because I do not have a flight ID at the point of creating this within the controller I can not loop this JSON to make the relations manually.
Can anyone point out what the best course of action is or if there is support for this? I took a look at the docs but they are woefully short and patchy in terms of being much help.
EDIT:
I should have said I can probably make this work using a custom name attribute on the model for the relation, then add a set mutator to loop this data and update the prices relation but I don't want to go down this route if there is support for this I am missing out of the box in backpack.
EDIT2:
Someone asked about the relation:
$this->belongsToMany(Website::class, 'website_pricing')->withPivot('price_adult', 'price_child');
This is working fine its not a problem with the relation working its how can I get backpack to store the data as a relation when the flight has no ID yet, or how can I pass the data I posted above in such a way that the backpack crud controller can handle it?
You may need to create a flight first, if no flight id is being provided. Can you explain the database relational structure more?
Basically thought I should post what I did because no one could provide an answer to this.
So basically you have to copy the store / update functions from the parent, changing a few lines.
$this->crud->hasAccessOrFail('create');
// fallback to global request instance
if (is_null($request)) {
$request = \Request::instance();
}
// replace empty values with NULL, so that it will work with MySQL strict mode on
foreach ($request->input() as $key => $value) {
if (empty($value) && $value !== '0') {
$request->request->set($key, null);
}
}
// insert item in the db
$item = $this->crud->create($request->except(['save_action', '_token', '_method']));
$this->data['entry'] = $this->crud->entry = $item;
// show a success message
\Alert::success(trans('backpack::crud.insert_success'))->flash();
// save the redirect choice for next time
parent::setSaveAction();
return parent::performSaveAction($item->getKey());
Basically any line which references a function in the parent class using $this->method needs to be changed to parent::
This line is what I used to submit the relations JSON string passed to the controller as relations $item->prices()->sync(json_decode($request->input('prices'), true));
This is done after the line containing $item = $this->crud->create as the item id that just got stored will be available at that point.

Laravel 5.5 retrieving null by nested relation

I have 3 databases:
Routes:
id
name
Rates:
Id
Route_id
Car_id
Cars:
id
name
My model for routes
public function rates()
{
return $this->hasMany('App\Rate', 'route_id');
}
My model for rates
public function car() {
return $this->belongsTo('App\Car','car_id');
}
Now I need to access the car relation, but when I do
return $this->route->with('from','to','rates.car')->paginate(74);
I get null for the car relation
{"id":1,"from_id":1,"to_id":2,"distance":400,"created_at":null,"updated_at":null,"from":{"id":1,"name":"\u0410\u043a\u043a\u043e","created_at":null,"updated_at":null,"lat":32.93310000000000314912540488876402378082275390625,"long":35.0827000000000026602720026858150959014892578125},"to":{"id":2,"name":"\u0410\u0440\u0430\u0434","created_at":null,"updated_at":null,"lat":31.261399999999998300381776061840355396270751953125,"long":35.21490000000000009094947017729282379150390625},"rates":[{"id":1,"route_id":1,"car_id":1,"rate":1123,"night_rate":1391,"car":null},{"id":5551,"route_id":1,"car_id":2,"rate":1123,"night_rate":1391,"car":null},{"id":11101,"route_id":1,"car_id":3,"rate":1123,"night_rate":1391,"car":null},{"id":16651,"route_id":1,"car_id":4,"rate":1123,"night_rate":1391,"car":null},{"id":22201,"route_id":1,"car_id":5,"rate":1123,"night_rate":1391,"car":null},{"id":27751,"route_id":1,"car_id":6,"rate":1123,"night_rate":1391,"car":null},{"id":33301,"route_id":1,"car_id":7,"rate":1123,"night_rate":1391,"car":null},{"id":38851,"route_id":1,"car_id":8,"rate":1123,"night_rate":1391,"car":null}]},
From my understanding you are trying to access a Car model through a Route model.
A couple of things I noticed that should help you find a solution.
First off I think the inverse relation you are supposed to use the belongToMany() function instead.
public function car() {
return $this->belongsToMany('App\Car','Rates'); // Perhaps call the table something like routes_cars to more clearly define it's a pivot table
}
Next I see you are trying to use model functions within the context of $this(). I assume you are doing this in your model? That logic should be in a controller, that might cause some undesired results but I'm not entirely sure. Also it looks like your parameters are incorrect when using with(). You use the function name that you defined in belongsToMany()
App/Route::with('car')->paginate(74);
With the correct relationships setup you rarely need to worry about the pivot table. If you are going to add extra information in the pivot table there are laravel functions to help you do that in the documentation.

Resources