I have 2 models : Album & Photo.
Album hasMany Photo and photo belongsTo('album','id');
Just Like:
class Photo extends Eloquent {
protected $table = 'photo';
public function album(){
return $this->belongsTo('album','id');
}}
and
class Album extends Eloquent {
protected $table = 'album';
public function photo()
{
return $this->hasMany('photo');
}}
i have no problem until i want to try select Album Name and show first photo on an Album.
I am trying this code:
<?php $albums= Album::get();?>
#foreach($albums as $album)
<pre>{{$photo = $album->photo->first()}}</pre>
#endforeach
and output :
{"id":1,"images":"1.png","album_id":1,"created_at":"2014-09-08 03:54:36","updated_at":"2014-09-08 03:54:36"}
{"id":3,"images":"3.jpg","album_id":3,"created_at":"2014-09-08 04:30:35","updated_at":"2014-09-08 04:30:35"}
it's mean i have 2 album and i already select first photo of each album.
and when i trying to call images attributes it's error:
echo "$album->photo->first()->images";
error :
It is likely that you have an Album in your database which does not have a Photo associated with it. So when you loop over your albums and echo {{ $album->photo->first() }}, it simply outputs null for any album that does not have a photo (because there is, obviously, no first()) without throwing an error. However, when you try to access the image property of the album that doesn't have a photo, you are trying to get a property of a non-object, i.e. you are asking for the image property of null. Hence an error is thrown.
You can resolve this by wrapping your output in an #if statement that checks to make sure a photo exists, before trying to access its image property:
#foreach($albums as $album)
#if (count($album->photo))
{{ $album->photo->first()->image }}
#endif
#endforeach
There is a shortcut for this, using blade's or syntax, which checks for existence before trying to echo the result. This allows you to remove the #if statement:
#foreach($albums as $album)
{{ $album->photo->first()->id or null }}
#endforeach
First of all, I would recommend when using Eloquent to retrieve all entries in a table, use ::all() instead of ::get(), as shown in Basic Usage. Not sure if it's causing the problem, but you may want to follow the docs.
Secondly, in relationship, the first parameter to hasMany and belongsTo should be the model class name. So it should be 'Album' and 'Photo', first letter capitalized.
Judging from you output, album_id seems to be the foreign key name. So in your Photo class, change the relationship into the following:
public function album(){
return $this->belongsTo('Album','album_id');
}
Just ran your code, the issue is that you did not define the primary key for you models. Laravel will assume you are using 'id' as the primary key, and if that's not the case, your relationship will break. And it's always better to explicitly define what the primary key is, so as to avoid confusion when foreign keys are involved. So please add to the model class:
protected $primaryKey = 'album_id';
You can revise your code and see if the error persists. It's not showing up in my end now.
Related
I hope someone can please help me here because this is doing my head in.
I have two models, Ingredient and Uom (unit of measure).
In Ingredient I have:
public function uom() {
return $this->belongsTo(Uom::class, 'uom');
}
Each ingredient will have only one unit of measure. The column uom in the database is the one that holds the id for the unit of measure.
In Uom I have:
public function ingredients() {
return $this->hasMany(Ingredient::class);
}
Each unit of measure could have many ingredients.
In the ingredients table migration I have set up the foreign key as follows:
$table->foreign('uom')->references('id')->on('uoms')->onDelete('cascade');
Could someone please tell me why in the below foreach I get
Trying to get property 'name' of non-object
The blade code:
#foreach ($ingredients as $ingredient)
<tr>
<td>{{$ingredient->name}}</td>
<td>{{$ingredient->uom->name}}</td>
<td>{{$ingredient->user->name}}</td>
</tr>
#endforeach
The $ingredient->user->name works perfectly referencing a column 'added_by' so I'm at a loss as to why uom doesn't work.
Thanks in advance for any help, I hope I'm just overlooking something stupid
The problem you have is that the attribute has the same name as the relationship method you have: uom. If you change the column name on the ingredients from uom to uom_id, and change the relationship method in the model so the line states the following:
public function uom() {
return $this->belongsTo(Uom::class);
}
This should fix your problem (plus the relationship works like Laravel is intended to work)
Laraval has two options: return the relationship (the uom method) or the attribute (which is an integer from the database). Apparently it returns the integer which isn't an object and thus has no method name.
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;
I'm quite new to laravel and I'm trying to understand the Eloquent Relations.
I've already read some answers and the documentation but I haven't found a simple case similar to mine.
I have two model with one-to-many relation.
Document Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Document extends Model
{
public function dossiers()
{
return $this->belongsTo('App\Dossier');
}
protected $table = 'documents';
protected $primaryKey = 'id_document';
}
Dossier Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Dossier extends Model
{
public function documents()
{
return $this->hasMany('App\Document');
}
protected $table = 'dossiers';
protected $primaryKey = 'id_dossier';
}
So there is an attribute "protocol" inside both table. Inside Dossier is an unique attribute, inside Document can be repeated because more documents may be part of same dossier with that protocol.
Let's suppose I have to create a Document Model. But I need an attribute "color" that already exists in a Dossier.
so:
I have a form for the document. That can set all attribute except
color (so it can create the protocol shared with Dossier)
I submit the form then check if exists a Dossier with that protocol
(that is not the primary_key)
If i find a Dossier with that protocol, I took the Color of that dossier and
I insert it in the Document Model.
I'd like to know how I should implement the second step.
At the moment I've wrote in the DocumentController:
$document = Dossier::where('protocol', '=', $request->protocol)->first();
and then
$document -> color;
But I fell that's not the way.
Thanks for any advice
I think you want to insert color in document from dossier table if protocol match. If i understand you correctly then you can write it like this.
$dossier = Dossier::where('protocol', '=', $request->protocol)->first();
$color = ($dossier) ? $dossier->color: 'defaultColor';
Now in your create document
$document -> create([
'color' => $color,
... other form data here
]);
Note: it is not good practice to use primary key field as id_document or id_dossier. Better you change these to id, otherwise your current relationship will not work. Default, laravel relationship assume id as primary key. If you want to use different primary key name then you need to pass that key name in relationship as a second parameter.
$this->hasMany('App\Comment', 'foreign_key', 'local_key');
https://laravel.com/docs/5.6/eloquent-relationships#one-to-many
There are manyway to write the relation code, one is as rkj said anad u did as well.
The other one which i personally prefer is
$this->hasManny(Comment::class,'foreign_key', 'local_key'); //This is only if you are not following laravel standard table syntex.
But if your local key is id and foreign key on another table is comment_id. Then you dont need to add foreign key and primary key. You can simply do like this
$this->hasManny(Comment::class);
For making query, You can simply do this
$dossier = Dossier::where('protocol', $request->protocol)->first(); //This will give object
You do not need = , if its other then that u need to add that. This way its looks much cleaner right?
Then to display you can simply do this $dossier->color
I have a table notices. Model for this table is Notice.php
In this table I have notice and id column.
I have fetched all notices from notices table and viewed in my view. Here is my controller code for fetching all notices.
public function index()
{
$notice = Notice::orderBy('id','desc')->paginate(5);
return view('teacher.notice')->withNotices($notice));
}
Here is my view code to show all notices.
#foreach($notices as $notice)
{{$notice->id}}
{{ $notice->notices }}
#endforeach
Now I want to put two button inside this foreach loop. One is to confirm and another is remove confirmation.
To store this confirmation data I have created another table named notice_confirmed_student and model for this table is noticeConfirmedStudent.php. In this table have three column:
id
student_id
notice_id
If a student click confirm then his id and notice id will be stored in this table. I have done this perfect. But my problem is, in the foreach loop it shows both two button (confirm and remove confirm) at a time. I want to show confirm button if user already not confirmed for this notice. If user already confirmed for that notice then it should show remove confirmation button.
Here I am giving my blade foreach loop again with button for better understanding. Bellow code is not perfect, I have just written those code to understand my question.
#foreach($notices as $notice)
{{$notice->id}}
{{ $notice->notices }}
<?php $student_id= "select student_id from notice_confirmed_student where notice_id=$notice->id"; ?>
#if ($student_id == $auth::user()->id)
<button>confirm</button>
#else
<button>Remove Confirmation</button>
#endif
#endforeach
Thanks in advance.
Few things are wrong/incorrect here, to make it clear,
Notice <> User relation is Many-Many and notice_confirmed_student is a pivot table. so user model should have relation,
public function confirmedNotices()
{
return $this->belongsToMany(Notice::class, 'notice_confirmed_student')
}
Then in for each loop you can check like,
if(in_array($notice-id, Auth::user()->confirmedNotices->pluck('id')->all())) {
// user confirmed
} else {
// user not confirmed.
}
if I correctly understand your issue, you need to check if record with given id exists notice_confirmed_student table, and then check in your loop. retrieve the confirmed students with your notices.
$notice = Notice::with('notice_confirmed_student_or_whatever_your_relation_method_called)')->orderBy('id','desc')->paginate(5);
then check in loop, if related attribute is not empty like you do in your view
#if($notice->my_attr && $notice->my_attr->user_id == \Auth::user()->id)
// do stuff
#else
// it doesn't has record
#endif
Am learning laravel and I encountered a problem saving data into my database from my form.
My instance
when a user tries to make a multiple purchase of products ie.when a user purchases more than one product,i wanted to save the names of products that belongs to the purchase user made into my 'PURCHASES' table having an 'ID' of '1'.
Names of product to be save;
1.productA
2.productB
3.productC
Codes
FORM IN MY VIEW
<input type='hidden' name='product_name'
#foreach($order as $order)
value='{{$order->product_name}}'
#endforeach >
MY purchase CONTROLLER
Saving the names;
$purchase = new Purchase;
$purchase->product_name = $posted['product_name'];
$purchase->save();
When i initiate the function i get an error exception reading 'Trying to get property of non-object' from my view from the line;
#foreach($order as $order)
value='{{$order- >product_name}}'
#endforeach >
How do i go about this problem?
There are a lot of strange things in your code unless I'm reading it wrong, but most likely when you're seeing that error in a view it's because you didn't pass that data into the view. Take this example:
Controller
public function showProducts() {
// assuming $order_array is a set of product IDs that is part of an order
$orders = array('products' => Products::whereIn('id', $order_array);
return View::make('your/view' compact('orders'));
}
I don't quite understand what you're trying to do but passing the object array 'orders' to the view allows you to then call your line:
#foreach($orders as $order)
code here
#endforeach