Laravel 5.1 eloquent belongsTo relationship joining on multiple columns - php

I am connecting to a remote database that has been designed poorly but I can't amend it in any way I only have read access to the get the data I need. It has the following structure:
Products
- id
- style_id
- department_id
Brands
- id
- Name
- style_id
- department_id
So as you can see rather than a product just having a brand_id field it has a style_id and department_id that you have to join on in order to find out what brand a product is.
So how would I set up my belongsTo relationship in my Product model in order to achieve this?

I made a scope in the end to do this for me.
public function scopeWithBrand($query)
{
$query->join('Brands', function($q) {
$q->on('Products.department_id', '=', 'Brands.department_id')
->on('Products.style_id', '=', 'Brand.style_id');
})->addSelect(['Brands.id AS brand_id', 'Products.*']);
}

As far as I know Laravel does not support composite keys, there is
an issue opened on the laravel repo where the devs have answered that they don't have intentions of implementing that.
I think you can only query Product-Brand queries like for example Products by Brand combining wheres like this:
Product::where('style_id',$brand->style_id)->where('department_id',$brand->department_id)

Related

How to get products based on a count on a field in this table with Laravel

I'm working on Laravel 5.8
Let's say we have a table products like this:
id | product_type_id |...
1 |______1_______|...
2 |______2_______|...
3 |______2_______|...
4 |______3_______|...
I would like to know how to get the all the products which "share" a product type.
In other words, I would like to get all the products except those whose product_type_id is unique in the table.
I know who to do it in a foreach loop but I would like to take advantage of the resources of using Laravel.
Thanks in advance.
The Laravel way of doing it would be using Eloquent relationships along with has() and whereHas(), like this:
$products = Product::whereHas('type', function ($builder) {
$builder->whereKey(Type::has('products', '>=', 2)->pluck('id'));
})->get();
I'm assuming you have defined Product and Type models and connected them together:
Product belongsTo Type
Type hasMany Product
If I'm understanding your question correctly you could do something like this.
First, make sure your ProductType model has a products relationship defined.
(I assume it does based on your Products table.)
Then you can query based on a relationship count using the Eloquent model method has.
Example:
ProductType::with('products')->has('products', '>', 1)->get();
The with('products') is optional. It simply grabs the Products at the same time to avoid additional queries. The whereHas method also works but is really only necessary if you need to filter the relationship based on more complex parameters.
You could also use the has/whereHas method inside the Product model using an inverse (ie belongsTo) relationship to get the same thing but inverted. It really depends on how you want the data presented to you.
Example:
Product::whereIn(
'product_type_id',
ProductType::has('products', '>', 1)->pluck('id')
)->get();
To sum it all up the first way will give you:
ProductType => Product
While the second example will give you:
Product => ProductType
See the related Laravel documentation for more info.
Hope that helps!

How in Laravel access to relation while building a query?

Let's say I have tables
companies id | name
guests id | name
books id | name
They have models with relations
Company -> hasMany -> Guest
Guest -> hasMany -> Book
Now, I wanna get all books where guests from particular company
I have no Idea how to reach that in eloquent ORM
I will apreciate any help
Thanks
You can use whereHas to query based on the existence of relationships:
$books = Book::whereHas('guest.company', function ($query) use ($companyId) {
$query->where('id', $companyId);
})->get();
Roughly: get all books that belong to a guest that belongs to a company with id of $companyId
Laravel Docs - 5.6 - Eloquent - Relationships - Querying Relationship Existence
$company = Company::with("guests.books")->find($id); // or how you get the company doesn't matter
$company->guests->books // gives you what you're looking for.
Note that, with("guests.books")is not necessary but, it provides you all data in single query
For more further you may want to check out official docs about relationships

Is it possible to perform this query with Laravel or Sql with my database structure?

I have a database with a table articles and a table category.
My table articles have some fields. And one that is category_id and a another orientation.
Categories, in my design, are arranged by orientation. Here is an example
So, I would like to get all category BUT these categories must belong to the right orientation. I want list of all category who have articles with 'web' orientation, by example.
I do not know if it's possible with this architecture and if you understand me.
Any help is welcome
UPDATE : adding the schemas
If you have your models and relations set up, I believe this should do what you want:
$categories = Category::whereHas('articles', function($query) {
$query->where('orientation', 'web')
})->get()
From the Laravel documentation:
If you need even more power, you may use the whereHas and orWhereHas
methods to put "where" conditions on your has queries. These methods
allow you to add customized constraints to a relationship constraint,
such as checking the content of a comment

I want to show foods based on categories in laravel

I have a database table categories having columns:
Category_id
CategoryName
And other table is Food with:
Food_id
FoodName
Category_id
I want to show the food items according to category on webpage. I'm using laravel 5.2 and I'm newbie.
Join those two tables and fetch the data, here is an example on how you do it without creating a model.
$rows = DB::table('food')->select('food.food_id','food.foodName','categories.categoryName')->join('categories','categories.category_id','=','food.category_id')->where('categories.categoryName', '=', 'breakfast')->get();
you can remove the where('','','') part if you dont want to filter
good luck
You would create models for Food and Category. See here for the documentation: https://laravel.com/docs/5.2/eloquent
If you then add relations between both models in those models you can just use Laravels lazy/eager loading to get your data.

Laravel 4.2 ORM - Querying relation with various tables in between

I have a database schema that goes like this:
Section
id
name
Subsection
id
name
section_id
Category
id
name
subsection_id
SubCategory
id
name
category_id
Product
id
name
subcategory_id
As you can see, each table has a foreign key that references the previous table. The problem comes when I try to get, for example, the Section from the current product or get all products from one section. So far I have tried this:
Section::with('product')->find(1)->product;
But I get this:
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'product.section_id' in 'where clause' (SQL: select *
from products where products.section_id in
(1))
1 - This makes me think I need to set up a section_id in the products table to make this work. Is this correct?
2 - Shouldn't the Laravel ORM automatically go up the table hierarchy from Product to Section and get the results?
3 - Is there a way to do this maintaining my current table structure, I mean, without adding extra fields in the tables for the foreign keys?
Thanks.
No that is one way to do it but it isn't the only way.
No, how would it know that automatically?
I believe so and you can always create a specific query when laravel relationships don't work for you.
Okay first this assumes you have relationships setup on all the models to access the one below it. If that isn't the case you will need to setup the relationships.
Section::with('subsection.category.subcategory.product')->get();
I've never tried such extreme nesting but I believe this will work. The Laravel Docs talk about eager loading and scroll to see the nested example.
Another item that comes to mind is the hasManyThrough relationship. You couldn't do it for this number deep but it may be something you want to look into.
A brief summary from the docs is taking the first three from your example, Section, Subsection, and Category and then in the section class you would have this relationship.
public function category()
{
return $this->hasManyThrough('Category', 'SubSection');
}
The laravel docs with more information.

Categories