associative table for OneToMany relation - php

I'm working on a subtitles bot where:
A Movie has multiple subtitles (depending on quality and language)
A Series has multiple seasons with multiple episodes that have multiple subtitles (same as a movie)
These are my tables (Thanks to DaveRandom):
The problem is, as far as I know associative tables are for many-to-many relationships (correct me if I'm wrong), I'm kinda stuck here, especially with Eloquent's belongsToMany method:
class Subtitle extends Model {
public $guarded = [];
public $timestamps = false;
public function SeriesEpisodes()
{
return $this->belongsToMany('SeriesEpisode', null, null, 'series_episodes_subtitle');
}
public function Movie()
{
return $this->belongsToMany('Movie');
}
}
But the problem is, A Subtitle belongsToOne Episode, whereas an Episode might have many subtitles.
I was wondering how one could use associative tables for such structure.
Or should I change the structure?

So what I was trying to achieve is possible with polymorphic relationships,
2 associative tables are removed and instead 2 fields are added to subtitles table:
ex: parent_type, parent_id
then I can use:
subtitles:
class Subtitle extends Model {
public $guarded = [];
public $timestamps = false;
public function Parent()
{
return $this->morphTo();
}
}
series_episodes:
class SeriesEpisode extends Model {
public $timestamps = false;
public $guarded = [];
public function Subtitles()
{
return $this->morphMany('Subtitle', 'Owner');
}
}
movies:
class Movie extends Model {
public $timestamps = false;
public $guarded = [];
public function Subtitles()
{
return $this->morphMany('Subtitle', 'Owner');
}
}
Hope it helps others.

Related

How to get only active element from many to many relationship with translation in laravel

I have a problem with a many to many relationship and the translations of the terms.
I have 4 tables:
products
- id, price, whatever
products_lang
- id, product_id, lang, product_name
accessori
- id, active
accessori_lang
- id, accessori_id, lang, accessori_name
I'm trying to assign accessories to products with an intermediate table named:
accessori_products
this is the model for Product:
class Product extends Model {
protected $table = 'products';
public function productsLang () {
return $this->hasMany('App\ProductLng', 'products_id')->where('lang','=',App::getLocale());
}
public function productsLangAll() {
return $this->hasMany('App\ProductLng', 'products_id');
}
public function accessori() {
return $this->belongsToMany('App\Accessori', 'accessori_products');
}
}
this is the model for productLng:
class ProductLng extends Model {
protected $table = 'products_lng';
public function products() {
return $this->belongsTo('App\Product', 'products_id', 'id');
}
}
Then I have the model for Accessori:
class Accessori extends Model {
protected $table = 'accessori';
public function accessoriLang() {
return $this->hasMany('App\AccessoriLng')->where('lang','=',App::getLocale());
}
public function accessoriLangAll() {
return $this->hasMany('App\AccessoriLng');
}
public function accessoriProducts() {
return $this->belongsToMany('App\Products', 'accessori_products', 'accessori_id', 'products_id');
}
}
And the model for AccessoriLng:
class accessoriLng extends Model {
protected $table = 'accessori_lng';
public function accessori() {
return $this->belongsTo('App\Accessori', 'accessori_id', 'id');
}
}
I get the results by this:
$products = Product::has('accessori')->with([
'productsLang ',
'accessori' => function ($accessori){
$accessori->with([
'accessoriLang'
]);
}
])->get();
return $products;
but I want to get only the active accessories something like where accessori.active = 1 but I really don't know where to put it. I've tried in different way but I'm stuck on it by 2 days.
IIRC you don't need a model for the intermediate table on your many to many relationships.
If you want to return Products where Accessori is active you can use whereHas on the Product model.
$prod = Product::whereHas('accessori', function($query) {
$query->where('active', 1);
})->get();
Where the $query param will be running on the Accessori model.
You can do the inverse as well with Accessori to Product.
$acessoris = Accessori::where('active', 1)->whereHas('accessoriProduct')->with(['accessoriLang', 'accessoriProducts.productsLang'])->get();

Array returning null value, many to many. laravel

I'm trying to retrieve data from many to many relationship.I have two tables :
companies: [cid,name,origin]
vehicle_types: [id, type]
their pivot table: companies_vehicle_types: companies_id,vehicle_types_id Relationship defined: In Companies:
class companies extends Model
{
//
protected $fillable = ['name','origin'];
protected $primaryKey = 'cid';
public function vehicles(){
return $this->hasOne('App\vehicles');
}
public function vehicle_types(){
return $this->belongsToMany('App\vehicle_types', 'companies_vehicle_types', 'companies_id', 'vehicle_types_id');
}
}
In vehicle_types
class vehicle_types extends Model
{
//
protected $fillable = ['type'];
public function vehicles(){
return $this->belongsTo('App\vehicles');
}
public function companies(){
return $this->belongsToMany('App\companies','companies_vehicle_types','vehicle_types_id','companies_id')->withTimestamps();
}
}
I want to retrieve companies where vehicle_types = specific type. How can i do that? I tried doing following in my controller:
$vehicle_types=vehicle_types::where('type','Bike')->get();
foreach ($vehicle_types as $vehicle_type) {
# code...
foreach ($vehicle_type->companies as $company) {
$brand[]=$company->pivot->name;
}
}
return $brand;
But it doesn't seem to be working. $vehicle_types is working fine and returning value. $brand is not returning any value.

Laravel 5 using pivot table with hasMany relationship

I'm making a poll system and I have two tables :
polls table : Has those fields (id,question,created_at,updated_at).
choices table : Has those fields (id,poll_id,choice).
And a pivot table named choice_poll : Has those fields (id,choice_id,poll_id,ip,name,phone, comment ,created_at,updated_at)
Poll Model :
class Poll extends Model
{
protected $table = 'polls';
protected $fillable = ['question'];
public $timestamps = true;
public function choices()
{
return $this->BelongsToMany('App\Choice')->withPivot('ip','name','phone','comment');
}
}
Choice Model :
class Choice extends Model
{
protected $table = 'choices';
protected $fillable = ['poll_id','choice'];
public $timestamps = false;
public function poll()
{
return $this->belongsTo('App\Poll')->withPivot('ip','name','phone','comment');
}
}
Now when I try to build this query it doesn't return the choices :
$poll->first()->choices()->get()
PS: There is many choices in the choices table associated with the first poll.
In this case you have Many To Many relationship so try to change belongsTo in :
public function poll()
{
return $this->belongsTo('App\Poll')->withPivot('ip','name','phone','comment');
}
To belongsToMany, and it will be :
public function poll()
{
return $this->belongsToMany('App\Poll')->withPivot('ip','name','phone','comment');
}
NOTE 1: You have to change BelongsToMany to belongsToMany note the B should be in lower case.
NOTE 2: You want the pivot table with timestapms create_at,updated_at as you mentioned in th OP so you have to use withTimestamps(); :
return $this->belongsToMany('App\Poll')
->withPivot('ip','name','phone','comment')
->withTimestamps();
//AND in the other side also
return $this->belongsToMany('App\Choice')
->withPivot('ip','name','phone','comment')
->withTimestamps();
Hope this helps.
This:
public function poll()
{
return $this->belongsTo('App\Poll')->withPivot('ip','name','phone','comment');
}
and
public function choices()
{
return $this->BelongsToMany('App\Choice')->withPivot('ip','name','phone','comment');
}
should be:
public function poll()
{
return $this->belongsToMany('App\Poll')->withPivot('ip','name','phone','comment');
}
and
public function choices()
{
return $this->belongsToMany('App\Choice')->withPivot('ip','name','phone','comment');
}

Ordering of nested relation by attribute with laravel

Hi there i'm trying to sort a collection by attribute of the relation.
This is my model
class Song extends \Eloquent {
protected $fillable = ['title', 'year'];
public function artist(){
return $this->hasOne('Artist','id', 'artist_id');
}
}
class SongDance extends \Eloquent {
protected $table = 'song_dances';
protected $fillable = ['rating'];
public function dance(){
return $this->belongsTo('Dance', 'dance_id');
}
public function song(){
return $this->belongsTo('Song', 'song_id');
}
}
class Dance extends \Eloquent {
protected $fillable = ['name'];
public function song_dances(){
return $this->hasMany('SongDance','dance_id','id');
}
public function songs(){
return $this->belongsToMany('Song', 'song_dances', 'dance_id', 'song_id');
}
}
this is how far i'm by now:
$dance = Dance::find(1);
$songs = $dance->songs()
->with('artist')->whereHas('artist', function ($query) {
$query->where('urlName','LIKE','%robbie%');})
->where('song_dances.rating', '=', $rating)
->orderBy('songs.title','asc')
->where('songs.year', '=', 2012)
->get();
Yeah i just could add a ->sortBy('artist.name'); to the query, but he result-collection can be quite big (about 6000 items) therefore i would prefer a databased sorting.
is there a possibility to do this?
Since Eloquent's relations are all queried separately (not with JOINs), there's no way to achieve what you want in the database layer. The only thing you can do is sort the collection in your app code, which you've already dismissed.
If you feel you must sort it in the database then you should write your own join queries instead of relying on Eloquent's relations.

Laravel 4 Eloquent one-to-many relations with morph

I'm pretty new to Laravel and Eloquent, so this could easily be something trivial but anyways I've been missing a good solution so far. So heres my problem:
I have a main gallery and i want the user to be able to upload any images or videos that he needs into that main gallery and select images/videos from that gallery to be shown elsewhere on the website (basically what i'm doing is centralising multimedia content all in one place).
Using deduction (with all my poor knowledge of Eloquent) i found this as best solution for me:
//Gallery Model
class Gallery extends Eloquent {
protected $table = 'gallery';
protected $guarded = array();
public static $rules = array();
public function images() {
return $this->morphMany('Image', 'imageable');
}
public function videos() {
return $this->morphMany('Video', 'videoable');
}
}
//About Orchestra Model
class OrchestraAbout extends Eloquent {
protected $table = 'orchestra_about';
protected $guarded = array();
public static $rules = array();
public function images() {
return $this->morphMany('Image', 'imageable');
}
public function videos() {
return $this->morphMany('Video', 'videoable');
}
}
//Image Model
class Image extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function imageable()
{
return $this->morphTo();
}
}
//Video Model
class Video extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function videoable()
{
return $this->morphTo();
}
}
And when inserting into database i simply duplicate the row and only change the imageable_id /videoable_id and imageable_type/videoable_type to match the OrchestraAbout Model.
Anyone here knows of a better solution for this?
Thanks for all the smart answers! Cheers!

Categories