I want to take houses lists and houses pictures on mysql from laravel. But, i have this problem. Using the process below:
$houses = Houses::query()
->orderBy('sort', 'ASC')
->take('6')
->get();
This query, give houses list to me. And I need to use the houses I retrieve to get their photos, this is the best I could think of:
$pictures = Housephotos::query()
->where('house_id', '=', $houses->house_id)
->get();
Question one: This process is correct?
Question two : How can do this?
Add a relation to Houses:
class Houses extends Model
{
public function photos()
{
return $this->hasMany(Housephotos::class);
}
}
and now you can get the photos easily like:
$houses = Houses::query()
->orderBy('sort', 'ASC')
->take('6')
->get();
foreach ($houses->photos as $photo) {
echo $photo->id;
}
the problem with that is, select query will run n times (5 times for this example).
if you add with to the query however, then laravel will run a single in query to get the pictures:
$houses = Houses::query()
->with('pictures')
->orderBy('sort', 'ASC')
->take('6')
->get();
You need to make a relationship between Housephotos and House so that there is house_id in Housephotos. If this is true, you can already use the houses Id you have to retrieve the houses Id:
Say you already have the houses, then you can have:
$pictures = Housephotos::whereIn('house_id', '=', $houses->pluck('id')->toArray())
->get();
This will give you the houses photos.
Related
Ok.
I have three tables
products
--product_id
--product_name
--product_type_id
--price15
--price23
--description
--bonus_points
--image
productTypes
--product_type_id
--product_type_name
productQuantities
--id
--product_id
--warehouse_id
--quantity
Products are placed in different warehouses so I have to keep tracks of its numbers
And has relationships are like this
class Product extends Model
{
public function productType() {
return $this->belongsTo('App\Models\ProductType','product_type_id','product_type_id');
}
public function productQuantities() {
return $this->hasMany('App\Models\ProductQuantity','product_id','product_id');
}
}
What I want to get is all columns from products and product type name from productType, sum of quantity from productQuantities, so I can perform search on those column values later on with where().
How can I get these columns with Eloquent?
I know I could get them with raw SQL commands but I need to do this way for compatibility reasons.
I tried this way before I ask the question.
But model relations just stopped working with no errors. Values just got emptied out from the other parts of the page.
$products = Product::selectRaw('products.*, productTypes.product_type_name, sum(product_quantities.quantity) as quantitySum')
->leftjoin('productTypes','products.product_type_id','=','productTypes.product_type_id')
->leftjoin('productQuantities','products.product_id','=','productQuantities.product_id')
->where('products.product_id','like','%'.$searchID.'%')
->where('product_name', 'like', '%'.$searchName.'%')
->where('product_type_name', 'like', '%'.$searchType.'%')
->where(function($q) use ($searchPrice) {
$q->where('price15','like','%'.$searchPrice.'%')
->orwhere('price23','like','%'.$searchPrice.'%');
})
->where('points', 'like', '%'.$searchPoints.'%')
->groupBy('products.product_id')
->orderByRaw($query)
->paginate($paginateBy);
Working version before this was simple.
Product::leftjoin('productTypes','products.product_type_id','=','productTypes.product_type_id')
->select('products.*','productTypes.product_type_name')
->where('products.product_id','like','%'.$searchID.'%')
->where('product_name', 'like', '%'.$searchName.'%')
->where('product_type_name', 'like', '%'.$searchType.'%')
->where(function($q) use ($searchPrice) {
$q->where('price15','like','%'.$searchPrice.'%')
->orwhere('price23','like','%'.$searchPrice.'%');
})
->where('points', 'like', '%'.$searchPoints.'%')
->orderByRaw($query)
->paginate($paginateBy);
And I thought any kind of join methods doesn't seem to be working well with Eloquent relationship? But older one has leftjoin method as well.
I have not tested this (and am assuming you want to group on product_type_name but you should be able to do something along the lines of:
$results = Product::with(['productType','productQuantities'])
->select(DB::raw('products.*,
productType.product_type_name,
sum(productQuantities.quantity) as "QuantitySum"'))
->groupBy('productType.product_type_name')
->get();
OR
$results = DB::table('products')
->join('productType', 'productType.product_type_id', '=', 'products.product_type_id')
->join('productQuantities', 'productQuantities.product_id', '=', 'products.product_id')
->select(DB::raw('products.*,
productType.product_type_name,
productType.product_type_name,
sum(productQuantities.quantity) as "QuantitySum"'))
->groupBy('productType.product_type_name')
->get();
Then you should be able to access the aggregated quantities using (in a loop if you wanted) $results->QuantitySum.
you can get it with eager loading and aggregating. For example, you need to query products has product type name like "new product" and quantity greater than 1000:
Product::with("productType")
->whereHas("productType", function ($query) {
$query->where("product_type_name", "like", "new product");
})
->withCount(["productQuantities as quantity_count" => function ($query) {
$query->selectRaw("sum(quantity)");
}])
->having("quantity_count", ">", 1000)
->get();
you can get through relationship
$product->productType->product_type_name
and attribute:
$product->quantity_count
$products = Product::withsum('productQuantities','quantity')
->leftjoin('product_types','products.product_type_id','=','product_types.product_type_id')
Gives me the result that I wanted. And didn't break the other parts.
But I'm still confused why with() and withSum() didn't work together.
Is it because products belongs to productTypes maybe
Objective
I'm trying to select some columns from a multiple inner join query.
I have a model called Item and this model belongs to the other three Produto, Unidadeand Marca
Problem
I'm not getting the full result declared on my query. Only some columns are being shown.
What I tried
I have already tried to put everything in one ->select() , but I had the same issue. I've checked the relations configuration is working in other part of the code
Result Obtained
Only the columns from first and the last addSelect() are being shown.
var_dump() output
Code
public function download()
{
$item = new Item;
// $data = $item->query()
$data = DB::table('items')
->join('produtos', 'items.produto_id', '=', 'produtos.id')
->join('unidades', 'items.unidade_id', '=', 'unidades.id')
->join('marcas', 'items.marca_id', '=', 'marcas.id')
->select('items.codigo','items.nome')
->addSelect('items.metrica_cod', 'items.metrica')
->addSelect('produtos.codigo', 'produtos.nome')
->addSelect('unidades.codigo', 'unidades.nome')
->addSelect('marcas.codigo', 'marcas.nome')
->get();
var_dump($data);
}
I am creating a search in laravel for an API but my search gives me the wrong results. I am trying to search by location and food type. I have the following tables:
foods
shops
shop_food
users
comments
Here is my search code:
public function searchShop($food, $location)
{
//
if($food == " " || $location == " "){
return $this->index();
}
//get all records where city and food are equal to
$shops = Shop::where('city', '=', $location)
->with('comments.user')
->with(['foods'=> function($query) use($food){
$query->where('name','=', 'fish pepper'); }])
->get();
//check if empty and return all
if($shops->isEmpty()){
return $this->index();
}
return $shops;
}
my result is the below instead of just the record where location and food it shows all the shops filtered by location even where food isnt a match :
The with method that you're using does not filter in the way that you think it does. Your code actually filters the food results, telling Eloquent to retrieve all Shop and either no foods, or the foods with the name fish pepper. This is called constraining eager loads.
The method you're looking for is whereHas rather than with. This is referred to as querying a relationships existence.
$shops = Shop::where('city', '=', $location)
->with('comments.user')
->whereHas('foods', function($query) use($food){
$query->where('name','=', 'fish pepper');
})
->get();
This will now return only Shops that have a corresponding food entry with the name fish pepper.
If memory serves, whereHas won't actually populate foods for you, but in this instance you wouldn't need it, as it's safe to assume that they all have fish pepper. If you do want to pull all foods, change with('comments.user') to with(['comments.user', 'foods']).
Documentation for whereHas and other ways of achieving this can be found here.
Documentation about what you were doing with the with method can be found here.
Hope that helps.
I got this query:
$users = DB::table('users')->whereExists(function($query)
{
$query->select(DB::raw(1))
->from('galleries')
->whereRaw('galleries.user_id = users.id');
})->get();
This query selects all users who have gallery. Problem is that I can't use eloquent releationships now. Whenever i try to loop like this:
#foreach ($user->gallery as $gallery)
{{$gallery->name}}
#endforeach
I get error:
Undefined property: stdClass::$gallery
It happens with all other tables. What am I doing wrong here? My realationships are defined and they work just fine, i got problems only in this query. Thanks.
EDIT
Since it's not eloquent query, could you show me example how to write query, into few tables with eloquent. For example, I need all users who have their status approved in example table
First, determine a relationship in the User class, like this:
class User {
// Determine relation to Example table
public function examples() {
return $this->hasMany('Example', 'user_id', 'id'); // second parameter is the foreign key
}
}
Then the query:
User::whereHas('examples', function( $query ) {
$query->where('status','approved');
})->get();
I have a many-many relation between Ingredient and Recipe, with a pivot table (ingredient_recipe).
I'd like to get ingredients ordered by how many recipes have them. Example, if I use salt in 2 recipes and meat in 3 recipes, I'll have meat before salt.
This is what I have. It works but it doesn't order correctly, even though the resulting query executed directly on my DB works as expected, so Laravel is doing something internally, I guess.
//Ingredient model
public function recipesCount()
{
return $this->belongsToMany('Recipe')->selectRaw('count(ingredient_recipe.recipe_id) as aggregate')->orderBy('aggregate', 'desc')->groupBy('ingredient_recipe.ingredient_id');
}
public function getRecipesCountAttribute()
{
if ( ! array_key_exists('recipesCount', $this->relations)) $this->load('recipesCount');
$related = $this->getRelation('recipesCount')->first();
return ($related) ? $related->aggregate : 0;
}
//controller
$ingredients = Ingredient::with('recipesCount')->whereHas('recipes', function($q)
{
$q->where('user_id', Auth::id());
})->take(5)->get();
//outputting the last query here and executing it on my db returns correctly ordered results.
How can I fix it?
In order to order by related table you need join. There's no way to achieve that with eager loading whatsoever.
Ingredient::with('recipesCount')
->join('ingredient_recipe as ir', 'ir.ingredient_id', '=', 'ingredients.id')
->join('recipes as r', function ($j) {
$j->on('r.id', '=', 'ir.recipe_id')
->where('r.user_id', '=', Auth::id());
})
->orderByRaw('count(r.id) desc')
->groupBy('ingredients.id')
->take(5)
->get(['ingredients.*']);
There's no need for whereHas anymore, for inner joins will do the job for you.