Getting all products from catalog laravel - php

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

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();

One to Many Relationship - Laravel & Mysql

In my application, Users can have many products. Now, i am trying to display the users phone number for a every displayed products.
In my products table, there is a column user_id for the respective users.
This is how my model looks like
User Model
public function products()
{
return $this->belongsTo('Models\Database\User','user_id');
}
Product Model
class Product extends BaseModel
{
protected $fillable = ['user_id','type', 'name', 'slug', 'sku', 'description',
'status', 'in_stock', 'track_stock', 'qty', 'is_taxable', 'page_title', 'page_description'];
// protected $guarded = ['id'];
public static function getCollection()
{
$model = new static;
$products = $model->all();
$productCollection = new ProductCollection();
$productCollection->setCollection($products);
return $productCollection;
}
public function users()
{
return $this->hasMany('\Models\Database\Product');
//->withTimestamps();
}
public function categories()
{
return $this->belongsToMany(Category::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
public function prices()
{
return $this->hasMany(ProductPrice::class);
}
public function orders()
{
return $this->hasMany(Order::class);
}
public function users()
{
return $this->hasMany('Models\Database\Product');
}
And in my view, this is how i try to get the respective user's phone number
<p>{{$product->users->phone}}</p>
But i get an error like
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'products.product_id' in 'where clause' (SQL: select * from products
where products.product_id = 1 and products.product_id is not
null)
You should do:
User Model
public function products()
{
return $this->hasMany('Models\Database\Product');
}
Product Model
public function user()
{
return $this->belongsTo('Models\Database\User');
}
In your blade:
{{ $product->user->phone }}
You have got your relationship models inverted,
change them:
In your User model:
public function products()
{
return $this->hasMany('Models\Database\Product');
}
In your Product model:
public function user()
{
return $this->belongsTo('Models\Database\User','user_id');
}
And then you could access the properties like:
<p>{{$product->user->phone}}</p>
Link to the Docs

Laravel Many to Many relationship gets partial results

I have Course and Category Models with many to many relationship between them. So I created CategoryCourse Model to decompose relationship. Here are my three models:
class CategoryCourse extends Model
{
private $foreignkeys = [
'$category_id','$course_id'
];
public function categories()
{
return $this->belongsToMany('App\Category');
}
public function courses()
{
return $this->belongsToMany('App\Course');
}
}
class Category extends Model
{
protected $title = ['title'];
public function categorycourse()
{
return $this->hasMany('App\CategoryCourse');
}
}
class Course extends Model
{
protected $fillable = [
'title', 'desc'
];
public function categorycourse()
{
return $this->hasMany('App\CategoryCourse');
}
}
In my controller I have method as follows:
public function getCoursesByCategory(Request $request, $id)
{
$id = Hashids::decode($id);
$categories = Category::findOrFail($id[0]);
$courses = $categories->categorycourse()->get();
return view('courses',compact('courses'));
}
I have three tables in database, they are categories, courses and category_courses. My view is displaying results from category_courses but not results from courses. I am learning laravel. Can any one please help? I want to display all courses that belong to a category, in my view.
Here is my view code:
#foreach($courses as $course)
{{$course->title}}
#endforeach
You have to change your code to:
class Category extends Model
{
protected $title = ['title'];
public function courses()
{
return $this->belongsToMany('App\Course', 'category_course', 'category_id', 'course_id');
}
}
The relationship should be in Category only.
And then you call:
$courses = $categories->courses;

Laravel many layer eloquent relationship

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

Laravel return property from third table

I have three tables:
products
product_types
product_categories
products belongs to product_types and product_types belongs to product_categories.
How can I access a column from product_categories from products?:
ProductTypes model:
class ProductTypes extends Eloquent {
public function category() {
return $this->belongsTo('ProductCategories');
}
}
Products model:
class Product extends Eloquent {
protected $table = 'products';
public function brands() {
return $this->belongsTo('ProductBrands', 'brand_id', 'id');
}
public function ages() {
return $this->belongsTo('ProductAges', 'age_id', 'id');
}
public function types() {
return $this->belongsTo('ProductTypes', 'type_id', 'id');
}
public function images() {
return $this->hasMany('ProductImages');
}
public function reviews() {
return $this->hasMany('ProductReviews');
}
public function toArray() {
$ar = $this->attributes;
$ar['brand'] = $this->brand;
$ar['age'] = $this->age;
$ar['type'] = $this->type;
return $ar;
}
public function getBrandAttribute() {
$brands = $this->brands()->first();
return (isset($brands->brand) ? $brands->brand : '');
}
public function getAgeAttribute() {
$ages = $this->ages()->first();
return (isset($ages->age) ? $ages->age : '');
}
public function getTypeAttribute() {
$types = $this->types()->first();
return (isset($types->type) ? $types->type : '');
}
}
I have tried:
$productData->types()->category()->category
But this gives an error saying the method doesn't exist.
Sorry about the title, couldn't think of one.
The problem is, that you're not executing the query when doing types() and therefore you're calling category() on the query builder instance and not the ProductTypes model.
You can use the dynamic properties for accessing the result of the relationship.
$productData->types->category->category
Also consider renaming your relationships. Currently you have "types" for example but it only returns one type, because its a one-to-many relation. "type" would make more sense.

Categories