How can I get a pivot on my relationship in Laravel? - php

I have a relationship in my app. A candidate can have several "candidate_trainings" and each "candidate_training" is associated with a training. I wanted to avoid making "candidate_trainings" the piviot since it's hard to delete the right values when detaching, etc. So, how can I, on my hasMany relationship get the CandidateTraining model with the data from the Training model.
Here are my relationships:
<?php
namespace App;
use App\Traits\SanitizeIds;
use App\Salary;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class Candidate extends Model
{
public function saveTraining($data) {
$this->candidateTrainings()->delete();
foreach(json_decode($data['training']) as $training) {
if(Training::find($training->training)->first()) {
$candidateTraining = new CandidateTraining;
$candidateTraining->description = $training->value;
$candidateTraining->training_id = $training->training;
$this->candidateTrainings()->save($candidateTraining);
}
}
}
public function candidateTrainings() {
return $this->hasMany('\App\CandidateTraining');
}
public function trainings() {
return $this->belongsToMany('\App\Training');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Training extends Model
{
protected $fillable = ['name_french', 'name_english'];
public function candidates() {
return $this->belongsToMany('\App\Candidate');
}
public function candidateTrainings() {
return $this->hasMany('\App\CandidateTraining');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class CandidateTraining extends Pivot
{
public function candidate() {
return $this->belongsTo('\App\Candidate');
}
public function training() {
return $this->belongsTo('\App\Training');
}
}
Thank you!

For you to be able to update the data directly on the CandidateTraining model, you need to add the $fillable fields to it.
protected $fillable = ['training_id', 'description'];
Your code should work! But if you don't mind, I did a little refactoring. You can accomplish this in another way:
<?php
namespace App;
use App\Traits\SanitizeIds;
use App\Salary;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class Candidate extends Model
{
public function saveTraining($data)
{
// remove all relationships
$this->trainings()->detach();
// add new ones
foreach(json_decode($data['training']) as $training)
{
if(Training::find($training->training)->first())
{
$this->trainings()->attach($training->training, [
'description' => $training->value,
]);
}
}
}
public function candidateTrainings()
{
return $this->hasMany(App\CandidateTraining::class);
}
public function trainings()
{
return $this->belongsToMany(App\Training::class)
->withTimestamps()
->using(App\CandidateTraining::class)
->withPivot([
'id',
'training_id',
'description',
]);
}
}
That $training->training stuff is not readable, change it to something like $training->id if you are able to.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Training extends Model
{
protected $fillable = ['name_french', 'name_english'];
public function candidates()
{
return $this->belongsToMany(App\Candidate::class)
->withTimestamps()
->using(App\CandidateTraining::class)
->withPivot([
'id',
'training_id',
'description',
]);;
}
public function candidateTrainings()
{
return $this->hasMany(App\CandidateTraining::class);
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class CandidateTraining extends Pivot
{
protected $fillable = ['training_id', 'description'];
public function candidate()
{
return $this->belongsTo(App\Candidate::class);
}
public function training()
{
return $this->belongsTo(App\Training::class);
}
}
If you want to access the pivot object from a controller:
$candidates = Candidate::with(['trainings'])->get();
foreach ($candidates as $candidate)
{
dd($candidate->pivot);
}

Related

cannot retrieve Category model with related items

I have very strange error in my laravel website.
I try to retrieve Category model with related items, but looking at the error I see that laravel tries to retrieve items field from category model and of course it fails. But I am completely cannot understand why it happens, because I have the same code working well in other parts of my website.
routes/web.php
Route::name('gallery.')->prefix('gallery')->group(function () {
Route::get('/', 'GalleryController#index')->name('index');
Route::get('/{slug}', 'GalleryController#item')->name('item');
});
GalleryController
public function item($slug)
{
$category = $this->imageRepository->getCategoryWithPaginatedImages($slug, $perPage = 20);
return view('pages.gallery.item', compact('category'));
}
ImageRepository
namespace App\Repositories;
use Illuminate\Database\Eloquent\Collection;
use App\Models\ImageCategory as Model;
class ImageRepository extends CoreRepository
{
protected function getModelClass()
{
return Model::class;
}
public function getCategoryWithPaginatedImages($slug, $perPage = null)
{
$columns = ['id','title','slug','description','image','published','metatitle','metakey','metadesc'];
$result = $this
->startConditions()
->whereSlug($slug)
->select($columns)
->with('images:id,title,category_id,md,lg')
->firstOrFail()
->toArray();
$result = Arr::arrayToObject($result);
$result->items = collect($result->items)->mypaginate($perPage);
return $result;
}
}
Image
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Image extends Model
{
protected $guarded = [];
public function category() { return $this->belongsTo(ImageCategory::class); }
}
ImageCategory
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ImageCategory extends Model
{
protected $guarded = [];
public $timestamps = false;
public function images() { return $this->hasMany(ImageCategory::class, 'category_id'); }
}
so when I hit gallery/slug then getCategoryWithPaginatedImages gives me following error
Illuminate\Database\QueryException
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'category_id' in 'field list' (SQL: select `id`, `title`, `category_id`, `md`, `lg` from `image_categories` where `image_categories`.`category_id` in (2))
I guess the relationship images on ImageCategory definition has an issue, should be as under
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ImageCategory extends Model
{
protected $guarded = [];
public $timestamps = false;
public function images()
{
return $this->hasMany(Image::class, 'category_id');
}
}

laravel eloquent relation for many tables

I am going to join 4 eloquent models using belongTo, hasMany, .... in laravel.
$result = \DB::select(
'ca.*',
array(DB::expr('CONCAT(u.first_name, " ", u.last_name)'), 'user'),
array(DB::expr('CONCAT(u.first_name, " ", u.last_name)'), 'full_name'),
array('u.id','user_id'),
array('d.name','department_name'),
array('d.clean_name','department_clean_name'),
array('d.id','department_id'),
array('u.extension','user_extension'),
array('u.mobile','user_mobile'),
array('u.email','email')
)
->from(array('case_assignments', 'ca'))
->join(array('departments', 'd'), 'left')->on('d.id','=','ca.department_id')
->join(array('users', 'u'), 'left')->on('u.id','=','ca.user_id')
->where('case_id','=', $case_id)
->get();
How can i change this to laravel eloquent relations?
Try this,
CaseAssignment Model:-
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CaseAssignment extends Model
{
public function department()
{
return $this->BelongsTo('App\Models\Department','department_id');
}
public function user()
{
return $this->BelongsTo('App\User','user_id');
}
}
Department Model:-
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Department extends Model
{
public function caseAssignments()
{
return $this->hasMany('App\Models\CaseAssignment');
}
}
User Model:-
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function caseAssignments()
{
return $this->hasMany('App\Models\CaseAssignment');
}
}
In Controller:-
$result = CaseAssignment::with('department','user')->where('case_id','=', $case_id)
->get();
dump($result->department->name);
dump($result->department->clean_name);
dump($result->department->id);
dump($result->user->extension);
dump($result->user->mobile);
dump($result->user->email);
dump($result->user->first_name.' '.$result->user->last_name);
dd($result);
Use relationships for this.
In CaseAssigment model add these 2 records
public function user() {
return $this->belongsTo(User::class);
}
public function department() {
return $this->belongsTo(Department::class);
}
And the query
$result = CaseAssigment::query()
->with([
'departament' => function($departaments){
$departament->select('id', 'name', 'clean_name');
},
'user' => function($users){
$user->select('id', DB::raw('CONCAT(first_name, last_name) AS full_name'), 'extension', 'mobile', 'email');
}
])
->where('case_id','=', $case_id)
->get();
I think you have one department and one user on CaseAssigment. If there are a lot of them, then tell me I will rewrite the request

How can I pass a parameter from the controller index function to the model's functions? LARAVEL

//------------------------------//
//below is the controller index function code //
//------------------------------//
public function index($from, $to,$id)
{
$data=Attendance::where('attendance_date','>=',$from)
->where('attendance_date','<=',$to)
->with('userAttendance')//--> **I need to pass the $id to this function in the model**
->with('admin')
->get()
//---------------------------------//
//below is the model code //
//----------------------------------//
class Attendance extends Model
{
protected $table = "attendances";
protected $fillable=[
'attendance_date',
'admin_id',
];
//---> **i need the $id passed to here**
public function userAttendance()
{
return $this->belongsToMany('App\User', 'user_attendances','attendance_id','user_id')
->withPivot(
'present_absent',
'excuse',
'attendance_key_amount',
'verified_date',
'comment',
);
}
}
just try this
Controller:
public function index()
{
$id = 50;
Product::getId(50);
}
Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public static function getId($id){
dd($id);
}
}

Many To Many (Polymorphic) using the same model with different types

I have these 3 tables in the database:
I'm using Many To Many (Polymorphic) Eloquent relationship to connect the Models. The problem is that the Creadores table can be of type artista or autor in the Creaciones table.
Is it possible to tell Eloquent when to use artista or autor?
It works if I extend the Creador Model into 2 other Models: Artista and Autor. But when I want to show all the creaciones of a creador using the Creador Model, it's not possible because the Polymorphic relationship was created with the extended models.
Libro Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use ChrisKonnertz\BBCode\BBCode;
class Libro extends Model
{
protected $table = 'Libros';
// Return all the artists of the book
public function artistas()
{
return $this->morphedByMany('App\Creador', 'creador', 'creaciones');
}
// Return all the authors of the book
public function autores()
{
return $this->morphedByMany('App\Creador', 'creador', 'creaciones');
}
}
Creador Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Creador extends Model
{
protected $table = 'creators';
// Return all the books where author
public function autorLibros()
{
return $this->morphToMany('App\Libro', 'creador', 'creaciones');
}
// Return all the books where artist
public function artistaLibros()
{
return $this->morphToMany('App\Libro', 'creador', 'creaciones');
}
}
You might be better off just adding a type property to Creador with 'artista'/'autor' in it.
The polymorphic relationship can only take a single model.
So your code would then become:
public function creadors()
{
// Return a general relation for all 'creadores'.
return $this->morphedByMany(App\Creador::class, 'creador', 'creaciones');
}
public function artistas()
{
// Filter for 'artista's.
return $this->creadors()->where('type', 'artista');
}
public function autores()
{
// Filter for 'autor's.
return $this->creadors()->where('type', 'autor');
}
Solved it the following way. Changed the relation from a Polymorphic Many to Many to a normal Many to Many, adding withPivot and wherePivot.
Creador Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Creador extends Model
{
protected $table = 'creators';
public function libros()
{
return $this->belongsToMany('App\Libro', 'creaciones')->withPivot('creador_type');
}
// All books as an Artist
public function librosArtista()
{
return $this->libros()->wherePivot('creador_type', 1);
}
// All books as an Author
public function librosAutor()
{
return $this->libros()->wherePivot('creador_type', 2);
}
}
Libro Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use ChrisKonnertz\BBCode\BBCode;
class Libro extends Model
{
protected $table = 'libros';
public function creador()
{
return $this->belongsToMany('App\Creador', 'creaciones')->withPivot('creador_type');
}
// All book artists
public function artistas()
{
return $this->creador()->wherePivot('creador_type', 1);
}
// All book authors
public function autores()
{
return $this->creador()->wherePivot('creador_type', 2);
}
}
And when creating a attaching a Creador to a Libro:
$libro->artistas()->attach( $creador, [
'creador_type' => 1
]);

Laravel Tables Join

I have three tables:
notes: id, business_id, note
businesses: id, title, description
businessimages : id, business_id, image
I get my customers notes with this:
$customer = Auth::guard('customer-api')->user();
$notes = Note::where('customer_id', $customer->id)->with('business:id')-
>orderBy('id', 'desc')->get();
Now I want to get notes.id, businesses.id, businesses.title, businesses.description, businessimages.image for each notes and show all of them in one json array
How could I do?
Note::where('customer_id',$customer->id)
->join('businesses', 'businesses.id', '=', 'notes.buisness_id')
->join('businessimages', 'businesses.id', '=', 'businessimages.buisness_id')
->select(notes.id, businesses.id, businesses.title, businesses.description,businessimages.image)
->get();
Note model;
public function business() {
return $this->hasOne('App\Business', 'business_id', 'id');
}
Business mode;
public function businessImage()
{
return $this->hasOne('App\BusinessImage', 'business_id', 'id');
}
Your controller;
$notes = Note::where('customer_id', $customer->id)->with('business.businessImage')->orderBy('id', 'desc')->get();
You should consider using API Resources
This is a great way to organize a model(or a collection of models as well).
App\Note
use Illuminate\Database\Eloquent\Model;
class Note extends Model
{
public function business()
{
return $this->belongsTo('App\Business');
}
}
App\Business
namespace App;
use Illuminate\Database\Eloquent\Model;
class Business extends Model
{
public function note()
{
return $this->hasOne('App\Note');
}
public function businessImage()
{
return $this->hasOne('App\BusinessImage');
}
}
App\BusinessImage
namespace App;
use Illuminate\Database\Eloquent\Model;
class BusinessImage extends Model
{
protected $table = 'businessimages';
public function business()
{
return $this->belongsTo('App\Business');
}
}
App\Http\Resources\Note
namespace App\Http\Resources;
class Note
{
public function toArray($request)
{
return [
'noteId' => $this->resource->id,
'businessId' => $this->resource->business->id,
'businessTitle' => $this->resource->business->title,
'businessDescription' => $this->resource->business->description,
'businessImage' => $this->resource->business->businessImage->image
];
}
}
Somewhere in a controller
use App\Http\Resources\Note as NoteResource;
public function foo()
{
$customer = Auth::guard('customer-api')->user();
$notes = Note::where('customer_id', $customer->id)->with(['business','business.businessImage'])->orderBy('id', 'desc')->get();
return NoteResource::collection($notes);
}

Categories