How to split up an Eloquent model query - php

I'm trying to break up an Eloquent query like this
$query = new Product;
if (!empty($req->query['id'])) {
$query->where('id', '=', '1');
}
$products = $query->get();
The result above gives me all products in the database. This however, does in fact work.
$products = Product::where('id', '=', '1')->get();
Is there a way to do this?

In Laravel 4 you need to append your query parameters to your query variable. In Laravel 3, it would work like you're doing.
This is what you need to do (I'm unsure if it will work with new Product tho):
$query = new Product;
if (!empty($req->query['id'])) {
$query = $query->where('id', '=', '1');
}
$products = $query->get();

Your code does not make sense. If you make a new Product - then it will never have an ID associated with it - so your if (!empty($req->query['id'])) will always be false.
Are you just trying to get a specific product idea?
$products = Product::find(1);
is the same as
$products = Product::where('id', '=', '1')->get();

Related

How to fix whereNotExists and where query builder laravel

I try to combine whereNotExists and where, if you use it simultaneously it will and if you try one of them you can
$query = DB::table('tabel_produk')->where('kode_customer',$cust)->whereNotExists(function($query){
$query->select(DB::raw(1))->from('tabel_detail_realisasi')->whereRaw('tabel_detail_realisasi.barcode = tabel_produk.barcode');
})->distinct()->orderBy('barcode','asc') ->get();
Pleae help me with this
I don't have your DB schema so I've tried something similar with a local DB I have and it seems to be working fine. See my example below. Could you please replace my query with yours and see what's output by the query logger?
DB::flushQueryLog();
DB::enableQueryLog();
$results = DB::table('product_templates')
//Non deleted products
->where('deleted', '=', '0')
//
->whereNotExists(function ($query) {
//Where the category is not 'General'
$query
->select(DB::raw(1))
->from('product_categories')
->whereRaw('product_categories.id = product_templates.category_id')
->where('product_categories.name', 'General');
})
->distinct()
->orderBy('name', 'asc')->get();
DB::disableQueryLog();
$queryLog = DB::getQueryLog();
logger("Query results", compact('results', 'queryLog'));

Query array using whereHas

I want to filter products by category (manyToMany relationship). Basically the user select which categories to show. The categories I want to filter are in $request->keywords. This is what I tried:
$products = Product::all();
foreach($request->keywords as $keyword) {
$products = Product::whereHas('categories', function($q) use ($keyword){
$q->where('title', '=', $keyword);
})->get();
}
return response()->json($products);
The problem is that this does not get all the categories, only the products with the last category in the array. I guess at this point: $q->where('title', '=', $keyword);, $q does not keep the results of the last loop iteration but always deletes the last loop results.
I also tried the same thing with $q->orWhere('title', '=', $keyword);, but that actually doesn't give me any results.
Thanks for your help!
Changed your approach to fetch the data,
$products = Product::all();
if (!empty($request->keywords)) { // if keywords not empty
$keyword = $request->keywords;
$products = Product::whereHas('categories', function ($q) use ($keyword) {
$q->whereIn('title', $keyword); // where in for array
})->get(); // it won't override old data as there is no loop
}
return response()->json($products);
You can simply use whereIn on the title field by passing in your keywords.
$products = Product::all();
$titles = [];
foreach($request->keywords as $keyword) {
$titles[] = $keyword;
}
$products = Product::whereHas('categories', function($q) use ($keyword){
$q->whereIn('title', $titles);
})->get();
I'm improving other persons answer. Below is the filtered code here
$builder = new Product;
if($request->filled('keywords')) { // if keywords key has any value then query will execute.
$builder = $builder->whereHas('categories', function($q) use ($request){
$q->whereIn('title', array_values($request->keywords));
});
}
$items = $builder->get();
dd($items);
You can try this.

use DB::table with some filters conditions

I want to create a filter using laravel Query Builder.
I have the following code:
$queries = array();
$paginate = 10;
$orders = DB::table('orders')->whereNull('deleted_at');
// the filter i want to apply
$from = 2018-06-18;
$end = 2018-06-20;
$orders->whereBetween('orders.created_at', array($from, $end));
$queries['dateRange'] = request('dateRange');
// other filters
...
$orders->leftJoin('order_status', 'orders.OrderID', '=', 'order_status.OrderID')
->select('orders.*', 'order_status.Status')
->orderBy('OrderID', 'desc')
->paginate($paginate)
->appends($queries);
The problem is that i get an error - is not working. If a haven`t used leftjoin i will probably used like this
($orders = Order::query();).
How can i use properly the DB::table queries with some filters, or is another better solution to this?
UPDATE
to be more specific:
this code works:
$orders = DB::table('orders')->whereNull('deleted_at')
->leftJoin('order_status', 'orders.OrderID', '=', 'order_status.OrderID')
->select('orders.*', 'order_status.Status')
->orderBy('orders.OrderID', 'desc')
->paginate($paginate)
->appends($queries);
this code does not work:
$orders = DB::table('orders')->whereNull('deleted_at');
$orders->leftJoin('order_status', 'orders.OrderID', '=', 'order_status.OrderID')
->select('orders.*', 'order_status.Status')
->orderBy('orders.OrderID', 'desc')
->paginate($paginate)
->appends($queries);
I have changed to this approach and now it works. The problem was i have to specify on another line the paginate:
$orders = DB::table('orders')->whereNull('deleted_at');
// date filter
$orders->whereBetween(DB::raw('DATE(orders.created_at)'), array($from, $to));
$orders->leftJoin('order_status', 'orders.OrderID', '=', 'order_status.OrderID')
->select('orders.*', 'order_status.Status')
->orderBy('orders.OrderID', 'desc');
// the paginate and appends write on new line :)
$orders = $orders->paginate($paginate)->appends($queries);

Search and sort in laravel?

In laravel, I know you can do
$users = Post::where('hide', '=', 0)->take(40)->get();
to get all Post-objects where hide = 0 and
$users = Post::orderBy('created_at', 'DESC')->take(20)->get();
to sort them, but what if I want to do both?
You should be able to do
$users = Post::where('hide', '=', 0)->orderBy('created_at', 'desc')->take(20)->get();
You can continue to chain methods from the query builder after the where.

laravel using query builder without chaining

I have a query builder that works:
$article = Page::where('slug', '=', $slug)
->where('hide', '=', $hidden)
->first();
But I want to only add the second where statement if hidden is equal to 1. I've tried the code below which shows the logic of what I'm trying to do, but it doesn't work.
$article = Page::where('slug', '=', $slug);
if ($hidden == 1) {
$article->where('hide', '=', 1);
}
$article->first();
I'm using Laravel 4, but I think the question still stands with Laravel 3.
Yeah there's a little "gotcha" with Eloquent and the query builder. Try the code below ;)
$query = Page::where('slug', '=', $slug);
if ($hidden == 1) {
$query = $query->where('hide', '=', 1);
}
$article = $query->first();
Note the assigning of $query within the conditional. This is becuase the first where (statically called) returns a different object to the query object within the conditional. One way to get around this, I believe due to a recent commit, is like so:
$query = Page::where('slug', '=', $slug)->query();
This will return the query object and you can do what you want as per normal (Instead of re-assigning $query).
Hope that helps.

Categories