get data from multiple relations in laravel eloquent - laravel

I have the following tables pharmacies,categories,medicines and I am using laravel
the relations are like this
pharmacy have many medicines and the medicine belongs to one category
the medicines table have pharmacy_id and category_id columns + other columns
I want to show a pharmacy by id and it should return an object of pharmacy with categories, each category have object of medicines in this pharmacy. If there is no medicine in any category, then it should not be returned.
I think its a model relations issue
any idea could be useful
the category model
class Category extends Model
{
protected $table = 'categories';
public function pharmacies()
{
return $this->belongsToMany(Pharmacy::class, 'pharmacy_category', 'category_id', 'id');
}
public function medicines()
{
return $this->hasMany(Medicine::class);
}
}
the pharmacy model
class Pharmacy extends Model
{
use SoftDeletes;
protected $table = 'pharmacies';
protected $appends = ['favourite'];
public function categories()
{
return $this->belongsToMany(Category::class,'pharmacy_category','pharmacy_id','id');
}
public function getFavouriteAttribute()
{
if (!Auth::check()) {
return 0;
}
return (FavouritePharmacy::where('user_id', Auth::user()->id)->where('pharmacy_id', $this->id)->count() == 1) ? 1 : 0;
}
}
the medicine model
class Medicine extends Model
{
protected $appends = ['favourite'];
public function orders()
{
return $this->belongsToMany(Order::class);
}
public function getFavouriteAttribute()
{
if (!Auth::check()) {
return 0;
}
return (FavouriteMedicine::where('user_id', Auth::user()->id)->where('medicine_id', $this->id)->count() == 1) ? 1 : 0;
}
}

If you want to display pharmacy info, categories with medicines, with these relationships I'd do this:
$pharmacy = Pharmacy::find($id);
$categoriesWithMedicines = Category::whereHas('medicines', function($q) use($id) {
$q->where('pharmacy_id', $id);
})
->with(['medicines' => function($q) use($id) {
$q->where('pharmacy_id', $id);
}])
->get();
Then in a view, you'll have a pharmacy object and a list of categories with medicines which belong to the pharmacy:
#foreach ($categoriesWithMedicines as $category)
{{ $category->name }}
#foreach ($category->medicines as $medicine)
{{ $medicine->name }}
#endforeach
#endforeach

Related

Trying to retrieve posts from table by category slug

Hello i am trying to loop posts that are associated to each category by the slug. It works when i use the ids but when i change my controller function to search by slug it retrieves the slug but does not load the foreach loop.
I have tried so many methods and i don't know where i am going wrong please help.
Category Model :
protected $table = 'post_categories';
public function posts()
{
return $this->hasMany('App\Post', 'id', 'name', 'catslug');
}
Post Model
public function user()
{
return $this->belongsTo('App\User');
}
public function postCategories()
{
return $this->belongsTo('App\PostCategory');
}
Controller
public function getPostCategory($catslug) {
$postCategories = PostCategory::with('posts')
->orderBy('name', 'asc')
->where('catslug', '=', $catslug)
->first();
return view ('articles.category.categoriesposts')->with('postCategories', $postCategories);
}
Route
Route::get('articles/category/{catslug}', [
'uses' => 'ArticlesController#getPostCategory' ,
'as' => 'PostCategory'
] );
View
#foreach($postCategories->posts as $post)
<h4>{{ substr($post->title, 0, 50) }}</h4>
<p>{{ substr($post->body, 0, 90) }}</p>
#endforeach
When i use id there is no problem i cant see what i am doing wrong any feedback will be truly appreciated
Thanks
Ash
Save category id in posts table insted of category name or slug.
Change in post category model:
public function posts()
{
return $this->hasMany('App\Post', 'category_id');
}
Your controller method:
public function getPostCategory($catslug)
{
$postCategories = PostCategory::with('posts')->where('catslug', $catslug)->first();
return view('articles.category.categoriesposts')->with('postCategories', $postCategories);
}
If you want to order posts by name then add orderBy() in relationship :
public function posts()
{
return $this->hasMany('App\Post', 'category_id')->orderBy('name', 'asc');
}

Laravel Eloquent many to many relationship with translation

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');
}
}
the last model is for the relationship between the two tables above:
class ProductAccessori extends Model {
protected $table = 'accessori_products';
public function accessoriProducts() {
return $this->belongsTo('App\Product', 'accessori_id', 'products_id');
}
}
I'm trying to get the accessories of each product and to get also the translation but I'm having a lot of problem with this.
It's my first time with a many to many relation with translations too.
Can anyone put me on the right direction?
controller
$products = Product::has('accessori')->with([
'productsLang ',
'accessori' => function ($accessori){
$accessori->with([
'accessoriLang'
]);
}
])->get();
return $products;
you'll get products with accessori that has accessoriLang.

Laravel Nesting to 4 levels not working

I have relationships like the following:
Category -> Subcategory -> Product -> Price
A Category contains X Subcategories.
A Subcategory contains X Products.
A Product contains X Prices (New Price, Old Price, One Record per Price Change)
I wanted to do the following:
#foreach($categories as $category)
[...]
#foreach($category->subcategories as $subcategory)
[...]
#foreach($subcategory->products as $product)
[...]
#foreach($product->prices as $price)
[... #endforeach x4 ...]
The 3 first levels are working. When using the 4th however ($product->prices) I get an Trying to get property of non-object error.
The relationships in the Models:
Category.php
class Category extends Model
{
public function subcategories()
{
return $this->hasMany('App\SubCategory');
}
}
SubCategory.php
class SubCategory extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
public function products()
{
return $this->hasMany('App\Product');
}
}
Product.php
class Product extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
public function subcategory()
{
return $this->belongsTo('App\SubCategory');
}
public function price()
{
return $this->hasMany('App\ProductPrice');
}
}
ProductPrice.php
class ProductPrice extends Model
{
public function product()
{
return $this->belongsTo('App\Product');
}
}
This is what I send to my View:
class PageController extends Controller
{
public function showMainPage()
{
$categories = Category::with('subcategories')->get();
$data = array(
"categories" => $categories,
);
return view('index')->with($data);
}
}
This worked fine, even with Products but began to have errors when using the ProductPrices.
As #GONG said, change your code for use eager load, this will run so much faster than use some foreaches.
See laravel docs: https://laravel.com/docs/5.3/eloquent-relationships#eager-loading

Laravel Eloquent group by with pivot table & relations

I have this platform I'm creating for foodtruck events. There is a pool of exhibitors who attend several events. Each foodtruck has it's own menu of dishes that they serve, in several categories.
The problem / what I'd like to achieve
I would like to make a menu for each event, looping through all
exhibitors (who attend) and then showing the dishes by category.
Something like this;
/menu/{eventid}
Dish category 1
dish from exhibitor A
dish from exhibitor B
Dish category 2
dish from exh A
dish from exh C
dish from exh D
...
Models
Event model
class Event extends Model
{
protected $table = "events";
public function exhibitors()
{
return $this->belongsToMany('App\Exhibitor', 'events_exhibitors');
}
Dish model
class Dish extends Model
{
//
protected $table = "dishes";
public function category()
{
return $this->hasOne('App\Category', 'id', 'category_id');
}
public function exhibitor()
{
return $this->belongsTo('App\Exhibitor');
}
}
Exhibitor model
class Exhibitor extends Model
{
protected $table = "exhibitors";
public function events()
{
return $this->belongsToMany('App\Event', 'events_exhibitors');
}
public function dishes()
{
return $this->hasMany('App\Dish');
}
}
Database structure
There is a pivot table to register which foodtrucks go to which events. So far, I think (hope) my relations are working. I hope this image shows enough;
What I've tried
I've tried several things but I think my insight in Laravel eloquent lacks to understand the logic behind this issue.
$dishes = Event::where('id', $id)
->with(['exhibitors.dishes' => function($q) {
$q->select('dishes.dish_data');
}])->get();
Or
$dishes = Event::with(array('exhibitor.dish') => function($query) use ($sub){
$query->where('name',$sub);}))->get();
I have absolutely no clue how to accomplish this by Eloquent or how this would work in the view.
Try something like this:
It will get all the ids of the exhibitors that are connected to the event.
Then it will get all categories where the connected dishes have an exhibitor_id that is in the array of exhibitor ids.
Category Model
class Category extends Model
{
protected $table = "categories";
public function dishes()
{
return $this->hasMany('App\Dish', 'category_id');
}
}
Controller Action
$event = Event::findOrFail($id);
$exhibitorIds = $event->exhibitors()->select('exhibitors.id')->get()->pluck('id')->all();
$categories = Category::whereHas('dishes', function($query) use ($exhibitorIds) {
$query->whereIn('exhibitor_id', $exhibitorIds);
})->with(['dishes' => function($query) use ($exhibitorIds) {
$query->whereIn('exhibitor_id', $exhibitorIds);
}])->get();
return view('events.menu', compact('event', 'categories') );
View
#foreach($categories as $category)
<h2>{{ $category->name }}</h2>
<ul>
#foreach($category->dishes as $dish)
<li>{{ $dish->dish_data }}</li>
#endforeach
</ul>
#endforeach

Laravel 4 many to many and polymorphic in one direction

I'd like a relationship between a few models that is a many to many and polymorphic in one direction, this is how I've solved it for now but it really bothers me to have it this way, I loose all attach(), detach() etc functionality and it should be a simple way to do this. Can't find any docs, examples or anything, all I've seen are just so basic.
<?php
use Illuminate\Database\Eloquent\Collection;
class Category extends Eloquent {
/*
public function categorizables() {
return $this->morphTo();
}
*/
public function categorizables(){
$categorizables = new Collection();
$categorizableRows = DB::table('categorizables')->where('category_id', $this->id)->get();
foreach ($categorizableRows as $categorizable) {
$class = $categorizable->categorizable_type;
$categorizables->add($class::find($categorizable->categorizable_id));
}
return $categorizables;
}
}
class Article extends Eloquent {
/*
public function categories() {
return $this->morphMany('Category','categorizable');
}
*/
public function categories(){
$categoryRows = DB::table('categorizables')
->where('categorizable_id', $this->id)
->where('categorizable_type', get_class($this))->get();
$categoryIds = array();
foreach ($categoryRows as $category) {
$categoryIds[] = $category->id;
}
return Category::find($categoryIds);
}
}
class Person extends Eloquent {
/*
public function categories() {
return $this->morphMany('Category','categorizable');
}
*/
public function categories(){
$categoryRows = DB::table('categorizables')
->where('categorizable_id', $this->id)
->where('categorizable_type', get_class($this))->get();
$categoryIds = array();
foreach ($categoryRows as $category) {
$categoryIds[] = $category->id;
}
return Category::find($categoryIds);
}
}
/*
Table categorizables
id
category_id
categorizable_type (Possible "Article" or "Person" in this case)
categorizable_id (id of Article or Person)
Table categories
id
name
Table articles
id
name
content
Table People
id
name
content
*/

Resources