Good morning, I am having a little trouble with model relationships in Eloquent, I need to link articles and images for those articles with an intermediate table. In the intermediate table I'd like to add the id's of both article and image, and I would like to retrieve all the images belonging to an article, what would be the best way to manage the relationship? Thanks in advance
You don't need to use pivot table since it's one-to-many relationship.
Just use hasMany() relation:
public function images()
{
return $this->hasMany('App\Image');
}
And then use eager loading to load all images with article:
$article = Article::with('images')->where('id', $articleId)->first();
You can use morphMany() relationship (Polymorphic Relationship) to solve your problem like this:
UPDATE: The table structure goes like this:
- articles
- id
- title
- content
- ...
- images
- id
- owner_id
- owner_type (Here there can be - Article, Auction, User, etc)
- name
- mime_type
- ...
Polymorphic relations allow a model to belong to more than one
other model on a single association. For example, imagine users of
your application can "comment" both posts and videos. Using
polymorphic relationships, you can use a single comments table for
both of these scenarios.
You models will look like this:
class Article extends Model
{
public function images()
{
return $this->morphMany(Image::class, 'owner');
}
}
class Image extends Model
{
public function owner()
{
return $this->morphTo();
}
}
To save multiple images to an article, you can do like:
$article->images()->create([... inputs_arr ...]);
and to fetch them, you can do this like:
$articleImages = Article::find($id)->images;
Hope this helps!
In Image model class
class Image extends Model
{
public function article()
{
return $this->belongsTo(Article::class);
}
}
Then you can access all the images that belong to Article as follows.
$image= Image::first();
Then for example when we want to get the name of the image that belongs to Article.
$imageName = $image->article->name;
Related
I have a table which will be addressed by a model in Laravel for stock movements. I would like to establish a relates to field which can be related to a number of different tables.
As per the attached diagram I need the relates_to_id to be one of the following...
Purchases.purchase_id
Invoices.invoice_id
And there may be more being added in the future as we find more records which may result in a stock movement occurring.
Now I have added a relates_to_type field to the database schema for the stock movements table so that I can specify which record type the particular movement record relates to. But I have been struggling to figure out how to establish the model for such a relationship to work or if it will even work that way or if I will need to have a separate field for each type of relationship as I wish to be able to read the related record through the ORM's related record scheme.
This is the exact use case for polymorphic relations, they supply your model as you wished for with an column indicating the relation type and the id of the related model.
See also this example from the laravel documentation:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Image extends Model {
/**
* Get all of the owning imageable models.
*/
public function imageable() {
return $this->morphTo();
}
}
class Post extends Model {
/**
* Get the post's image.
*/
public function image(){
return $this->morphOne('App\Image', 'imageable');
}
}
class User extends Model {
/**
* Get the user's image.
*/
public function image()
{
return $this->morphOne('App\Image', 'imageable');
}
}
Here every user and post can have an image and every image has an imageable which is either a user or a post.
I'm playing with laravel for the first time and i'm a little confused on how to achieve a link table relationship. I have 3 tables: Tank, TankContent and Content
I have the following models:
Tank:
class Tank extends Model
{
public function getTankContent()
{
return $this->hasMany('App\TankContent', 'tankID', 'tankID');
}
}
TankContent:
class TankContent extends Model
{
public function getTank()
{
return $this->belongsTo('App\Tank', 'tankID', 'tankID');
}
public function getContent()
{
return $this->belongsTo('App\Content', 'contentID', 'contentID');
}
}
Content:
class Content extends Model
{
public function getContentTanks()
{
return $this->hasMany('App\ContentTank', 'contentID', 'contentID');
}
}
Now im trying to call say tankID 2 and get all the content details inside of that
$content = Tank::find(2);
$items = $content->getTankContent;
This will list me the content. But then how do i go about linking the results to getContent() from the TankContent model?
Thanks in advance. Hopefully I just need it explaining and then it will all click.
p.s i have tried reading the https://laravel.com/docs/5.5/eloquent-relationships#many-to-many and im still stumped!
TankContent isn't required, the belongsToMany relationship methods belong on the Tank and Content models.
https://laravel.com/docs/5.5/eloquent-relationships#many-to-many
From here you can see there is no RoleUser model, the models are only Role and User. The belongsToMany relationship on those models defines that the intermediate, or pivot, table is role_user.
You can additionally define other fields on that relationship with withPivot() chained onto the belongsToMany method. (read "Retrieving Intermediate Table Columns"). Therefore, there is likely no reason to have a separate model for the intermediate/pivot table.
I have already checked this official example http://laravel.com/docs/eloquent#many-to-many-polymorphic-relations
but I still confused because I may have a different case.
I have a DetailsAttribute model which deals with details_attribute table.
I have a Action model witch deals with action table.
The relationship between them is many to many.
So I created a new table details_attribute_action with model DetailsAttributeAction
My DetailsAttribute model should have:
public function actions(){}
My Actions model should have:
public function detailsAttributes(){}
and my DetailsAttributeAction model should have functions but I don't know what they are.
My question is what is the code inside the previous functions please? and should really the DetailsAttributeAction have functions of not?
What you're looking for is a Many-to-Many relation, not one that is polymorphic.
http://laravel.com/docs/eloquent#many-to-many
Your code should look something like this:
class DetailsAttribute extends Eloquent {
// ...
public function actions()
{
// Replace action_id and details_attribute_id with the proper
// column names in the details_attribute_action table
return $this->belongsToMany('Action', 'details_attribute_action', 'details_attribute_id', 'action_id');
}
}
class Action extends Eloquent {
// ...
public function detailsAttributes()
{
return $this->belongsToMany('DetailsAttribute', 'details_attribute_action', 'action_id', 'details_attribute_id');
}
}
You won't have to worry about how to create the DetailsAttributeAction model in Laravel. It's simply a table to map the Many-to-Many relationships you've created.
I have two models in my Laravel 4.2 web application, User and Group. A user can be a member of many groups, and a group can have many members. Both models are thus joined with a many-to-many relationship:
<?php
class User extends Eloquent {
public function groups()
{
return $this->belongsToMany('Group');
}
}
class Group extends Eloquent {
public function users()
{
return $this->belongsToMany('User');
}
}
?>
One of my API resources is /groups, which lists all groups available within the app:
<?php
$groups = Group::with('users')->all();
?>
This works, however in the JSON response each user contains all fields from the users table (excluding of course those in the $hidden attribute). I would like this relationship to return only a specific set of fields instead of the whole table.
In other relationship types I can easily achieve this with the following statement (assume now that users may belong to only one group):
<?php
public function users()
{
return $this->hasMany('User')->select(['id', 'first_name', 'last_name']);
}
?>
However the above does not seem to work with many-to-many relationships. I came across this question which apparently refers to the same issue and it looks like this was not possible in Laravel 4.1. The author of the chosen answer, tptcat, provides a link to an issue on Laravel's Github issue tracker, but the link is no longer working and I couldn't figure whether this issue is still open in 4.2.
Has anybody come across this and successfully managed to solve it?
{
return $this->belongsToMany('User')->select(array('id', 'name'));
}
use this
The all method takes in an array of column names as a parameter.
If you look at the source, it takes * (which means everything) by default.
https://github.com/laravel/framework/blob/4.2/src/Illuminate/Database/Eloquent/Model.php#L624-L629
You can pass in the columns that you needed and it should return the results only with the specified columns.
<?php
$groups = Group::with('users')->all(array('first_column', 'third_column'));
Use like this.
<?php
class User extends Eloquent {
public function groups()
{
return $this->belongsToMany('Group')->select(array('id', 'name'));
}
}
class Group extends Eloquent {
public function users()
{
return $this->belongsToMany('User')->select(array('id', 'name'));
}
}
?>
Instead of selecting column in relationship, you can select column as below:
$groups = Group::with('users:id,first_name,last_name')->all();
And when you are selecting column in relationship, make sure that you are selected foreign key of relation table
I created an Seo table with Eloquent's polymorphic relationship. So for Seo table, I have something like this
title
description
seoble_id
seoble_type
timestamps
Then for all the models that will have custom SEO, I added the morphOne relationship while the Seo model will have morphMany relationship. So for Post model I will have something like this
namespace App\Models;
class Post extends Eloquent {
public function seo()
{
return $this->morphOne('App\Models\Seo', 'seoble');
}
}
However, the relationship will only work if I the seoble_type is filled with the fully namespaced model class name. So the seoble_type must be 'App\Models\Post' (model name like 'Post' or table name like 'posts' will not work) for the polymorphic relationship to work. The problem is, if I somehow want to change the namespace, I will have to update all the seo table to update the seoble_type field, which will be a hassle.
Now, before I tried the polymorphic relationship, I usually created the equivalent table something like this:
title
description
object_id
type
timestamps
And for the relationship, for each model I will have something like this:
namespace App\Models;
class Post extends Eloquent {
public function seo()
{
return $this->hasOne('App\Models\Seo', 'object_id')->where('type', 'post');
}
}
My question is, are these 2 methods equivalent?
if you using morph it mean you wish single table can be used as relations to any table with indication by object_id and type_id. so the answer for your question, is not equivalent.
I thought at your case (for save seo table) the recommended ways as my opinions is using morphOne.
and then, for your problem in morph you can fill your seoable_type with whatever do you like, not should fill with your namespace
here is simple code when using morph :
namespace App\Models;
class Seo extends Eloquent {
public function seoable()
{
return $this->morphTo();
}
public function post()
{
return $this->belongsTo('App\Models\Seo', 'seoable_id');
}
}
/*----*/
namespace App\Models;
class Post extends Eloquent {
public function getSeo($type)
{
return $this->morphOne('App\Models\Seo', 'seoable');
}
}
// you can using like this :
$seo = \Seo::where('seoable_type', 'post');
$seo->post->first();
// or like this :
$post = \Post::with('getSeo')->findOrFail($id)->toArray();
wish this helped you.