So I have two Laravel/Eloquent models, and I want to add one more field to one of them.
Model 'Car' gets data from table 'cars' and has fields 'id', 'model', 'color' and 'price'. Model 'Person' has fields 'id', 'name' and 'car_id', which is foreign key from 'cars' table. I want model 'Person' to have a field named 'car', which would contain car model from 'Car' model, depending on existing car_id. I've tried something like:
use App\Models\Car;
class Person extends Model {
protected $car = array(Car::find($this->car_id));
}
But that was unsuccessful (errors like 'syntax error, unexpected '(', expecting ')''). What could be the solution? Thanks!
You need to define One-To-Many relationship first. Then get car model for the person:
$carModel = Person::find($personId)->car->model;
Take a look at Eloquent Relationships. What you are trying to do is to create a relationship between Car and Person models. It is up to you if a person can own one or multiple cars. I am suggesting you to let a person have multiple cars.
So, the Person model should know that it has multiple cars:
class Person extends Model
{
public function cars()
{
return $this->hasMany(App\Car::class);
}
}
A car belongs to a person, so the model should know that:
class Car extends Model
{
public function person()
{
return $this->belongsTo(App\Person::class);
}
}
Of course, when creating the tables you should add the field person_id to the CARS table.
Well, what I needed was:
protected $appends = ['car'];
public function getTypeAttribute($car)
{
return Car::find($this->car_id)->model;
}
It was all about serialization and 'protected $appends', thank you all :)
That's not how its done.
The person can have a car (or many). Let's suppose that every person have one car in your database, your car table should have a nullable person_id column, and add this to your User model
public function car() {
return $this->hasOne('App\Role');
}
Now you can get the person and the his car information's like this
User::where('id',$id)->with('car')->get();
I hope you get the point here
Related
I have these three tables:
tbl_lista_contactabilidad tbl_equipo_postventaatc users
------------------------- ----------------------- -----
id id id
usuarios_id asesor_id name
tbl_lista_contactabilidad.usuarios_id should be related with tbl_equipo_postventaatc.asesor_id. asesor_id should be the "pivot" between tbl_lista_contactabilidad.usuarios_id and users.id to make the relation.
I want to make this relation so I tried to do this relation in this way (I will put only the relation of the model)
Tbl_Lista_Contactabilidad (Model 1)
public function postventaatc(){
return $this->belongsTo('App\Models\Tbl_EquipoPostventaatc','usuarios_id');
}
Tbl_Equipo_Postventaatc (Model 2) -> This should be the pivot model
public function contactabilidad(){
return $this->hasMany('App\Models\Tbl_Lista_Contactabilidad','usuarios_id');
}
public function user(){
return $this->belongsTo('App\Models\User','asesor_id');
}
User (Model 3)
public function postventaatc(){
return $this->hasMany('App\Models\Tbl_Lista_Postventaatc','asesor_id');
}
EXAMPLE:
As you see in the image... if I relate usuarios_id with users directly I will get another name and I don't want that... I want the relation just like in the image
A pivot table is a structure used to join two separate models together with a single relationship. This is called a many-to-many relationship in Eloquent.
From what you've described, this is not the case here. Rather, it looks like a has-many-through relationship.
If I'm understanding correctly, your relationships should look like this:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Tbl_Lista_Contactabilidad extends Model {
protected $table = 'tbl_lista_contactabilidad';
public function postventaatc() {
return $this->belongsTo(Tbl_EquipoPostventaatc::class, 'usuarios_id');
}
}
class Tbl_EquipoPostventaatc extends Model {
protected $table = 'tbl_equipo_postventaatc';
public function contactabilidad() {
return $this->hasMany(Tbl_Lista_Contactabilidad::class, 'usuarios_id');
}
}
class User extends Model {
public function postventaatc() {
return $this->belongsTo(Tbl_EquipoPostventaatc::class, 'asesor_id');
}
public function contactabilidad() {
return $this->hasManyThrough(Tbl_Lista_Contactabilidad::class, Tbl_EquipoPostventaatc::class, 'asesor_id', 'usuarios_id');
}
}
Obviously this is easier for a native English speaker, but I cannot stress how much easier this would be if you were following the Laravel rules around naming your models, tables, and columns. Why does usuarios_id column relate to a table called tbl_equipo_postventaatc? Why use asesor_id instead of user_id? 🤷🏽♂️ Those names have nothing to do with each other, and make it hard to figure out what is going on.
When dealing with belongsToMany relation, you use a pivot table to record the relation.
For many pivot tables, the relations are just created and then deleted. They won't have their own property, so you never update them.
I know I can do this to auto-set both updated_at and created_at.
class Foo extends Model
{
public function bars() {
$this->belongsToMany(Bar::class)->withTimestamps();
}
}
But how to use only created_at? I have no idea.
You could take another approach:
Skip the withTimestamps() method (to avoid adding both created_at and updated_at columns).
Add a custom pivot column: created_at.
So your code:
class Foo extends Model
{
public function bars() {
$this->belongsToMany(Bar::class)->withPivot('created_at');
} // ^^^^^^^^^^^^^^^^^^^^^^^^
}
Now, with this approach you will need to set the value of created_at manually when creating records:
$foo = Foo::find(1);
$foo->bars()->attach($someId, ['created_at' => now()->format('d-m-Y H:i:s')]);
// or whatever you use as date ^^^^^^^^^^^^^
Also, this column won't be casted as a Date by default -as opposed to what Laravel do with timestamp columns- so this:
$foo->bars()->first()->pivot->created_at
won't be an instance of Carbon. If you want it though, you could create a custom Pivot model, then specify the column to cast and update your relationship to use the custom Pivot model:
Pivot model FooBar.php
class FooBar extends Pivot // <--
{
protected $casts = [
'created_at' => 'datetime:d-m-Y H:i:s',
];
}
Then in your Foo.php class:
class Foo extends Model
{
public function bars() {
$this->belongsToMany(Bar::class)->using(FooBar::class)->withPivot('created_at');
// ^^^^^^^^^^^^^^^^^^^^
}
}
I have 3 models: Items, Serials and SerialsCategories. When I show Item form (to create or update) I need to show the serials which belongs to a categoryId selected in a previous step. A serial can belong to more than one category.
Right now I have on my Item model:
public function getSerialsTypeByCategory() {
return (new SerialType)->getByCategory($this->itemCategoryId);
}
On my SerialType model:
public function getByCategory($itemCategoryId) {
return SerialTypeItemCategory::find()->select(['serialTypeId'])->where(['itemCategoryId' => $itemCategoryId])->all();
}
This is working, it does what I need but ... Is this the proper way? is there a better way?
it's not wrong what you are doing. but there is something more -
check this link:
Working with Relational Data
if you use ->hasOne and ->hasMany to define relations, your model gains some extra benefits, like joining with lazy or eager loading:
Item::findOne($id)->with(['categories'])->all();
with a relation, you can also use ->link and ->unlink, to add/delete related data without having to think about linked fields.
Further, it is easy to define relations via junction table:
class Order extends ActiveRecord
{
public function getItems()
{
return $this->hasMany(Item::className(), ['id' => 'item_id'])
->viaTable('order_item', ['order_id' => 'id']);
}
}
Have three entities:
Project
Employee
Employment
Problem description: Employee can work on many projects and for each he has one employment. I want to have access to all projects and your referred employments of a certain employee.
I'm not sure but the relationship must look like a ternary:
The physical table is not defined yet. So, be free to design (most basic) them.
And my question:
How i can build using Laravel Eloquent Relationships?
Basically your four tables will be something like:
employee
id
...your fields
project
id
...your fields
employments
id
...your fields
employee_project
employee_id
project_id
employment_id
You can split the problem in 2 by 2 relations:
class Employee extends Model{
public function projects(){
return $this->belongsToMany("Project")
}
// Second relation is Optional in this case
public function employments(){
return $this->belongsToMany("Employment", 'employee_project')
}
}
A Project model
class Project extends Model{
public function employees(){
return $this->belongsToMany("Employee")
}
// Second relation is Optional in this case
public function employments(){
return $this->belongsToMany("Employment",'employee_project')
}
}
A Employment model
class Employment extends Model{
public function employees(){
return $this->belongsToMany("Employee")
}
public function projects(){
return $this->belongsToMany("Project")
}
}
At this point in your controller you can manage your relation, for example if you want to add to $employee, the project with id 1 with the employment with id 2 you can simply
$employee->projects()->attach([1 => ['employment_id' => '2']]);
I hope this answer to your question.
If you need timestamps in your pivot table, add ->withTimesetamps() to your relationships.
Employee has Employment
Employment has Project
Im trying to access url property on files table by $post->file->url, but i'm getting "Trying to get property of non-object" error. My table and model is different because i can't use File as model name. is there something missing? I hope someone come with solution. here's my tables:
- posts:
[PK] id
title
[FK] featured_image
- files:
[PK] id
title
url
my model:
class TheFile extends \Eloquent
{
protected $table = 'files';
public function post() {
return $this->belongsTo('Post');
}
}
class Post extends \Eloquent
{
protected $table = 'posts';
public function file() {
return $this->hasOne('TheFile', 'id', 'featured_image');
}
}
thanks in advance.
Maybe I'm wrong but as I see it, you actually have the relationship the wrong way around here. If table X has one table Y then the FK field is on Y and related to the PK on X. But you have it the other way around.
As such you need to do one of two things:
Change your database to put post_id on files rather than having featured_image (points as file`.`id) on posts
Change your relationships to match your database structure:
class TheFile extends \Eloquent
{
protected $table = 'files';
public function post() {
return $this->hasOne('Post');
}
}
class Post extends \Eloquent
{
protected $table = 'posts';
public function file() {
return $this->belongsTo('TheFile');
}
}
Obviously with your various field changes too if you aren't going to change the tables.
The basic rule of thumb is that if a table has the FK it's the 'belongs to' table. The other table is either 'has one' or 'has many'. The slight exception to this rule is obviously 'belongs to many' where a table can relate to another table where neither has an FK - but even that's a specialised version of the same rule - X 'has many' X_Ys and Y 'has many' X_Ys and X_Y belongs to X and X_Y belongs to Y. So it's just syntactic sugar really.
I changed my table name to medias, and my model to Media. Then put these code into Post model . It's works. The name of tables, model and method must be similar.
public function media() {
return $this->belongsTo('Media', 'featured_image', 'id');
}