How to use where clause on an object in laravel - mysql

I want to use a where clause on an object. I have tried the below method
DB::table('user')
->where('account_id', 17)
->where('address', '{"city":{"zipcode":0,"code":0},"country":{"code":0,"pincode":0}}')
->delete();
Which is giving below error
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. (SQL: delete from "user".....
Can anyone help me to solve this?
Thanks.

I assume you stored json in the address field. Also maybe try ->get() first before deleting.
Your json string is invalid. Possible solution is to json_encode an array with your data.
$json = json_encode([
"city" => [
"zipcode" => 0,
"code" => 0
],
"country" =>
"code" => 0,
"pincode" => 0
]);
$users = User::where('account_id', 17)
->where('address', $json)
->get();
# now do action with users or do delete(I don't know if u can delete a null result or if it throws err.)

Related

How to properly use Yii2 querybuilder insert method?

I was trying to use the QueryBuilder object to generate a properly escaped INSERT statement. The database table name is generated using an uploaded file's name and there'd be multiple tables, so using a model here is not really an option.
The code I tried to use was this:
$params = [
"index" => $row["A"],
"description" => $row["B"],
];
$conn->createCommand(
$qb->insert($tableName, [
"Index" => ":index",
"Description" => ":description",
], $params),
$params
)->execute();
The SQL error message I got was this that the number of parameters did not match the number of tokens.
My primary problem was that the documentation does not properly explain what the $params variable should be. I found out that it should be an empty, but initialised array, so basically $params = [];.
Also, since the function uses $params as a reference, they are already processed by the QueryBuilder object and I don't need to escape my values two times.
The final code that worked was this:
$params = [];
$conn->createCommand(
$qb->insert($tableName, [
"Index" => $row["A"],
"Description" => $row["B"],
], $params),
$params
)->execute();
I hope this helps anyone out there sometime.
It is simple as that:
$conn->createCommand()->insert($tableName, [
"Index" => $row["A"],
"Description" => $row["B"],
])->execute();
The yii\db\Command::insert() does the escaping for you. E.g.:
$a = "a'b\"";
echo \Yii::$app->db->createCommand()->insert('t', ['a' => $a])->getRawSql() . "\n";
returns
INSERT INTO `t` (`a`) VALUES ('a\'b\"')

Laravel: DB Query returns stdclass instead of array

I've got the following:
$srv = DB::table('ads')
->join('ad_service','ad_service.ad_id', '=', 'ads.id')
->select('ads.id')
->whereIn('ads.id',[45789,46531])
->get();
Log::info($srv);
and log info gives me
49 => stdClass::__set_state(array(
'id' => '46531',
)),
50 =>
stdClass::__set_state(array(
'id' => '46531',
)),
51 =>
stdClass::__set_state(array(
'id' => '46531',
)),
What I would like to have:
return the entry ONCE, there are multiple entries with this id in the "ad_service" table , and i would like to retrieve it once.
its a many to many relationship.
also biggest problem, what is this stdclass set state?
I was expecting something like:
array('id' => '46531', ...,)
thanks guys.
EDIT:
Solved it using Eloquent:
$srv = Ad::whereIn('id',[46696,48982,...MORE IDS HERE])->get();
this returns not an object but a collection itself. i do not really know what #ourmandave meant with "you get a collection with std class objects" i mean obviously i could see that but i do not really know why i got it, and why i get it as i wish using eloquent.
Any answer to that would be appreciated:
Why does DB:: return this std class stuff and Eloquent returns the "wanted format"?
If you just want one record you could try:
$srv = DB::table('ads')
->join('ad_service','ad_service.ad_id', '=', 'ads.id')
->select('ads.id')
->whereIn('ads.id',[45789,46531])
->first();
Change the get to a first(). The reason you are getting multiple records is because get() returns a laravel collection of your ads.
You're actually getting back a lararvel Collection.
From the docs (https://laravel.com/docs/5.8/queries#retrieving-results)
The get method returns an Illuminate\Support\Collection containing the
results where each result is an instance of the PHP stdClass object.
You may access each column's value by accessing the column as a
property of the object:
foreach ($users as $user) {
echo $user->name;
}
There's a lot of methods they provide for collections to treat them like arrays.
(https://laravel.com/docs/5.8/collections#available-methods)
You might also try the distinct() method to get back one of multiples.
$srv = DB::table('ads')
->join('ad_service','ad_service.ad_id', '=', 'ads.id')
->select('ads.id')
->whereIn('ads.id',[45789,46531])
->distinct()
->get();
To convert a model and its loaded relationships to an array, you should use the toArray method. This method is recursive, so all attributes and all relations (including the relations of relations) will be converted to arrays
$srv = DB::table('ads')
->join('ad_service','ad_service.ad_id', '=', 'ads.id')
->select('ads.id')
->whereIn('ads.id',[45789,46531])
->get()
->toArray();
Print array:
Log::info($srv);

How do I make the most effective and efficient logic to check the data in the database exist or not?

I use laravel 5.6
I have a json file containing 500 thousand records. I want to create a logic to check whether the id of each record already exists or not in the database. If it doesn't already exist, then there will be a data insert process. If it already exists, there will be a data update process
I have made logic. I just want to make sure whether my logic is effective or not
My logic code like this :
$path = storage_path('data.json');
$json = json_decode(file_get_contents($path), true);
foreach ($json['value'] as $value) {
$data = \DB::table('details')->where('id', '=', $value['Code'])->get();
if ($data->isEmpty()) {
\DB::table('details')->insert(
[
'id' => $value['Code'],
'number' => $value['Number'],
...
]
);
}
else {
\DB::table('details')
->where('id', '=', $value['Code'])
->update([
'id' => $value['Code'],
'number' => $value['Number'],
...
]);
}
}
The code is working. But the process seems really long
Do you have another solution that is better?
updateOrCreate
You may also come across situations where you want to update an existing model or create a new model if none exists. Laravel provides an updateOrCreate method to do this in one step. Like the firstOrCreate method, updateOrCreate persists the model, so there's no need to call save():
// If there's a flight from Oakland to San Diego, set the price to $99.
// If no matching model exists, create one.
$flight = App\Flight::updateOrCreate(
['departure' => 'Oakland', 'destination' => 'San Diego'],
['price' => 99]
);
in your case your code should be like this (create Details model first) :
$path = storage_path('data.json');
$json = json_decode(file_get_contents($path), true);
foreach ($json['value'] as $value) {
Details::updateOrCreate(
[ 'id' => $value['Code'] ],
[ 'number' => $value['Number'], ... ]
);
}
i think that's the best way to do it. Eloquent return's a collection so you cant just validate that your string is null.

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.

Codeigniter/Mysql: Column count doesn't match value count with insert_batch()?

Alright, so i have a huge list (like 500+) of entries in an array that i need to insert into a MySQL database.
I have a loop that populates an array, like this:
$sms_to_insert[] = array(
'text' => $text,
'contact_id' => $contact_id,
'pending' => $status,
'date' => $date,
'user_id' => $this->userId,
'sent' => "1"
);
And then i send it to the database using the built insert_batch() function:
public function add_sms_for_user($id, $sms) {
//$this->db->delete('sms', array("user_id" => $id)); Irrelevant
$this->db->insert_batch('sms', $sms); // <- This!
}
The error message i get is as follows:
Column count doesn't match value count at row 1.
Now, that doesn't make sense at all. The columns are the same as the keys in the array, and the values are the keys value. So, why is it not working?
Any ideas?
user_id turned out to be null in some situations, that's what caused the error.
EDIT: If you replace insert_batch() with a loop that runs insert() on the array keys you will get more clear error messages.