Laravel eager loading a BelongsTo relation doesn't work - laravel

This seems extremely simple and yet it doesn't work:
// Reservations
class Reservation extends Model
{
public function service()
{
return $this->belongsTo('App\Landing');
}
}
// Service
class Landing extends Model
{
public function reservation()
{
return $this->hasMany('App\Reservation');
}
}
And then in my controller I have:
$x = Reservation::with('service')->get();
$y = Reservation::all()->load('service');
None of these work. I've tried several ways of loading it and none of them work. It always returns an empty result for the service.
Any other result works fine with eager loading (even with nesting) except te BelongsTo - this one.

The eager loading works.
The problem is your relationship
When you define a BelongsTo relationship you need to specify a foreign key if the name of your property does not correspond to the entity being referenced
For example: if you call the relationship "landing", you will be fine, because under-the-hood, Laravel passes the foreign key landing_id based on the name of the property
class Reservation extends Model
{ //landing correspond to the lowercase (singular) name of the Landing class
//in that case Laravel knows how to set the relationship by assuming
//that you want to match landing_id to the id of the landings table
public function landing()
{
return $this->belongsTo(Landing::class);
}
}
If you chose to name the relationship differently, such as "service", then you need to specify the foreign key ex: landing_id since service and landing are two different words, and landing correspond to the lowercase version of the actual class Landing. Otherwise Laravel would think your foreign key is "service_id" instead of landing_id
class Reservation extends Model
{
//service is a custom name to refer to landing
//in that case Laravel needs you to specify the foreign key
public function service()
{
return $this->belongsTo(Landing::class, 'landing_id');
}
}
Read more here: https://laravel.com/docs/5.8/eloquent-relationships#updating-belongs-to-relationships

Related

Removing duplicates in Laravel relationships

I'm working with a situation where people and employers are related through licenses. So my models look something like this:
class Employer extends \Illuminate\Database\Eloquent\Model
{
public function people()
{
return $this->belongsToMany(Person::class, 'licenses');
}
// &c
}
class Person extends \Illuminate\Database\Eloquent\Model
{
public function employer()
{
return $this->belongsToMany(Employer::class, 'licenses');
}
// &c
}
However, person-employer pairs can have multiple licenses. So the aforementioned relationship returns duplicate Person entities, namely one Person entity for every License entity associated with the employer.
How do I fix this issue so that these relationships only return unique entities?
You can try laravel $collection->unique('licence_number')
so whatever eloquent returns you in collection just use unique with attribute
on the basis of you want to make the result unique like
licence_number is in the collection
[ { licence_number:1, name:'test' }, { licence_number:2, name:'jhon' } ]

Laravel Eloquent Relation belongsTo update

I am trying to update/delete/create in belongsTo relations.
Company has many sports
sports is belonging to Company
Here is two models.
class CompanySports
{
public function company()
{
return $this->belongsTo(Company::class, "company_id","id");
}
class Company
public function sports()
{
return $this->hasMany(CompanySports::class,"company_id","id");
}
}
at controller, when sports is added or modified or remove, what is the best practice to update?
i know that many to many, sync can be used. In this, what is the best solution? Should i compare everytime after loading all from database which is not good practice i believe.
From your code, I would first recommend putting your models in separate files, and ensuring they are singular. If you use the artisan make:model command to generate the stubs, it should do this for you.
// app/CompanySport.php // <-- NOTE singular
class CompanySport // <-- NOTE singular
{
public function company()
{
return $this->belongsTo(Company::class, "company_id","id");
}
}
// app/Company.php
class Company {
public function sports()
{
return $this->hasMany(CompanySport::class,"company_id","id"); // singular
}
}
From there, I find it helpful to build helper methods in the various classes so that the grammar sounds natural and more importantly, belongs to the model. For example:
// app/Company.php
class Company
{
...
public function addSport(CompanySport $sport)
{
$this->sports()->save($sport);
}
public function removeSport(CompanySport $sport)
{
$this->sports()->find($sport->id)->delete();
}
}
These helper functions can then be easily called from anywhere, e.g. controller:
// CompanySportsController.php
public function store(Company $company, CompanySport $sport)
{
$company->addSport($sport);
return redirect('/company/' . $company->id);
}
If you are using these helpers, there is no comparing or sync to be done since you are only using a one to many relationship. Eloquent does everything for you.
Also, I've found this cheatsheet particularly helpful when building out the initial relationships and scaffolding of a new app.
While adding new record of Company Model, you need not to do anything as there is no child for it yet.
While updating an instance of a Company model, again you need not to update anything on its children. As relationship are based on id(primary key) which I believe you don't change while updating.
And now for deleting there are some questions. Do you want to delete the children when the parent is deleting? If so, you can use ON DELETE CASCADE which you can set up in migration like
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
in your spors table.
Well you can make your own function too like answered in here
Well if you don't want to delete the children, you can use softdelete on your Model. set up the relations then like
CompanySports
public function company()
{
return $this->belongsTo(Company::class, "company_id","id")->withTrashed();
}
This way you can get the parent of a children without any error though the parent is deleted.

Correct relationship in Laravel

I have four tables in database: groups, specialties, lessons, group_lesson. It's structures:
groups
id
specialty_id
name
specialties
id
name
lessons
id
specialty_id
group_lesson (UNIQUE INDEX lesson_id, group_id)
lesson_id
group_id
date
My models look like that for now:
class Group extends Eloquent {
public function specialty() {
return $this->belongsTo('Specialty');
}
}
class Lesson extends Eloquent {
public function specialty() {
return $this->belongsTo('Specialty');
}
}
class Specialty extends Eloquent {
public function lessons() {
return $this->hasMany('Lesson');
}
public function groups() {
return $this->hasMany('Group');
}
}
I need get additional fields in Group model look like that
Group - Eloquent model
name - string
lessons - collection of Lesson models of Group Specialty
date - date from group_lesson table
I've tried different relationships and combinations, but it's doesn't work. Please help me to write correct relationships.
You can use eager-loading to access relational data through relationships, and can even chain relationships further. As a rule of thumb, if you can draw a path to from 1 model to another through a relationship, you can eagerload all the relevant and relational data for that with chained eager-loads.
Laravel Eager Loading
As an example
$speciality_group = Speciality::with('group','lessons')->find($id);
Even though you are only getting a single instance of the speciality model, the related data is hasMany, meaning multiple records. You need to loop through these records using a foreach loop to access the relevant data for them, or alternitavely add additional closures in your initial query to load only a single related model.
foreach($speciality_group->group as $group)
{
echo $group->name;
}
You will need to do this for both instances where you want to display related information.

Laravel - Using different field names in the database (userid in a table and created_by in other)

I am trying to use a table for my Users and separate table for users' Projects in my database. However I want the names of the fields to be different for user id. What I want to take the id from the 'Users' table; and while saving the created project to the database, use that (user) id as created_by_id in Projects table.
public function store(CreateProjectRequest $request)
{
$project = new Project($request->all());
Auth::user()->projects()->save($project);
// Project::create($request->all());
return redirect('pages/home');
}
Also in Users.php, I added:
public function projects()
{
return $this->hasMany('App\Project');
}
The commented field is working on its own. However, I guess my problem arises because when I comment that line again, and add the other two lines ($project... and Auth::user... bits), I guess it is assuming I have a field in the Projects table named id.
I thought I would work around this problem with changing the primary key but I couldn't find how to take the Auth::user()->id; and make it write that value in created_by_id in a secure way. This is what I found though:
class Project extends Eloquent {
protected $primaryKey = 'created_by_id';
}
Edit: I don't think changing the primary key is my solution.
You can pass a second and third parameter to hasMany() method to specify the keys to use. Documentation
public function projects()
{
return $this->hasMany('App\Article','userid','created_by');
}

Get model name dynamically in cakephp 2.x

Is there any function to get the all table or model names in cakePhp.
I want to update my table's field and for that I need to select all table dynamically so that in future when I'll add new table I do not have to make changes in function.
The new table automatically update the fields.
I don't quite understand the question - from what i gather you want to write abstract actions to account for multiple models? If this is the case you can add abstract actions into the AppController and use $this->modelClass. This will return the model name from were you are calling the abstract action from. For example if you calling the abstract action from 'UsersController' which by default uses the Model 'User' then the modelClass will return 'User'.
class AppController extends Controller {
public function abstractAdd() {
// Get the model in use
$this->{$this->modelClass}->create();
// Use the save method in that model
if ($this->{$this->modelClass}->save($data)) {
// do something
}
}
}
class UsersController extends AppController {
public function add() {
$this->abstractAdd();
}
}
Hope this helps

Resources