I am going to create polymorphic relations in Laravel but my tables are so old and it's naming conventions are not according to laravel. Can I do this and how ?
Of course you can set your table name and FK column names directly.
Look over Realtion docs and if necessary in Laravel API or source code
If you have
posts
id - integer
title - string
body - text
comments
id - integer
post_id - integer
body - text
likes
id - integer
likeable_id - integer
likeable_type - string
Then your code will be
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Like extends Model
{
/**
* Get all of the owning likeable models.
*/
public function likeable()
{
return $this->morphTo('likeable', 'likeable_type', 'likeable_id');
}
}
class Post extends Model
{
/**
* Get all of the post's likes.
*/
public function likes()
{
return $this->morphMany('App\Like', 'likeable', 'likeable_type', 'likeable_id');
}
}
class Comment extends Model
{
/**
* Get all of the comment's likes.
*/
public function likes()
{
return $this->morphMany('App\Like', 'likeable', 'likeable_type', 'likeable_id');
}
}
Related
I'm stuck for hours with one of those issues where a fresh set of eyes might help. I just can't understand what's missing.
I'm connecting a model called User_ativo and defining two one-to-many relations to models Instituicao and Tipo_Ativo.
My database is simple.
Table user_ativo has columns "tipo_ativo_id" and "instituicao_id". I have a test row where both are set to 1. Both my tables instituicoes and tipo_ativos have only "id" and a string field "nome" (name). Both have a record with id == 1.
User_ativo.php:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User_ativo extends Model
{
public function tipo(){
return $this->belongsTo('App\Tipo_ativo');
}
public function instituicao(){
return $this->belongsTo('App\Instituicao');
}
}
Instituicao.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Instituicao extends Model
{
protected $table = 'instituicoes';
public function user_ativos(){
return $this->hasMany('App\User_ativo');
}
}
Tipo_ativo.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Tipo_ativo extends Model
{
protected $table = 'tipo_ativos';
public function user_ativos(){
return $this->hasMany('App\User_ativo');
}
}
My controller method that fetches the date goes as follow:
public function index()
{
$ativos = User_ativo::with('tipo', 'instituicao')->get();
return view('ativos.index', compact('ativos'));
}
Now here's where it gets interesting, for some reason I can't figure out, when I echo the $ativos variable in my view I get this:
[{"id":1,"user_id":1,"instituicao_id":1,"tipo_ativo_id":1,"tipo":null,"instituicao":{"id":1,"nome":"Banco do Brasil"}}]
So, weirdly my relationship with the Instituicao model works, but the one with Tipo_ativo returns null.
I'm pretty confident someone will point out some dumb and obvious mistake in all of this, but I can't for the life of me understand why one works and the other doesn't since they're pretty much the same thing.
Your relationships names are not according to laravel convention.
Read below function and provide foreign_key and local_key/owner_key to your relationships then it will work
public function belongsTo($related, $foreignKey = null, $ownerKey = null, $relation = null){}
If we do not follow laravel convention while creating relationships then we have to tell it that these are the foreign and local keys that should be used.
Read more here
class User_ativo extends Model{
public function tipo(){
return $this->belongsTo('App\Tipo_ativo','user_ativo_id'); //second parameter is foreign_key_of_User_avito_table_here
}
public function instituicao(){
return $this->belongsTo('App\Instituicao','user_ativo_id'); //second parameter is foreign_key_of_User_avito_table_here
}
}
class Instituicao extends Model
{
protected $table = 'instituicoes';
public function user_ativos(){
return $this->hasMany('App\User_ativo','instituicao_id'); //second parameter is foreign key of Instituicao model
}
}
class Tipo_ativo extends Model
{
protected $table = 'tipo_ativos';
public function user_ativos(){
return $this->hasMany('App\User_ativo','tipo_ativo_id'); //second parameter is foreign key of Tipo_ativo model.
}
}
I have this class. Which has a morphedByMany relationship
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class OrdenDeElaboracion extends Model
{
// ... Stuff goes here
/**
* Get all of the model variants that are assigned this production order.
*/
public function variantes()
{
return $this->morphedByMany('App\Variante', 'elaborable')
->withPivot(['cantidad', 'informacion_adicional', 'informacion_adicional_fabricacion', 'informacion_adicional_instalacion'])
->using('App\Elaborable');
}
}
But now I want that other class App\Elaborable to have relationship with this one App\Estatus so every "variante (product variant)" on the "elaborable (items with the ability to be elaborated)" table could have a "estatus (status)"
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\MorphPivot;
class Elaborable extends MorphPivot
{
// ... more stuff here
/**
* The relations to automatically populate to the model.
*
* #var array
*/
protected $with = ['estatus'];
/**
* Get the status records associated with the order.
*/
public function estatus()
{
return $this->morphMany('App\Estatus', 'modelo');
}
}
But this does not work for me I don't know why.
The MorphPivot class extends from Model so I can't figure out what am I doing wrong
Update: Code Example
Route::get('/get_test', function () {
$orden_de_elaboracion = OrdenDeElaboracion::findOrFail(1);
return $orden_de_elaboracion->variantes->map(function ($variante) {
$newEstatus = new Estatus([]);
$variante->estatus()->save($newEstatus);
return $newEstatus->id;
});
});
With that I get this. Like if the relationship wasn't defined.
I don't know if this has something to do -> https://github.com/laravel/framework/issues/17770
Using the laravel ducmunet example :
There are there table like
posts
id - integer
title - string
body - text
videos
id - integer
title - string
url - string
comments
id - integer
body - text
commentable_id - integer
commentable_type - string
And 3 model (post, command and video) .
Comment model has morphTo relation with post and video.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* Get all of the owning commentable models.
*/
public function commentable()
{
return $this->morphTo();
}
}
class Post extends Model
{
/**
* Get all of the post's comments.
*/
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
}
class Video extends Model
{
/**
* Get all of the video's comments.
*/
public function comments()
{
return $this->morphMany('App\Comment', 'commentable');
}
}
Is there a solution for insert new record into model related to the comment (video or post model).
For example if i have an instace of comment model by this instrument :
$nc = comment::find(3);
Now how can i add new post or video related to $nc comment.
I can't use save method because save method argument is an instance of post or video model but i don't know which model related to $nc comment by polymorphic.
in another word i will add a new post or video to a comment existing ($nc).
You could always use associate() and dissociate() just like BelongsTo relation. For example:
$video = Video::find(1);
$comment = new Comment();
$comment->commentable()->associate($video);
$comment->save()
Just a reminder, one comment belongs to a single video or post. Happy coding!
Improving Bagus answer with the Correct way to use associate()
$video = Video::find(1)
$comment = new Comment();
$comment->commentable()->associate($video);
$comment->save();
We are able to create Eloquent models for tables. But how Laravel knows to which table to associate a model with? Do we have something similar to hbm.xml(mapping file we use for Hibernate) which says this model means this table.
The table name is a protected property:
class User extends Eloquent {
protected $table = 'my_users';
}
Laravel Docs
You can manually override the table name as the above answer states.
Its just a protected member of the Model.php class.
class User extends Eloquent {
protected $table = 'my_users';
}
Otherwise, a lowercase, plural format is automatically used, based on the classname of the Model. (class_basename($this))
As shown here... (Illuminate/Database/Eloquent/Model.php)
/**
* Get the table associated with the model.
*
* #return string
*/
public function getTable()
{
if (isset($this->table)) {
return $this->table;
}
return str_replace('\\', '', Str::snake(Str::plural(class_basename($this))));
}
I would like to create a relationship between 2 tables with eloquent but i can't find exactly how to proceed...
Here are my 2 models with relationship :
Table "etablissement":
<?php class Etablissement extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'etablissement';
public function annulation()
{
return $this->hasMany('Annulation');
}}
Table "annulation":
<?php class Annulation extends Eloquent {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'annulation_remboursement';
public function etablissement ()
{
return $this->belongsTo('Etablissement');
}}
In the "Etablissement" table there is an id for each etablissement (id_etablissement) and in the "annulation" there is a column with the id_etablissement. How can i return in my controller a relation in order to have the etablissement's name with the annulation->id_etablissement :
class AnnulationsController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
}
It should be something like this within your index method:
$annulation = Annulation::find(1);
$annulation->etablissement->name
The annulation_remboursement table should have a establissement_id field.
Perhaps the error may be in the keys of the relation.
In https://laravel.com/docs/4.2/eloquent#one-to-one we see:
Take note that Eloquent assumes the foreign key of the relationship based on the model name. In this case, Phone model is assumed to use a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method. Furthermore, you may pass a third argument to the method to specify which local column that should be used for the association:
return $this->hasOne('Phone', 'foreign_key');
return $this->hasOne('Phone', 'foreign_key', 'local_key');
[...] One To Many: Again, you may override the conventional foreign key by passing a second argument to the hasMany method. And, like the hasOne relation, the local column may also be specified:
return $this->hasMany('Comment', 'foreign_key');
return $this->hasMany('Comment', 'foreign_key', 'local_key');
* You should also checkout Defining The Inverse Of A Relation at the same page.
So, in your case you have a key named id_etablissement but Laravel is searching for etablissement_id. If you wish to override this behaviour and specify a key you should do something like:
protected $table = 'etablissement';
public function annulation()
{
return $this->hasMany('Annulation','id_etablissement');
}
and according to "The Inverse Of A Relation"
protected $table = 'annulation_remboursement';
public function etablissement ()
{
return $this->belongsTo('Etablissement','id_etablissement');
}
Note that I didn't put any of the local keys, but those will be the third parameter of the relation.