I want to retrieve tags related to each model without loading all columns of intermediate tables. I want to display tags on index page. Please tell me if any solution exist for this scenario.
I tried with hasManyThrough relationship to get tags but its not working because of polymorphic index table.
(Table Name => Table Columns)
food_index => id, description, food_type, food_id
fruits => id, description, price, availability
vegetables => id, description, price, availability, calories
cereal => id, description, price, availability, brand
tags => id, tag
(pivot table)
taggable => id, tag_id, taggable_type, taggable_id
Models =>
class Fruit extends Model
{
public function index()
{
return $this->morphOne('App\FoodIndex', 'indexable', 'food_type', 'food_id');
}
public function tags() {
return $this->morphToMany('App\Tag', 'taggable');
}
}
class Vegetable extends Model
{
public function index()
{
return $this->morphOne('App\FoodIndex', 'indexable', 'food_type', 'food_id');
}
public function tags() {
return $this->morphToMany('App\Tag', 'taggable');
}
}
class Cereal extends Model
{
public function index()
{
return $this->morphOne('App\FoodIndex', 'indexable', 'food_type', 'food_id');
}
public function tags() {
return $this->morphToMany('App\Tag', 'taggable');
}
}
class Tag extends Model
{
public function fruits() {
return $this->morphedByMany('App\Fruit', 'taggable');
}
public function vegetables() {
return $this->morphedByMany('App\Vegetable', 'taggable');
}
public function cereals() {
return $this->morphedByMany('App\Cereal', 'taggable');
}
}
class FoodIndex extends Model
{
public function owner()
{
return $this->morphTo("owner", "food_type", "food_id");
}
public function tags()
{
// return $this->hasManyThrough("App\Tag", "App\FoodIndex", "food_id", 'food_type', "taggable_id", "taggable_type");
// return $this->hasManyThrough('App\Tag', $this->food_type, 'id', 'id');
}
}
Code in controller =>
$index = FoodIndex::whereRaw("MATCH description AGAINST (? IN BOOLEAN MODE)", [$this->fullTextWildcards($term)])->with([
'tags'
])->simplePaginate(5);
I expect $index->tag property to return the tag associated with each food item
but I am getting errors
Related
What Eloquent model would you use to:
Get all Pages that its Company brand color is red/slug.
Where brand color is a pivot table and stored as an ID on the Company table.
So you have brand_colors id, name, slug, hex
Have company where it has brand_color_id
And Pages that has just the company ID.
I want to grab all pages whose company brand color is X.
How would you go about it?
This table has the company_id
class WebsitePage extends Model
{
use HasFactory;
public function scopeFilter($query, array $filters) {
// Get all pages with a color that the company has
$query->when($filters['color'] ?? false, fn($query, $color) =>
$query->whereHas('color', fn ($query) =>
$query->where('name', $color)
)
);
}
// Where URL slug 'red' color, associated with company brand_color_id matches brandColor slug
// or just simpley call $company->color() ?
public function color()
{
// return $this->with(Company::class, 'brand_color_id');
// return $this->belongsTo(Company::class, 'company_id');
// dd($this->with())
// return Company::with('color.red');
}
This table has brand_color_id, etc.
class Company extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'name',
'slug',
'description'
];
public function pages() {
return $this->hasMany(WebsitePage::class);
}
public function color() {
return $this->belongsTo(BrandColor::class, 'brand_color_id');
}
}
This table has: id | name | slug | hex
class BrandColor extends Model
{
use HasFactory;
}
So knowing this, how would you get all pages whose company color is the one filtered?
In terms of the page controller, this is what I'm doing:
class PageController extends Controller
{
public function index(WebsitePage $websitePage)
{
// return view('web.inspiration.pages.index', [
// 'pages' => WebsitePage::latest()->paginate(30)
// ]);
return view('web.inspiration.pages.index', [
'pages' => WebsitePage::latest()->filter(
request(['color'])
)->paginate(30)->withQueryString()
]);
}
}
Your model layout isn't described that well, but I think you just want to define a HasOneThrough relationship to join WebsitePage to BrandColor:
class WebsitePage extends Model
{
public function company(): BelongsTo
{
return $this->belongsTo(Company::class);
}
public function color(): HasOneThrough
{
return $this->hasOneThrough(BrandColor::class, Company::class);
}
}
class Company extends Model
{
public function color(): BelongsTo
{
return $this->belongsTo(BrandColor::class);
}
}
class BrandColor extends Model
{
public function company(): HasOne
{
return $this->hasOne(Company::class);
}
}
Then in your controller, just use a condition on your whereHas() and with() calls:
class PageController extends Controller
{
public function index(): View
{
$color = request("color");
$pages = WebsitePage
::whereHas("color", fn ($q) => $q->where("color", $color))
->with(["color" => fn ($q) => $q->where("color", $color)])
->paginate(30)
->withQueryString();
return view("web.inspiration.pages.index", compact($pages));
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();
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
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
Question: How to get best 3 organizations according to column General in Review, together with other related data(User, Address, City, Country, Review, Activity)
PS. Organization has many reviews, and column General is a grade 1-5.
I have tables Organization, User, Review, Activity, Address, City, Country.
I also have models for each table and their relationships:
Example table organization:
class Organization extends Model {
protected $table = 'organization';
protected $fillable = ['OrgName'];
public function user() {
return $this->belongsTo('App\Models\User', 'UserId', 'Id');
}
public function address() {
return $this->belongsTo('App\Models\Address', 'AddressId', 'Id');
}
public function review() {
return $this->hasMany('App\Models\Review', 'OrganizationId', 'Id');
}
public function activity() {
return $this->belongsTo('App\Models\Activity', 'ActivityId', 'Id');
}
}
So far I got this:
class OrganizationRepository {
protected $organization;
function __construct(Organization $organization)
{
$this->organization = $organization;
}
public function best3() {
return $this->organization->with(['address.city.country', 'activity', 'review' => function($query) {
$query->orderBy('Timestamp', 'desc')->take(1);
}, 'review.user' ])->where()->take(3)->get();
}