I tried all the tutorials on internet and Youtube but it doesn't work so you guys are my last chance please I need your help.
I need to use $candidate->service->service_name
and $candidate->documents->doc but it doesn't work
I get this error [Call to undefined method stdClass::service()] (by the way, should I use"documents" or "document" ?)
the "candidate" has more than one document, and the document belongs to only one "candidate";
the "candidate" has to choose one "service" (to work in) and the service is chosen by a lot of "candidate"
I have 3 tables :
services=['id_service',
'service_name'] #((id_service Primary key))
candidate =[ 'id_candidate',
'id_service',
'name',
'email'...]; #((id_candidate Primary key, id_service Foreign key))
document=['id_doc',
'id_candidate',
'doc'] #((id_doc Primary key, id_candidate Foreign key))
IN CANDIDATE'S MODEL :
use App\Models\Service;
use App\Models\Document;
public function documents()
{
return $this->hasMany(Document::class);
}
public function service()
{
return $this->belongsTo(Service::class);
}
IN DOCUMENT'S MODEL :
use App\Models\Candidate;
public function candidate()
{
return $this->belongsTo(Candidate::class, 'id_candidate', 'id_doc');
}
IN SERVICE'S MODEL :
use App\Models\Candidate;
public function candidates()
{
return $this->hasMany(Candidate::class);
}
IN CANDIDATECONTROLLER :
public function show( $id_candidate)
{
$candidate = DB::table('candidates')->select('id_candidate','id_service','name')->where('id_candidate', $id_candidate)->first();
return view ('candidate.profile', compact('candidate'));
}
IN candidate/profile :
...
<input type="text" id="service" name="service" value={{ $candidate->service()->service_name }}>
You're my hope
Thank you in advance
Candidate Model
class Candidate extends Model
{
public function candidate_documents()
{
return $this->hasMany(Document::class, 'id_candidate');
}
public function candidate_service()
{
return $this->BelongsTo(Service::class, 'id_service');
}
}
By using DB:: relationships do not work as commented by #ceejayoz
so from candidate controller you can used it like this
$candidateResult= Candidate::with('candidate_documents')->with('candidate_service')->get();
you can also use hasOne in candidate_service() depends on where is your foreign key is
In your code, Candidate has a id_service column, then candidate belongsTo Service.
by using hasOne and hasMany we are telling laravel that this table does not have the foreign key.
Related
I have Task model. My Task model has some relationships and it currently looks like this:
class Task extends Model
{
use HasFactory;
public $timestamps = false;
public function city()
{
return $this->hasOne(City::class, 'id', 'city_id');
}
public function type()
{
return $this->hasOne(Type::class, 'id', 'type_id');
}
public function note()
{
return $this->hasOne(Note::class, 'id', 'note_id');
}
public function operator()
{
return $this->hasOne(User::class, 'id', 'operator_id');
}
}
Now, in my TasksController I need to get Tasks that match certain criteria, like this:
$tasks = Task::whereCityId($city->id)->whereTypeId($type->id)->get()->toArray();
The problem is that fields named city_id type_id note_id operator_id will get my integer values that they have.
Instead I would like to get certain value from a related Model.
For example:
operator_id should be replaced with username from User table that corresponds to the user id.
An obvious solution to this would be to simply use foreach loop, go through my results and get the data I need and simply create another array with the information replaced, but I am not sure if this is the best idea and perhaps there is something better.
You have to change in your code:
$this->hasOne(ClassName::class, 'id', 'foreign_key');
To
$this->belongsTo(ClassName::class, 'foreign_key', 'id');
because Task's id does not available as foreign key in these tables. These table's id present in task table as foreign key so you have to use belongsTo() relationship to tell script from where these id belongs.
Then access properties like this:
$tasks = Task::with("type", "city", "operator")
->whereCityId($city->id)->whereTypeId($type->id)->get();
foreach($tasks as $task){
echo $task->city->name;
}
first you should fix your relation:
public function city()
{
return $this->hasOne(City::class,'city_id','id');
}
and so one the same error, foreign key in argument order comes before the primary key.
after that you can use addSelect:
$tasks = Task::whereCityId($city->id)->whereTypeId($type->id)
->addSelect(['userName' => User::select('name')
->whereColumn('users.id', 'tasks.operator_id')
->limit(1)])->get()->toArray();
i think this will help better than what you ask.
$tasks = Task::whereCityId($city->id)
->whereTypeId($type->id)
->with('operator')
->get()->toArray();
with('operator') is ORM feature that make you collection to include its relation as collection property. In this case it will convert to array property.
you could access it from your foreach function as
#foreach($task as $key)
$key['operator']['username']
#endforeach
Have a nice day
I am working on a project where we have a model for a service provider, the type of care provided, and the status:
Provider:
class Provider extends Model
{
protected $table = 'providers';
public function status() {
return $this->belongsTo('App\Status');
}
public function caretype() {
return $this->belongsTo('App\CareType', 'id');
}
}
CareType:
class CareType extends Model
{
protected $table = 'type_of_care';
public function providers() {
return $this->hasMany('App\Providers', 'type_of_care_id');
}
public function category() {
return $this->belongsTo('App\CareCategory');
}
}
Status:
class Status extends Model
{
protected $table = 'status';
public function providers() {
return $this->hasMany('App\Providers');
}
}
On the my SearchController (the controller that processes search requests for providers), the show() function using eager loading retrieves the caretype perfectly. But on the search() function that lists the collection of search results, the caretype is always listed as null.
I don't understand why it would be working in one function but not the other, especially when the code to eager load is exactly the same in both functions:
public function search(Request $request)
{
$validated = $request->validate([
//I removed the validation code for this post
]);
$providers = Provider::with(['status', 'caretype'])->get();
return view('search.results', ['providers' => $providers]);
}
public function show($id)
{
$single_provider = Provider::with(['status', 'caretype'])->where('id', $id)->first();
return view('search.details', ['provider' => $single_provider]);
}
Any help in this would be appreciated. I know that the model and relationship foreign keys are properly defined because the show() function is able to get the caretype just fine.
nope. your relationship and foreign keys are not correct. as from the doc
Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with a _ followed by the name of the primary key column. However, if the foreign key on the Child model is not like that, you may pass a custom key name as the second argument to the belongsTo method.
you are passing the id column as the foreign key in Provider model's caretype ralation but your foreign key is type_of_care_id. so you are getting some results when the id matches but if not, you are getting null. change your relationship code to
public function caretype()
{
return $this->belongsTo('App\CareType', 'type_of_care_id');
}
now again from the doc
If your parent model does not use id as its primary key, or you wish to join the child model to a different column, you may pass a third argument to the belongsTo method specifying your parent table's custom key.
in your case id is the primary key. so you don't have to pass the third parameter. just update the primary key reference and everything will work perfectly.
I'm developing a project to track deliveries of goods.
My idea would be that one delivery can go to different places, and all those places are connected by single trips.
Here is my Eloquent schema:
class Delivery extends Model
{
public function places()
{
return $this->hasMany(Place::CLASS, 'delivery_id');
}
public function trips()
{
// what should I do here?
}
}
class Place extends Model
{
public function delivery()
{
return $this->belongsTo(Delivery::CLASS, 'delivery_id');
}
}
class Trip extends Model
{
public function departurePlace()
{
return $this->belongsTo(Place::CLASS, 'departure_place_id');
}
public function arrivalPlace()
{
return $this->belongsTo(Place::CLASS, 'arrival_place_id');
}
}
Basically what I am trying to do is to get all the trips that are related to one delivery. Or, as another way of saying it, all the trips that connect all the places that one delivery must go through.
This is the SQL query that achieves the result I want:
select distinct trip.*
from delivery
join place on (place.delivery_id = delivery.id)
join trip on (place.id = trip.arrival_place_id or place.id = trip.departure_place_id)
I would like to have a trips() method on my Delivery model, that returns that result.
However I am quite confused as to how achieve that using Eloquent.
Unfortunately we could have simply used the union method to achieve this, but it seems that is doesn't work for hasManyThroughrelations.
Anyway, I think Eloquent relations are not meant to be used to achieve such a specific query.
Instead, you may use Eloquent scopes to achieve this.
So based on the answer of #Saengdaet, we can write two relations and then combine them with a scope:
(BTW: I don't know why you said that his code gave an error...)
class Delivery extends Model
{
public function places()
{
return $this->hasMany(Place::class);
}
public function outboundTrips()
{
return $this->hasManyThrough(
Trip::class,
Place::class,
"delivery_id", // Foreign key on places table
"departure_place_id", // Foreign key on trips table
);
}
public function inboundTrips()
{
return $this->hasManyThrough(
Trip::class,
Place::class,
"delivery_id", // Foreign key on places table
"arrival_place_id", // Foreign key on trips table
);
}
public function scopeTrips($query)
{
$deliveriesWithTrips = $query->with(['outboundTrips', 'inboundTrips'])->get();
$trips = [];
$deliveriesWithTrips->each(function ($elt) use (&$trips) {
$trips[] = $elt->inboundTrips->merge($elt->outboundTrips);
});
return $trips;
}
}
And now to retrieve all trips for a given delivery you simply write:
Delivery::where('id', $id)->trips();
If you want to get all trips from using Delivery model, you can use `hasManyThrough" relationship that provides a convenient shortcut for accessing distant relations via an intermediate relation.
But you have to choose which FK on your Trip model will you use to relate it
You can refer to "has-many-through" relationship
class Delivery extends Model
{
public function places()
{
return $this->hasMany(Place::CLASS, 'delivery_id');
}
public function trips()
{
return $this->hasManyThrough(
Trip::Class,
Place::Class,
"delivery_id", // Foreign key on places table
"departure_place_id", // Foreign key on trips table
"id", // Local key on deliveries table
"id" // Local key on places table
);
}
}
so i have those models
// Curso.php
public function trienio()
{
return $this->hasMany('App\Trienio');
}
// Trienio.php
public function curso()
{
return $this->belongsTo('App\Curso');
}
public function oe()
{
return $this->belongsTo('App\OE');
}
public function aluno()
{
return $this->hasMany('App\Aluno');
}
// Oe.php
public function trienio()
{
return $this->hasMany('App\Trienio');
}
// Aluno.php
public function trienio()
{
return $this->belongsTo('App\Trienio');
}
public function pap()
{
return $this->hasOne('App\PAP');
}
// Pap.php
public function aluno()
{
return $this->belongsTo('App\Aluno');
}
public function video()
{
return $this->hasOne('App\Video');
}
// Video.php
public function pap()
{
return $this->belongsTo('App\Pap');
}
and i'm having trouble "converting" those to sql foreign keys. can anybody give me insight on what the foreign keys equivalents will be considering those eloquent relationships? ty in advance
p.s - i can provide more details if needed.
p.s2 - what i REALLY want to know is how i should structure the fields, the sql foreign keys and the constraints based on those eloquent relationships. and how do i that ?
When ever you have hasMany relation, please specify the foreign key used. as follows
// Curso.php
public function trienio()
{
return $this->hasMany('App\Trienio', 'curso_id');
}
this means you have one to many relation ship between Curso and Trienio, but the table trienio must have a field as curso_id (If you want default implementation, no need to establish hard relationship using SQL foreign key constraints) By default this relation will work.
And in belongsTo you dont need to specify the key (Optional).
To fetch the data from Curso
$curso = Curso::find(1);
$trienio = $curso->trienio;
At the trienio side, its okay
// Trienio.php
public function curso()
{
return $this->belongsTo('App\Curso');
}
Similarly for all other.
Note: If you do like this for Curso and Trienio (one to many), the table of Trienio model must have curso_id field and by default relationship will work without doing anything at SQL side.
Update:Using SQL, modify table of Trienio model.
ALTER TABLE trienios MODIFY COLUMN curso_id INT NOT NULL,
ADD CONSTRAINT trienios_curso_id_fk
FOREIGN KEY(curso_id)
REFERENCES Curso(id);
Using Schema builder (Migration Files) Link
$table->foreign('curso_id')
->references('id')->on('curso')
->onDelete('cascade');
You can specify the cascade rule.
ok I have this table "areas":
id -> primary key, int
parent -> int, index, nullable
areaName -> string
this table contains areas, and each area can be a son of another area, so the parent column could be null, or another id of any other area.
now I want to make it accessible with Eloquent, this is an one to many relationship.
I tried this code but not so good, any ideas from someone who done something like this?
class Area extends Eloquent {
public function sons() {
return $this->hasMany('Area', 'id', 'parent');
}
public function parent() {
return $this->belongsTo('Area');
}
}
If I am not wrong and from the given code, Laravel complains about area_id column is not found, am I right?
This happens because you do not provide name of foreign column and Laravel tries to guess it for you.
Change relationship definition to this
public function parent() {
return $this->belongsTo('Area', 'parent');
}
I fount the solution, it works great for me.
class Area extends Eloquent {
public function subAreas() {
return $this->hasMany('Area', 'parent', 'id');
}
public function parentArea() {
return $this->belongsTo('Area', 'parent', 'id');
}
}