Understanding Eloquent One-to-many Relationships - laravel

I'm trying to understand Eloquent relationships but it seems I'm missing something in understanding it. I have:
A Meeting produces many Documents.
A specific Document can be produced for one Meeting.
Thus a one to many relationship. I am trying to display the 'meeting_name' in the Document details table but get this error:
Trying to get property 'meeting_name' of non-object (View: C:\wamp64\www\yajra_contact_system\resources\views\documents\index.blade.php)
Here is my code.
Please please explain with code solution:
app\Document.php File:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Document extends Model
{
protected $fillable = [
'document_name',
'document_desc',
];
public function meeting(){
return $this->belongsTo(Meeting::class);
}
}
app\Meeting.php File:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Meeting extends Model
{
protected $fillable = [
'document_id',
'meeting_name',
'meeting_desc',
'room_no',
'no_of_invitees',
'comments'
];
public function documents(){
return $this->hasMany(Document::class);
}
}
app\Http\Controllers\DocumentsController.php File:
namespace App\Http\Controllers;
use App\Document;
use App\Meeting;
use Illuminate\Http\Request;
class DocumentsController extends Controller
{
public function index()
{
$documents = Document::all();
$meetings = Meeting::all();
return view('documents.index', compact('documents', 'meetings'));
}
}
resources\views\documents\index.blade.php File:
#foreach($documents as $document)
<tr>
<td>{{$document->id}}</td>
<td>{{$document->document_name}}</td>
<td>{{$document->document_desc}}</td>
<td>{{$document->meetings->meeting_name}}</td> <!-- ERROR IS HERE -->
</tr>
#endforeach

you have many problems in your code:
first: in order to use the relation ... you have to load it first ...
loading relation done by using with('relationName') method ...
in index:
$documents = Document::with('meeting')->all();
second:
<td>{{$document->meetings->meeting_name}}</td> <!-- ERROR IS HERE -->
the relation is named meeting without s .. not meetings ...
third:
it's pest practices to provide foreign key in relation:
in Meeting model
public function documents(){
return $this->hasMany(Document::class,'meeting_id');
}
in Document model:
public function meeting(){
return $this->belongsTo(Meeting::class,'meeting_id');
}
please make sure you have a column meeting_id in your documents table referenced as foreign key to id in meetings table
more details about loading relation in:
https://laravel.com/docs/7.x/eloquent-relationships#eager-loading

So you have your tables mixed up.
You have a single record per meeting yet you have a document_id in your meetings table which you would need to duplicate meeting record for each document.
Remove the document_id from your meetings table
Add a meeting_id to your documents table
remember to update your models fallible array else you wont get the new columns in the collection.
This should fix your problem as your relationships are correct.

Related

Laravel Polymorphic Relationships - Return child with parent

I have a model Team with has a polymorphic relationship with Marketcenters Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
public function teamable()
{
return $this->morphTo();
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Marketcenter extends Model
{
public function teams()
{
return $this->morphMany('App\Team', 'teamable');
}
}
I need to retrieve all teams for one or any Marketcenter so I can list all Teams and to which Marketcenter they belong.
So I execute the following code and I get a collection od Teams for the Market Center in query:
$marketcenters = Marketcenter::where('id', $request->user()->marketcenter->id)->with('teams')->get();
foreach($marketcenters as $marketcenter) {
dd($marketcenter->teams);
}
But my problem appears when I want to retrieve each Team with their corresponding Market Center:
$marketcenters = Marketcenter::where('id', $request->user()->marketcenter->id)->with('teams')->get();
foreach($marketcenters as $marketcenter) {
dd($marketcenter->teams->marketcenter->mc_name);
}
Property [marketcenter] does not exist on this collection instance.
How can I retrieve parent data to child record in a Polymoprphic relationship?
Regards
Try querying for teams instead of the market center:
$teams = Team::whereHas('teamable', function ($q) {
$q->whereKey(request()->user()->marketcenter->id);
})->get();
Also, from the Laravel docs:
You may also retrieve the owner of a polymorphic relation from the polymorphic model by accessing the name of the method that performs the call to morphTo.
// This gets the marketcenter
$team->teamable
my question is why you want to access "marketcenter" via team model like $marketcenter->teams->marketcenter->mc_name instead you can directly use $marketcenter->mc_name in the for loop as both would return you the same object.
If you still need it than you have to have another foreach loop for martketcenter->team as you have morphMany so it would return you collection object from team model if you want marketplace than you have to call teamable function that would return the object of morphed model which may be Marketcenter or may not be depending on the morphed model attached to that record

Laravel - Illegal offset type when accessing property on OneToMany relationship

I'm learning how to use laravel and relationships. I'm having trouble accessing data from a hasMany relationship, I understand this might be a silly question. This might be a duplicate question, but I didn't find any specific answer like this.
I have two models, a salesman table and a prices table table. One salesman has many prices tables, so it's like this:
On Salesman model
<?php
namespace App\Pedidos;
use Illuminate\Database\Eloquent\Model;
class Vendedores extends Model
{
protected $connection = 'Pedidos';
protected $primaryKey = 'CD_VENDEDOR';
public function TabelaDePreco() {
return $this->hasMany('\App\Pedidos\TabelaDePreco', 'CD_VENDEDOR', 'CD_VENDEDOR');
}
}
On the prices table model
<?php
namespace App\Pedidos;
use Illuminate\Database\Eloquent\Model;
class TabelaDePreco extends Model
{
protected $connection = 'Pedidos';
protected $primaryKey = ['CD_VENDEDOR', 'CD_PRODUTO', 'CD_ESTADO'];
public function Vendedores() {
return $this->belongsTo('\App\Pedidos\Vendedores', 'CD_VENDEDOR', 'CD_VENDEDOR');
}
}
On the Controller
public function index()
{
$vendedores = Vendedores::all();
return view('pedidos.tabeladepreco.index')
->with('title', 'Tabela de preços')
->with('vendedores', $vendedores);
}
On the view, this will return TabelaDePreco model
#foreach($vendedores as $vendedor)
#foreach ($vendedor->TabelaDePreco as $tabela)
{{ dd($tabela) }}
#endforeach
Here is a print from the code above:
TabelaDePreco model
As you can see, data is loaded on the $tabela variable.
If I try to print, on the view, {{ $tabela->NR_LIMITE1 }}, I get the illegal offset type error. How do I access this attribute since data is loaded when using dd()? I've tried $tabela['NR_LIMITE1'] but with the same error.
What am I doing wrong?
Best regards.
EDIT:
As pointed by Jonas on the comments, Laravel won't support relationships when one of the tables has composite keys. Back to migrations.
You need to eager load your relation:
$vendedores = Vendedores::with('TabelaDePreco')->all();
return view('pedidos.tabeladepreco.index')
->with('title', 'Tabela de preços')
->with('vendedores', $vendedores);
It may also happen that $vendedor->TabelaDePreco is not defined if there is not TabelaDePreco associated with the $vendedor. Try adding a isset(). Also thing about pagination if you have many entries.

Hasmany with child of child in laravel 5.5

I have 3 tables.
shops
shop_foods
foods
I need to fetch foods table data when I create hasmany relation with shops_food and store.
$this->hasMany('App\Diet\ShopFood', 'shop_id', 'id');
Please, show your code so we can know what are you trying to do.
But what I can see here is that you have a wrong relationship.
Why are you assigning hasMany in a Many to Many relationship?
In your Shop Model you can make a foods relationship with:
$this->belongsToMany('App\Diet\Food);
Then you can retreive you food when calling
$shop->foods
And the shop_foods with the Pivot property
If i understand correctly you want to get foods when you call shops->shop_foods. if is that
//first you call your shops as you want.
Shop::with(['shops_food' => function($query){
//the 'shops_food' relationship should be called within an array
//this way you could query the relationship as the eloquent model.
//that way you could call the 'foods' relationship inside the shops_food relationship.
$query->with('foods')
}])
...
Note that you must have the relationship declared in shop and shop_foods models
lets your models are like these
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Shop extends Model
{
//
public function shops_food()
{
//shop_id is the foreing key inside your shop_foods table
return $this->hasMany('App\ShopFood','shop_id');
}
....
}
then ShopFood Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ShopFood extends Model
{
//
public function foods()
{
//shop_food_id is the foreing key inside your foods table
return $this->hasMany('App\Food','shop_food_id');
}
....
}
This reads as if you want
public function foods() {
$this->hasMany('App\Diet\Food');
}
in your ShopFood model and in your Shop model
public function shopfoods() {
$this->hasMany('App\Diet\ShopFood')->with('foods');
}
You can also make 2 separate relations in the Shop model:
public function shopfoods() {
$this->hasMany('App\Diet\ShopFood');
}
public function shopfoodsWithFoods() {
$this->hasMany('App\Diet\ShopFood')->with('foods');
}
So that way you can use whatever you need at that moment.
But the whole thing is really not clear...
I am not even sure how the 3 table are connected, so the hasMany are just guesses.
Nevertheless you can just go with the "with" function.
PS
There is also the possibility to just declare
protected $with = ['foods'];
in your ShopFood model, if you ALWAYS want those 2 connected. It's all in the documentation.

Laravel Eloquent polymorphic relationships to model hierarchy/inheritance

I am modelling a report which depending on its type (missing person, wanted, etc) could contain different fields but each type shares a number of fields. This I think is what differentiates this question from say: this question where the fields are common across all types.
At the moment I have created a report model with an integer field indicating its type which references a type table. The advantage is that this is an easy model to understand and implement. It means that I can also easily search for objects. On the other hand, this means that some fields do not make sense for some models and thus are always null. As I add fields unique to the individual types I end up with many columns in the table of which many are null.
I would like some advice on using Laravel's (5.2) polymorphic relationships. The way I envision this is that I will have a base report model that contains all the shared fields and have the MorphTo fields; then have the different types separate containing their unique fields in a one-to-one relationship with the reports model. Is this possible and does this even make sense? The problems I see are that I lose the ability to search across all "reports" regardless of type. Or is there a way around this like say Java where inheritance allows for sub-classes to be considered members of the superclass?
A rough diagram of such relationships is shown below. Reports holds the shared fields while Wanted and Missing have unique fields.
From the diagram representing the relations in your question above, I think it is a straight forward case of parent - child.
Here, your BaseReport or Report is the parent model so to say and the WantedReport and MissingReport are the child - so to say.
Only thing which needs to be changed in your diagram is that you need to define the foreign key of report_id in your child tables to point to the parent record in the base reports table.
Table-reports
id // primary key
date
description
Table - wanted_reports
id //primary key
report_id //foreign key linking to the reports table
status_at
is_captured //maybe a boolean field
charge
Table - missing_reports
id //primary key
report_id //foreign key linking to the reports table
status_at
is_found
last_seen_date
last_seen_at
The you can define the corresponding models as - Report
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Report extends Model
{
protected $table = 'reports';
protected $fillable = ['report_date', 'description'];
public function wanted_reports()
{
return $this->hasMany(WantedReport::class);
}
public function missing_reports()
{
return $this->hasMany(MissingReport::class);
}
}
WantedReport
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class WantedReport extends Model
{
protected $table = 'wanted_reports';
protected $fillable = ['report_id', 'status_at', 'is_captured', 'charge'];
public function report()
{
return $this->belongsTo(Report::class);
}
}
MissingReport
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MissingReport extends Model
{
protected $table = 'missing_reports';
protected $fillable = ['report_id', 'status_at', 'is_found', 'last_seen_date', 'last_seen_at];
public function report()
{
return $this->belongsTo(Report::class);
}
}
Then anywhere in your application you can access the relations like you normally do, for example
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ReportsController
{
public function store(Request $$request)
{
$report = $this->model->create([
'report_date' => Carbon:::now(),
'description' => $request->get('description')
]);
if($report)
{
$wantedReport = $report->wanted_reports()->create([
'status_at' => $request->get('status'),
...
]);
$missingReport = $report->missing_reports()->create([
'status_at' => $request->get('status'),
...
]);
}
}
}
Hope this helps

How to listed to deleted event properly?

I have records of a Model that I need to delete, however I need to delete their id's also from the pivot table, so I tried to listed to deleted event, but it didn't work
Here is how I add the event:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Criteria extends Model {
protected $table = 'criterias';
public static function boot()
{
parent::boot();
static::deleted(function($criteria)
{
DB::table('criteria_criteria')->where('criteria_id', '=', $criteria->id)->delete();
});
}
}
I am on Laravel 5.1, any idea how to do so?
I think you have not used its relationship. Please create a relationship with your pivot table like this.
public function criteria()
{
return $this->belongsToMany('App\Criteria');
}
This will automatically manage your deletion query on pivot table. It has also one benifit you can use its sync and detach methods to add and remove pivot table records.
For more detail you can read in this tutorial by search keyword pivot.

Resources