Laravel Relationships can't access - php

I have 3 models: User, A, B and C.
User.php
public function a()
{
return $this->belongsTo('App\A');
}
A.php
public function b(){
return $this->belongsTo('App\B');
}
B.php
public function cRelation(){
return $this->hasOne('App\C');
}
Then, i execute my query and load the relationship
$tests = User::all();
$tests->load('a.b.cRelation');
Now, in my view file, if i print this:
#foreach($tests as $test)
{{$test->a->b}}
#endforeach
I can see my c_relation magic property as expected.
But if i try to access it nothing is printed.
Where am i wrong? Why if i print the parent object ($test->a->b), i can see the property but i can't print it?

Here's what's happening...
When you just print a model in your template with {{ $test->a->b }}, the model is converted into JSON to make the output more readable.
When converting a model to JSON, Eloquent by default changes the relationship names from camelCase to snake_case.
However when you access a relationship from the model, you always use the method name so in that case {{ $test->a->b->cRelation }}

Related

get field value from eloquent relationship

I have this relationship on eloquent
public function Manufacturer() {
return $this->hasOne('App\Models\ManufacturerModel', 'id')->select('name');
}
And this returns correctly the manufacturer name:
{"id":1,"serialnumber":"123_1","buydate":"2018-01-26 00:00:00","offservice":null,"deleted":"0","manufacturer":{"name":"HP"}}
I want to retrieve the name not as JSON object but as a string
{"id":1,"serialnumber":"123_1","buydate":"2018-01-26 00:00:00","offservice":null,"deleted":"0","manufacturer":"HP"}
The best way to define the relationship is:
public function Manufacturer() {
return $this->hasOne('App\Models\ManufacturerModel', 'id');
}
Then you can get the manufacturer name this way:
$your_object->manufacturer->name;
Or adding a wrapper method:
public function ManufacturerName() {
return $this->manufacturer->name;
}
Notice that when you refer to the relationship without parenthesis the query is executed and what you are accessing is the result. If you don't want the entire record to be queried you can do this:
public function ManufacturerName() {
return $this->manufacturer()->select('name')->get()->name;
}
By accessing the relationship with parenthesis you are getting the relationship definition and you can modify it before executing the query.
Not directly but you can achieve the functionality using a little bit trick of php, for example, if you would like to use it in string context as given below:
// {{ $someModel->manufacturer }}
echo $someModel->manufacturer; // or echo Manufacturer::find(1);
Then you can do it using the __toString magic method in Manufacturer model as given below:
public function __toString()
{
return $this->name;
}
In this case, even on json_encode($manufacturer) will give you just name so why don't you just use $model->manufacturer->name;

Laravel get record from database in blade view

I would like to known how to get data from database in blade like from User table:
{{ Auth::user()->name }}
I have table user_settings
I would like to get record from this table by logged user id like this:
{{ UserSettings::user()->my_field }}
How can I do that?
Try this on your blade view
{{ \App\UserSettings::where('user_id',Auth::user()->id)->first()->my_field }}
In default, model file is inside App folder.
Such direct access to database table is not preferred though, you can return this as a variable from controller function like,
$field = \App\UserSettings::where('user_id',Auth::user()->id)->first()->my_field;
return view('view_name',comapact('field'));
and use in blade like
{{$field}}
Another good way is posted by Orkhan in another answer using eloquent relationship.
Hope you understand.
You need to retrieve the UserSettings associated to the authenticated user:
UserSettings::where('user_id', Auth::id())->first()->my_field
You can defined a method named current() to return that for you.
class UserSettings extends Model
{
public static function current()
{
return UserSettings::where('user_id', Auth::id())->first()
}
}
Then use:
UserSettings::current()
On the other had it would better to use one-to-one relationship on user model:
class User extends Model
{
public function settings()
{
return $this->hasOne('App\UserSettings');
}
}
Then use:
Auth::user()->settings->my_field

use QueryScope in Blade template

I have define scope in model like this
class Station extends Model {
protected $primaryKey = 'st_id';
public function scopeByDid($query)
{
return $query->groupBy("st_did");
}
}
I can call byDid from controller but I cannot get it through blade template like this
#foreach ($river->stations->byDid as $didType)
....
#endforeach
how do I get it. Appreciate your response. Thanks
If you're getting a relationship as an attribute (without () at the end) it means the relationship will have already been retrieved before the scope.
To get your code to work you will just need to change your foreach to:
#foreach($river->stations()->byDid()->get() as $didType)
Hope this helps!

Laravel 5 model object retrieval

I am new to Laravel 5 and was wondering how model object retrieval works.
For instance I have a separate table that is referenced by another table and I want to get the records from that.
Item Table
Category Table
I was trying to extend the User model
Class Item extends Model {
public function getCategory(){
$category = Category::find($this->category_id);
return $category;
}
}
So when I try to access the object retrieved in my view,
{{ $item->getCategory()->name }}
I get the error
Undefined property: Illuminate\Database\Eloquent\Builder::$name
What am I doing wrong? And what is the best practice in doing this? I used to do this in Symfony and it works so I was wondering how its done in Laravel.
Any help and input would be greatly appreciated.
Thank you all.
As stated in the docs here's how I did it
Class Item extends Model {
public function category()
{
return $this->hasOne('App\Category', 'id', 'category_id');
}
}
And accessed the object in the view this way
{{ $item->category->name }}

Laravel 5 - using dynamic properties in view

I have a dynamic property user in my model:
class Training extends Model
{
...
public function user()
{
return $this->belongsTo('App\User');
}
}
And I can easy get username in controller like this:
Training::find(1)->user->name
But I don't know how to perform the same in view. I tried this:
Controller:
return view('training/single', Training::find(1));
View:
{{ $user->name }};
but without success, I'm getting error Undefined variable: user. So it's look like I can't access dynamic property in view.
Any idea how can I use dynamic property in views?
I fear that's not really possible. There's no way to set the $this context in your view to the model. You could convert the model into an array with toArray() but that would include the related model and you would have to access it with $user['name'].
I personally would just declare the user variable explicitly:
$training = Training::find(1);
return view('training/single', ['training' => $training, 'user' => $training->user]);
Use eager loading
return view('training/single', Training::with('user')->find(1));

Categories