I trying to do a left join with where IN clause search. But I couldn't able to bind the array to the query.
$query = DB::table('offers');
$query->select('id', 'business_id', 'address_id', 'title', 'details', 'value', 'total_available', 'start_date', 'end_date', 'terms', 'type', 'coupon_code', 'is_barcode_available', 'is_exclusive', 'userinformations_id', 'is_used');
$query->leftJoin('user_offer_collection', function ($join)
{
$join->on('user_offer_collection.offers_id', '=', 'offers.id');
$join->on('user_offer_collection.user_id', 'IN', DB::Raw('?'));
})->setBindings(array_merge($query->getBindings() , array(array(
1,2,3
))));
You don't have to bind parameters if you use query builder or eloquent ORM. However, if you use DB::raw(), ensure that you binding the parameters.
Try the following:
$array = array(1,2,3);
$query = DB::table('offers');
$query->select('id', 'business_id', 'address_id', 'title', 'details', 'value', 'total_available', 'start_date', 'end_date', 'terms', 'type', 'coupon_code', 'is_barcode_available', 'is_exclusive', 'userinformations_id', 'is_used');
$query->leftJoin('user_offer_collection', function ($join) use ($array)
{
$join->on('user_offer_collection.offers_id', '=', 'offers.id')
->whereIn('user_offer_collection.user_id', $array);
});
$query->get();
Related
i have problem with pagination using group by
$results = AutomationStep::where([
['uuid', $uuid],
['step' => $step],
['status', $status]
])->select('custom_field', 'created_at', 'status', 'reason')->groupBy('subscribe_id')->get();
i try pagination but not working
$test = new LengthAwarePaginator($results, count($results), 10, null,
array('path' => Paginator::resolveCurrentPath()));
please help me, thanks
Use it
results = AutomationStep::where([
['uuid', $uuid],
['step' => $step],
['status', $status]
])->select('custom_field', 'created_at', 'status', 'reason')-
>groupBy('subscribe_id')->paginate(10);
// Note : 10 = Per page number.
use Illuminate\Pagination\LengthAwarePaginator;
$results = AutomationStep::where([
['uuid', $uuid],
['step' => $step],
['status', $status]
])->select('custom_field', 'created_at', 'status', 'reason')->->groupBy('subscribe_id')->get();
$perPage = 10;
$currentPage = LengthAwarePaginator::resolveCurrentPage();
$currentResult = $results->slice(($currentPage * $perPage) - $perPage, $perPage)->values()->all();
$updateResultn= new LengthAwarePaginator($currentResult , count($results), $perPage);
I filter and list the products listed with the code samples on my model page below with some data from the user.
I want to sort the listed products according to their prices. However, as it is seen in the minprice-maxprice sample code block, relation depends on several conditions.
From the period consisting of postFrom and postTo dates received by the user, if the daily is 0, it should be listed according to the old_daily price, if the daily is not 0, it should be listed according to the daily price.
How can I do that?
my model page
public $belongsTo = [
'price' => [
'ac\prices\models\Price',
'key' => 'id',
'otherKey' => 'pro_id',
],
]
public static $allowedSortingOptions = array (
'name desc' => 'Name - desc',
'name asc' => 'Name - asc',
'price desc' => 'Price - desc',
'price asc' => 'Price - asc',
);
public function scopeListFrontEnd($query, $options = []){
extract(array_merge([
'page' => 1,
'perPage' => 10,
'sort' => 'created_at desc',
'postFrom' => null,
'postTo' => null,
'minPrice' => null,
'maxPrice' => null,
], $options));
if(!is_array ($sort)){
$sort = [$sort];
}
foreach ($sort as $_sort){
if(in_array($_sort, array_keys(self::$allowedSortingOptions))){
$parts = explode(' ', $_sort);
if(count($parts) < 2){
array_push($parts, 'desc');
}
list($sortField, $sortDirection) = $parts;
$query->orderBy($sortField, $sortDirection);
}
}
if($minPrice != null) {
if(!is_array($minPrice)){
$minPrice = [$minPrice];
}
foreach ($minPrice as $mnPrice){
$query->whereHas('price', function($q) use ($mnPrice,$maxPrice,$postFrom,$postTo){
$q->where('daily', '==', '0')
->where(function( $query ) use ( $mnPrice, $maxPrice ) {
$query->where('old_daily', '>=', $mnPrice);
$query->where('old_daily', '<=', $maxPrice[0]);
});
$q->orWhere('daily', '!=', '0')
->where(function( $query ) use ( $mnPrice, $maxPrice ) {
$query->where('daily', '>=', $mnPrice);
$query->where('daily', '<=', $maxPrice[0]);
});
$q->when($postFrom == '0', function ($sq) {
$sq->where('id', '>', '0');
}, function ($ssq) use ($postFrom, $postTo) {
$ssq->where(function($q) use ($postFrom) {
$q->whereDate('start_date', '<=', $postFrom[0])
->whereDate('end_date', '>=', $postFrom[0]);
})->orWhere(function($q) use ($postTo) {
$q->whereDate('start_date', '<=', $postTo[0])
->whereDate('end_date', '>=', $postTo[0]);
});
});
});
}
}
$lastPage = $query->paginate($perPage, $page)->lastPage();
if($lastPage < $page){
$page = 1;
}
return $query->paginate($perPage, $page);
}
Without trying to decode exactly what you are trying to do here, I would be adding a sub-query select that pulls a sort_price field into the results that you can then orderBy.
$query->selectRaw('CASE WHEN daily = 0 THEN old_daily ELSE daily END as sort_price');
$query->orderByRaw('(SELECT sort_price)');
You can also do this directly in the sort condition as per MYSQL ORDER BY CASE Issue if you don't need this price in your result.
You can do this in the orderByRaw builder method.
I have a product with several skus. Each sku has many attributes.
Each attribute has a type which could be something like "size" or "color", and a value, which would be something like "M", or "black".
Each product has an arbitrary number of attributes, which I've made selectable in a form.
Now, I have a list of each attribute and its value.
[
'size' => 'M',
'color' => 'black',
]
Great. Now I have to fetch the SKU(s) which correspond to these particular attributes.
For example, this works when I have just ONE attribute.
$product->skus->whereHas('attributes', function($query) {
return $query->where(['type' => 'size', 'value' => 'M']);
})->get();
But how do I build a query that returns only the skus that have attributes which match ALL of the qualifications?
And remember, these attributes are arbitrary in number. I can't hardcode it; I just have to pass the array of type-value pairs.
I figured out how to do this manually – but again it doesn't allow for the arbitrary number of attributes. Plus, it's clunky. Something like this:
$product->skus->whereHas('attributes', function($query) {
return $query->where(['type' => 'size', 'value' => 'M']);
})->whereHas('attributes', function($query) {
return $query->where(['type' => 'color', 'value' => 'white']);
})->get();
Edit: The following code appears to work but it's clunky as hell. There must be a better way to do it?
$list = $this->skus()->with('attributes');
foreach ($attrs as $type => $value) {
$list->whereHas('attributes', function ($query) use ($type, $value) {
return $query->where(['type' => $type, 'value' => $value]);
});
}
return $list->first();
The way that you have done it seems to be the cleanest way of doing what you asked for.
Remember that Eloquent is just an abstraction of SQL.
If your writing this in SQL, it would be something like:
select * from skus
where exists (select * from attributes where sku_id = skus.id and type = ? and value = ?)
and exists (select * from attributes where sku_id = skus.id and type = ? and value = ?)
and exists (select * from attributes where sku_id = skus.id and type = ? and value = ?)
...
This is essentially what you have already done with Eloquent in your question:
$list = $this->skus()->with('attributes');
foreach ($attrs as $type => $value) {
$list->whereHas('attributes', function ($query) use ($type, $value) {
return $query->where(['type' => $type, 'value' => $value]);
});
}
return $list->first();
User model has follow relation:
public function getWorkload() : ActiveQuery
{
return $this->hasMany(ScheduleWorkload::className(), ['staff_id' => 'id']);
}
Find method:
$staffs = User::find()
->alias('u')
->joinWith(['workload as uw' => function($q) {
$q->select(['uw.staff_id', 'uw.date', 'uw.time_ranges']);
}], true)
->select([
'u.id',
'CONCAT(u.first_name, \' \', u.last_name) as name',
'u.first_name',
'u.last_name',
'u.undelivered_messages',
])
->where(['u.is_staff' => 1])
->asArray()
->all()
;
I need get data without uw.staff_id in result set? Is it possible without post-processing?
UPDATE:
Result set that I have
I need "workload" as array parameter but do not use post-processing and just exclude "staff_id" from result set.
Raw sql:
SELECT `u`.`id`, `u`.`undelivered_messages`
FROM `user` `u`
LEFT JOIN `schedule_workload` `uw` ON `u`.`id` = `uw`.`staff_id`
WHERE `u`.`is_staff`=1
You can't do in Yii without any post-processing because ActiveQuery will search for foreign key in nested query result to build nested arrays for joined relation.
The most convenient way for you is to use ArrayHelper:
$staffs = User::find()
->alias('u')
->joinWith(['workload')
->where(['u.is_staff' => 1])
->all();
return \yii\helpers\ArrayHelper::toArray($staffs, [
User::className() => [
'id',
'first_name',
'last_name',
'name' => function ($user) {
return $user->first_name . ' ' . $user->last_name
},
'undelivered_messages',
'workload',
],
ScheduleWorkload::className() => [
'date',
'time_ranges',
'comment'
]
], true);
If I store in DB criterias what I want to use to build and filter queries - how to build query with Laravel Fluent Query Builder? Maybe you can give advice for refactoring this array for adding OR/AND to make complex filter by such conditions? Thanks!
For example if I read from database these criteria and made array:
$array = array(
'0' => array(
'table' => 'users',
'column' => 'name',
'criteria' => 'LIKE'
'value' => 'John'
),
'1' => array(
'table' => 'groups',
'column' => 'name',
'criteria' => 'NOT LIKE'
'value' => 'Administrator'
),
...
)
If you are really set on doing it your way, make a switch statement to set the flag for the index of the array
switch ($query)
{
case 0:
$this->get_data($x);
break;
case 1:
$this->get_data($x);
break;
case 2:
$this->get_data($x);
break;
default:
Return FALSE;
}
public function get_data($x){
$value = DB::table($array[$x]['table'])
->where($array[$x]['name'], $array[$x]['criteria'], $array[$x]['value'])
->get();
Return $value;
}
However, I would not advise this at all. Instead of storing the query filters in an array I feel you should just make them methods in your model. This will help with readability, modularity, and having reusable code.
public function get_user_by_name($name){
$user = DB::table('users')->where('name', 'LIKE', '%'.$name.'%')->get();
return $user;
}
public function get_group_by_name($name, $criteria = 'LIKE'){
$groups = DB::table('groups')->where('name', $criteria, '%'.$name.'%')->get();
return $groups;
}
http://laravel.com/docs/database/fluent