YII2 extra condition with AND operator - yii2

I'm updating a record in this way:
Yii::$app->db->createCommand()->update('table', ['config' => json_encode($array)],
'field1 = :field1', [':field1' => $field1]
)->execute();
My aim is to add an extra condition with the AND operator but I don't know how to do it.
I've followed this example: LINK
// UPDATE (table name, column values, condition)
Yii::$app->db->createCommand()->update('user', ['status' => 1], 'age > 30')->execute();
But it doesn't show a lot of possibilities.

try this way
Yii::$app->db->createCommand()
->update('table', ['config' => json_encode($array)],
'field1 = :field1 AND field2 = :field2',[':field1' => $field1,':field2' => $field2])
->execute();

Just like an array, with each condition separated by a ,.
In your case:
Yii::$app->db->createCommand()->update(
'table',
['config' => json_encode($array)],
['field1' => $field1, 'field2' => $field2]
)->execute();
Note that with this syntax you don't need to bind params, you could specify them directly inside the array of conditions as Yii2 santizes them.

Related

Multiple Fields with a GroupBy Statement in Laravel

Already received a great answer at this post
Laravel Query using GroupBy with distinct traits
But how can I modify it to include more than just one field. The example uses pluck which can only grab one field.
I have tried to do something like this to add multiple fields to the view as such...
$hats = $hatData->groupBy('style')
->map(function ($item){
return ['colors' => $item->color, 'price' => $item->price,'itemNumber'=>$item->itemNumber];
});
In my initial query for "hatData" I can see the fields are all there but yet I get an error saying that 'colors', (etc.) is not available on this collection instance. I can see the collection looks different than what is obtained from pluck, so it looks like when I need more fields and cant use pluck I have to format the map differently but cant see how. Can anyone explain how I can request multiple fields as well as output them on the view rather than just one field as in the original question? Thanks!
When you use groupBy() of Laravel Illuminate\Support\Collection it gives you a deeper nested arrays/objects, so that you need to do more than one map on the result in order to unveil the real models (or arrays).
I will demo this with an example of a nested collection:
$collect = collect([
collect([
'name' => 'abc',
'age' => 1
]),collect([
'name' => 'cde',
'age' => 5
]),collect([
'name' => 'abcde',
'age' => 2
]),collect([
'name' => 'cde',
'age' => 7
]),
]);
$group = $collect->groupBy('name')->values();
$result = $group->map(function($items, $key){
// here we have uncovered the first level of the group
// $key is the group names which is the key to each group
return $items->map(function ($item){
//This second level opens EACH group (or array) in my case:
return $item['age'];
});
});
The summary is that, you need another loop map(), each() over the main grouped collection.

laravel 5 update multiple columns in one line?

It's possible update multiple columns in one line with laravel 5.4?
I try to this
DB::table('Home_Content')->where('id',1)->update(
[$_POST['name'] => $_POST['content']],
[$_POST['title'] => $_POST['titleMsg']]
);
only 1st part is work([$_POST['name'] => $_POST['content']])
server not return any error, but only 1st part is success.
Update method syntax in Laravel is like so :
DB::table('users')
->where('id', 1)
->update(['options->enabled' => true]);
Which means the values we want to update are inside an array, what I've seen is that you separated what you want to update into two arrays
DB::table('Home_Content')->where('id',1)->update(
[$_POST['name'] => $_POST['content']],
[$_POST['title'] => $_POST['titleMsg']]
);
so now you are out of the array
Your code should be like this
DB::table('Home_Content')->where('id',1)->update([
$_POST['name'] => $_POST['content'],
$_POST['title'] => $_POST['titleMsg']
]);
Meaning each pair has a key and a value and separated with comma
If you want to update record in multiple row with id as Array() use following query.
DB::table('users')
->whereIn('id', [1,2,3])
->update(['status' => 1]);

Yii2 Query not quoting correctly

I run into this problem, time and time again. It would be nice to find out how to build queries properly so I can stop resorting to Yii::$app->db->createCommand() as a workaround.
My Yii2 query:
$users = UserSpatial::find()
->select('user_id, harvesine(y(coordinates), x(coordinates), :lat, :lon) as dist, astext(coordinates)')
->where('st_within(coordinates, envelope(linestring(point(:rlon1, :rlat1), point(:rlon2, :rlat2))))')
->orderBy('st_distance(point(:lon, :lat), coordinates)')
->params([
':lon' => $geo->lon,
':lat' => $geo->lat,
':rlon1' => $rlon1,
':rlat1' => $rlat1,
':rlon2' => $rlon2,
':rlat2' => $rlat2
])
->all();
The generated query ends up with backticks in all the wrong places and, oddly enough, not all parameters were backticked (sorry but you'll need to look closely for the misplaced backticks because I didn't know how best to highlight the incorrect placements):
SELECT \`user_id\`, harvesine(y(coordinates), x(coordinates), \`32.7699547\`, \`-116.9911288)\` AS \`dist\`, astext(coordinates)
FROM \`user_spatial\`
WHERE st_within(coordinates, envelope(linestring(point(-117.07730792871, 32.697490931884), point(-116.90494967129, 32.842418468116))))
ORDER BY st_distance(point(-116.9911288, \`32.7699547)\`, \`coordinates)\`
The query should look like the following as I did not wrap double-square-brackets around any of the fields or values:
SELECT \`user_id\`, harvesine(y(coordinates), x(coordinates), 32.7699547, -116.9911288) AS dist, astext(coordinates)
FROM \`user_spatial\`
WHERE st_within(coordinates, envelope(linestring(point(-117.07730792871, 32.697490931884), point(-116.90494967129, 32.842418468116))))
ORDER BY st_distance(point(-116.9911288, 32.7699547), coordinates)
I can live with Yii2 adding some backticks around field names and table names but why on earth is it backticking numerical values? (FYI: the $rlon and $rlat values don't seem to get backticked but I was assuming that was because they are a result of math calculations!?!?).
I've already tried forcing $geo->lon and $geo->lat to float values like so:
'lon' => (float)$geo->lon;
or
'lon' => (float)$geo->lon * 1;
but it didn't help.
Try to use array format for select and orderBy methods, like docs suggest:
Besides column names, you can also select DB expressions. You must use
the array format when selecting a DB expression that contains commas
to avoid incorrect automatic name quoting. For example,
$query->select(["CONCAT(first_name, ' ', last_name) AS full_name",
'email']);
In you case it will be like this:
$users = UserSpatial::find()
->select([
'user_id',
'harvesine(y(coordinates), x(coordinates), :lat, :lon) as dist',
'astext(coordinates)'
])
->where('st_within(coordinates, envelope(linestring(point(:rlon1, :rlat1), point(:rlon2, :rlat2))))')
->orderBy(['st_distance(point(:lon, :lat)', 'coordinates)'])
->params([
':lon' => $geo->lon,
':lat' => $geo->lat,
':rlon1' => $rlon1,
':rlat1' => $rlat1,
':rlon2' => $rlon2,
':rlat2' => $rlat2
])
->all();

CakePHP 3 query builder more conditions for one field

I should build up an sql query from a dynamically built up form. The user will select table fileds and AND/OR logical conditions between them. So in the end I should have an SQL query like this:
WHERE (
name LIKE "%foo%"
OR name LIKE "%bar%"
)
AND (
ad = "BP"
OR ad = "SV"
)
I tried
$query
->where(['Contacts.name LIKE' => '%foo%'])
->orWhere(['Contacts.cname LIKE' => '%bar%'])
->andWhere(function($exp){
return $exp->or_(
['Contacts.ad' => 'BP'],
['Contacts.ad' => 'SV']
);
})
);
What is clearly not good as I override Contacts.ad. I tried different ways but I was unable to get the right parenthesis.
The actual problem is more complex, as it may contain more fileds, not just this two (name and ad)
I would do this:
$query->where(['Contacts.name LIKE' => '%foo%'])
->orWhere(['Contacts.cname LIKE' => '%bar%'])
->andWhere([
'OR' => [
['Contacts.ad' => 'BP'],
['Contacts.ad' => 'SV']
]
]);

problem with ActiveRecord/Rails ordering of query data from MySQL -- no problem in SQLite

I have the following two ActiveRecord queries in an application_helper.rb file:
#left_menu = Page.select('id, menu_name').where(:published => true, :left_menu => true).order("sort")
Also can be written as:
#left_menu = Page.select('id, menu_name').where(:published => true, :left_menu => true).order("'sort' ASC")
and:
#left_menu = Page.find(:all, :conditions => {:published => true, :left_menu => true}, :order => :sort)
Why does the first one fail to sort on the 'sort' column, while the second one does not? Both work in SQLite, but only the second one works in MySQL.
Any ideas?
it's the quote in ther order params .
the query generated will be (similar to)
"SELECT id, title FROM `pages` WHERE (`pages`.`pub` = 1) ORDER BY 'sort' ASC"
its the char ' quote . It's wrong sql syntax , it's going to order by costant value not column value . sqlite allow it , mysql not.
try to simple use
Page.select('id, menu_name').where(:published => true, :left_menu => true).order("sort ASC")
without single quote in the order chain method parameters.
sorry for my english.
have a nice day