Eloquent where clause on with table - laravel-4

I have a Quote Eloquent model which has several relationships, one of them being Customer. I'm writing a search controller which takes a query and then searches the models. If I don't need to search on the custom relationship I can easily do this:
$Quote = Quote::where('trashed', '0'); // Never get trashed items.
$Quote->where('item', 'LIKE', '%'.$searchQuery.'%');
Works a treat.
However, if I want to search all quotes, but by the customers name:
$Quote = Quote::where('trashed', '0'); // Never get trashed items.
$Quote = $Quote->with(['Customer' => function($Query) use ($searchQuery) {
$Query->where('e_mail', 'LIKE', '%'.$searchQuery.'%');
}]);
All this is doing is saying "join the customers that have a name like $searchQuery. If I move the where clause to be after the with method, it can't access the e_mail field.
So how do I search the quotes, but where the customer is equal to something else?

Try this:
$Quote = Quote::with(['Customer' => function($Query) use ($searchQuery) {
$Query->where('e_mail', 'LIKE', '%'.$searchQuery.'%');
}])->where('trashed', '0')->where('item', 'LIKE', '%'.$searchQuery.'%');

I managed to solve this by using whereHas instead of with, with a query.
$Quote = Quote::whereHas('customer', function($Query) use($searchQuery) {
$Query->where('e_mail', 'LIKE', '%'.$searchQuery.'%');
});
Sorted!

Related

Get multiple average values in raw expression - Laravel MongoDB jenssegers

I am using Laravel with MongoDB and jenssegers package. I have a collection called ProductDetails in which I have three fields for which I need to retrieve the average value: price, margin and weight. I can make three different queries but I would like to get that in one query. I think it would be cleaner.
I tried using raw expressions but I cannot make it work. I can't even retrieve the average of a single value. I have seen many people using mongoDB aggregation but I don't see why and how it would be useful here.
Here's what I'd love to achieve:
$productDetails = ProductDetails::select('AVG(price) as avg_price','AVG(margin) as avg_margin','AVG(weight) as avg_weight')
->where('id', '=', $id)
->where('active', '=', true)
->get();
It works when I try to retrieve the values (not the average) but the select does not work with AVG() which is why I wanted to use raw expressions
This is an unfruitful attempt:
$productDetails = ProductDetails::raw(function($collection)
{
return $collection ->find([
'name' => 'First product',
'avg_price' => ['$avg' => "price"]
]);
})
you just have to use selectRaw :
$productDetails = ProductDetails::selectRaw('AVG(price) as avg_price, AVG(margin) as avg_margin, AVG(weight) as avg_weight')
->where('id', '=', $id)
->where('active', '=', true)
->get();
be careful about the ' location, it should be around the hole statement in select raw expressions.
but :
->where('id', '=', $id)
this statment will make the query return only one row, I think you mean
->where('product_id', '=', $id)
is not?

Laravel whereHas Returns all records

I have have 3 tables in my projects they are:
products(can have Multiple Variants)
variants (belongsto product)
product_attributes (this have product_id,attribute_id,value_id)
I want to filter variants from a product by value ids thats comes from form request as example (1,2,6)
I have tried like this:
$poruduct_id = $request->product_id;
$value_ids = $request->value_ids;
$searched_variants = Variant::whereHas('product.attributeValues', function ($query) use ($value_ids, $product_id) {
$query->whereIn('value_id', [$value_ids]);
})->where('product_id', $product_id)->get();
dd($searched_variants);
But the problem is the query returns all records from the product. What is the solution to filter exactly the values that the product Variants have?
Thank you.
-UPDATED-
I have tried like this but nothing changed
$searched_variants = Variant::select('product_id')->whereHas('product.attributeValues', function ($query) use ($value_ids, $product_id) {
$query->whereIn('value_id', [$value_ids]);
})->groupBy('product_id')
->havingRaw('COUNT(*) = ?', [count((array) $value_ids)])
->get();
-**FİNALLY SOLUTİON**-
I made it like this : I get the value code that is in for example Large the code is L
get all the codes to controller and executed this query ı hope this helps someone
1.$value_codes=$request->value_codes;
2.$value_codes_array=explode(',',$value_codes);
3.$product_id=$request->product_id;
4.$searchValues = preg_split('/,/', $value_codes_array, -1, PREG_SPLIT_NO_EMPTY);
$searchValues = preg_split('/,/', $value_idss, -1, PREG_SPLIT_NO_EMPTY);
$variants= Variant::where(function ($q) use ($searchValues) {
foreach ($searchValues as $value) {
$q->orWhere('sku', 'like', "%-{$value}")
->orWhere('sku', 'like', "%-{$value}-%")
->orWhere('sku', 'like', "{$value}-%");
}
})->where('product_id',$product_id)->get();
dd($variants);
If you have n variants to one product, you query should be like:
Product Model
public function variants: HasMany relationships
//usage
$produtc->variants->and here the query function
You need to use it in this way, it should work:
$productId = $request->product_id;
$valueIds = $request->value_ids;
$searchedVariants = Variant::whereHas('product.attributeValues', function ($query) use ($valueIds) {
$query->distinct()->whereIn('value_id', $valueIds);
}, '=', count($valueIds))->where('product_id', $productId)->get();

Finding a user with highest post created in last 24 hours, laravel Eloquent

How to find the user with the highest post created in the last 24 hours in laravel?
sorted by the number of posts in descending order.
If I'm not wrong, you are asking for the users with the highest number of posts created in the last 24 hrs.
To accomplish this, do the following:
$users = User::withCount(['posts' => function ($query) {
$query->where('created_at', '>=', carbon()->now()->subDay());
}])->orderBy('posts_count', 'DESC')
->get();
As the documentation states, you can add constraints to the queries.
Counting Related Models
If you want to count the number of results from a relationship without actually loading them you may use the
withCount method, which will place a {relation}_count column on
your resulting models. For example:
$posts = App\Post::withCount('comments')->get();
foreach ($posts as $post) {
echo $post->comments_count;
}
You may add the "counts" for multiple relations as well as add
constraints to the queries:
$posts = Post::withCount(['votes', 'comments' => function ($query) {
$query->where('content', 'like', 'foo%');
}])->get();
echo $posts[0]->votes_count;
echo $posts[0]->comments_count;
use Carbon\Carbon;
get user id:
$minusday = Carbon::now()->subDay();
$user_id = DB::table('posts')
->select('user_id', DB::raw('count(id) as total'))
->where('created_at', '>=', $minusday)
->groupBy('user_id')
->orderBy('total','desc')
->limit(1)
->get();
In regular SQL syntax you'd need something like below:
SELECT COUNT(id), user_id
FROM posts
WHERE created_at = today
GROUP BY user_id
ORDER BY COUNT(user_id) DESC
LIMIT 1;
It gets all the posts, groups them by user_id, sorts them with the highest user_id count up top and gets the first record.
I am by no means an expert on SQL, let alone the query builder in Laravel, so someone else would probably be better at writing that.
I know that you can get the posts that were created today by using Carbon, like so:
Post::whereDate('created_at', Carbon::today())->get();
EDIT: This might work for you:
$last24h = Carbon::now()->subDay();
DB::table('posts')
->select(array(DB::raw('COUNT(id)', 'user_id')))
->where('created_at', '>=', $last24h)
->groupBy('user_id')
->orderBy('COUNT(id)', 'DESC')
->limit(1)
->get();
Be sure to include use Carbon\Carbon to be able to use Carbon.
This should give you both the amount of posts and the corresponding user id.

How to use '::whereHas()' as a constraint for '::with()' query when using Eloquent?

I have a query:
Posts::whereHas('comments', function($query){
$query->where('name', 'like', 'asd');
})->with('comments')->get();
It returns all posts that have comments which have name like 'asd' with all comments of these posts. Can I use the above constraint in '::whereHas' for the 'with' method, so it would not return all comments, but only those that match the requirements? Or do I have to duplicate the query?
You can create query something like this, almost without duplicate :)
$callback = function($query) {
$query->where('name', 'like', 'asd');
}
Posts::whereHas('comments', $callback)->with(['comments' => $callback])->get();
Or, you can make like in this post Laravel - is there a way to combine whereHas and with

How to select instances for specific 'n' on m:n relationships?

I have two models Teacher and Category. These two have Many to Many relationship.
I want to get those teachers who have one category equal to "OLevels". Which method of eloquent is used for it or is there any other way I can get it?
Is there anyway to get it as:
$teachers = Teacher::where('category', '=', 'OLevels')->get();
You can use whereHas for that:
$category = 'OLevels';
$teachers = Teacher::whereHas('category', function($q) use ($category){
$q->where('name', $category);
})->get();
You could make use of eager loading with constraints
$teachers = Teacher::with(['category' => function($query)
{
$query->where('category', '=', 'OLevels');
}])->get();
Further info in the documentation.

Resources