Laravel many layer eloquent relationship - php

I have following eloquent.
Volume,
Issue,
Category,
Article,
ArticleTranslation,
Volume can have many issues.
Issue can have many categories.
Category can have many articles.
Article can have many translation.
SO how can i get Volume from Article/ArticleTranslation?

First your models.
..
class Volume extends Model {
public function issues() {
return $this->hasMany(Issue::class);
}
}
class Issue extends Model {
public function volume() {
return $this->belongsTo(Volume::class);
}
public function categories() {
return $this->hasMany(Category::class);
}
}
class Category extends Model {
public function issue() {
return $this->belongsTo(Issue::class);
}
public function articles() {
return $this->hasMany(Article::class);
}
public function articlesTranslated() {
return $this->hasMany(ArticleTranslated::class);
}
}
class Article extends Model {
public function category() {
return $this->belongsTo(Category::class);
}
}
..
Then in your code:
..
$articles = Articles::all();
$volumes = [];
foreach ($articles as $article) {
$volumes[] = $article->category->issue->volume;
}
..
Docs

Related

Laravel Polymorphic Relations returns NULL

I've read many posts about this issue but none of them works for me. I have a 'ISA' relationship in my database. A person can be either a Patient or a Nurse:
class Person extends Model
{
protected $table = 'persons';
public function commentable()
{
return $this->morphTo();
}
}
class Patient extends Model
{
public function persons()
{
return $this->morphMany('App\Person', 'commentable');
}
}
class Nurse extends Model
{
public function persons()
{
return $this->morphMany('App\Person', 'commentable');
}
}
This is my tables and the data inside them:
And this is my Route:
Route::get('person', function () {
$person = Person::find(1)->commentable();
return json_decode(json_encode($person), true);
});
I get an empty array!
You have to access the relationship as a property:
$person = Person::find(1)->commentable;

Laravel 5.4 can't get relation of elloquent model

I have filters which belong to filter groups
Filter.php:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Filter extends Model
{
public function group()
{
return $this->belongsTo('App\FilterGroup');
}
public function products()
{
return $this->belongsToMany('App\Product', 'product_filters');
}
public function categories()
{
return $this->belongsToMany('App\Filter', 'category_filter');
}
}
And categories which have many to many relationship with the filters
Category.php:
namespace App;
use App\Events\CategoryDelete;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $events = [
'deleting' => CategoryDelete::class
];
protected $table = 'categories';
public function parent()
{
return $this->belongsTo('App\Category', 'parent_id');
}
public function children()
{
return $this->hasMany('App\Category', 'parent_id');
}
public function parents()
{
$parentCategories = collect([]);
$parent = $this->parent;
while (!is_null($parent)) {
$parentCategories[] = $parent;
$parent = $parent->parent;
}
return $parentCategories->reverse();
}
public function products()
{
return $this->hasMany('App\Product');
}
public function filters()
{
return $this->belongsToMany('App\Filter', 'category_filter');
}
public function hasFilter($filter_id)
{
foreach ($this->filters as $filter) {
if ($filter->id == $filter_id) {
return true;
}
}
return false;
}
public function getFilterGroups()
{
$filterGroups = collect([]);
foreach ($this->filters as $filter) {
if (!$filterGroups->has($filter->group->id)) {
$filterGroups[$filter->group->id] = $filter->group;
}
}
return $filterGroups;
}
}
And in the category view I want to display the filters along with their filter group but when I try the following:
#foreach($category->filters as $filter)
{{ $filter->group->name }}
<br>
#endforeach
It throws the Trying to get property of non-object exception
Why can't I get the group of the filter?
I changed the group() method inside the Filter model to filterGroup and now when I call $filter->filterGroup it works fine. I dont know why, maybe group is some reserved word or something.

Getting all products from catalog laravel

I have 3 tables:
product
*id
category_id
name
...
category
*id
catalog_id
name
...
catalog
*id
name
...
and 3 models
class Catalog extends Model
{
public function category()
{
return $this->hasMany('App\Category');
}
}
class Category extends Model
{
public function product()
{
return $this->hasMany('App\Product');
}
public function catalog()
{
return $this->belongsTo('App\Catalog');
}
}
class Product extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
I'm working with data through repositories
example:
abstract class Repository
{
protected $model = false;
public function get($select = '*',$where = false, $take = false)
{
$builder = $this->model->select($select);
if($where)
{
$builder->where($where);
}
if($take)
{
$builder->take($take);
}
return $builder->get();
}
}
class ProductsRepository extends Repository
{
public function __construct(Product $products)
{
$this->model = $products;
}
public function getNewProducts()
{
return $this->get('*',['is_recommended' => 1],Config::get('settings.recommended_products_count'));
}
public function getProductsFromCategory($category_id)
{
return $this->get('*',['category_id' => $category_id]);
}
}
So, the question is: how can I get all products from catalog by it's id?
in raw sql it'll look like:
select * from products
join categories
on categories.id=products.category_id
join catalogs
on catalogs.id=categories.catalog_id
where(catalogs.id=1)
but how can I get them in my situation?
First, define a relation between catalogue and products in Catalog model:
public function products()
{
return $this->hasManyThrough('App\Product', 'App\Category', 'catalog_id', 'category_id', 'id');
}
Now, you should be able to get all products for given catalog with:
$products = Catalog::with('products')->find($id)->products;
You can find out more about has-many-through relation here: https://laravel.com/docs/5.4/eloquent-relationships#has-many-through

Laravel Eloquent Multiple Join

I have a table albums, each album has multiple songs, artworks, and can belong to a number of series.
Each of the songs can have lyrics from another table.
So far I have :
routes.php
Route::get('get_albums', function() {
return Album::with('songs', 'artworks', 'series')->get();
});
Album.php model
<?php
class Album extends Eloquent {
protected $table = 'albums';
public function songs()
{
return $this->hasMany('Song');
}
public function artworks()
{
return $this->hasMany('Artwork');
}
public function series()
{
return $this->hasMany('Serie');
}
}
Song.php model
<?php
class Song extends Eloquent {
public function album()
{
return $this->belongsTo('Album');
}
public function lyric() {
return $this->hasOne('Lyric');
}
}
Artwork.php model
<?php
class Artwork extends Eloquent
{
public function album()
{
return $this->belongsTo('Album');
}
}
Serie.php model
<?php
class Serie extends Eloquent {
public function album()
{
return $this->belongsTo('Album');
}
}
Lyric.php model
<?php
class Lyric extends Eloquent {
public function song()
{
return $this->belongsTo('Song');
}
}
This gives me back all the albums with their songs, artworks, and series. Trying to figure out how to do the 2nd join to get the lyrics for the songs.
You can try
Route::get('get_albums', function() {
return Album::with('songs.lyric', 'artworks', 'series')->get();
});

Chain of hasMany or hasManyThrough through N models

How can I get all the submissions belongs to a particular user?
Trying this:
$user=User::find(1);
dd($user->submissions);
Throwing error:
Call to undefined method Illuminate\Database\Query\Builder::hasMany()
Will I have to loop through the models?
Here are the models:
class User extends Eloquent implements ConfideUserInterface, BillableInterface
{
public function categories()
{
return $this->hasMany('Category');
}
public function forms()
{
return $this->hasManyThrough('App\Models\Form', 'Category');
}
public function submissions()
{
return $this->hasMany('Category')->hasMany('Form')->hasMany('Submission');
}
}
class Category extends \Eloquent {
public function user()
{
return $this->belongsTo('User');
}
public function forms()
{
return $this->hasMany('App\Models\Form');
}
public function submissions()
{
return $this->hasManyThrough('Submission', 'App\Models\Form', 'id', 'form_id');
}
}
namespace App\Models;
class Form extends \Eloquent {
public function user()
{
return $this->category->user();
}
public function category()
{
return $this->belongsTo('Category');
}
public function submissions()
{
return $this->hasMany('Submission');
}
}
class Submission extends \Eloquent {
public function user()
{
return $this->form->category->user();
}
public function category()
{
return $this->form->category();
}
public function form()
{
return $this->belongsTo('App\Models\Form');
}
}
That doesn't really work that way with chaining relations...
What you can do, is this:
$submissions = Submission::whereHas('form.category.user', function($q){
$q->where('id', 1);
})->get();
Note that whereHas with nested relationships has only been added in the latest Laravel 4 release. Make sure to composer update.
If i'm not getting your question wrongly, you need to define relationship correctly.
According to laravel 4.2 you can use below kind of code to define relations:
class User extends \Eloquent implements ConfideUserInterface, BillableInterface{
//...
public function submissions(){
return $this->hasMany('Submission');
}
}
//...
class Submission extends \Eloquent {
public function user()
{
return $this->belongsTo('User');
}
//...
}
To further reading take a look at: http://laravel.com/docs/4.2/eloquent#relationships

Categories