How to properly use Yii2 querybuilder insert method? - yii2

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\"')

Related

I want to modify array-column output when fetched

This is my data table image
my blade file
#table([
'id' => 'Persons.index',
'xhr' => route('api.manage-dup-api'),
'ns' => 'PersonsIndex',
'columns' => $columns ?? [],
'filters' => $filterTable ?? [],
'params' => [
'filters_live' => false,
'selectable' => true,
'toolbar_style' => 'fixed'
]
])
this is a query which passes data to a data table [API]
$q->with('user')
->with('user.roles')
->select(
'persons.*',
'birth->date as birthdate'
)->`enter code here`whereIn('id', $id)->orWhereIn('old_id_CONINET', $coninet_ids);
return $this->outputList($q, $request);
as shown in the picture I want to remove ["] from the CONINET_ID table
you are storing an array of strings in the DB.
you can convert the array values to int:
array_map('intval', $array);
you can also create an accessor on your eloquent model
public function getOldIdConinetAttribute($value)
{
return array_map('intval', $value);
}
It would better if you give some detailed info. As of now details mentioned above can not explain your code. As of my understanding, I suggest you to check Yajra datatable plugin which will help you solving your issue.
or you can cast coninet_id to array by adding below code in your model.
protected $casts = [
'coninet_id' => 'array'
];

How to use where clause on an object in laravel

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.)

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.

Looping through an array and executing statement in MYSQL

Is it possible to loop through this array in mysql and execute a delete statement where the category_id column is equal to the current value been looped in that array below.
$row = [
'type' => '3',
'name' => 'Warez',
'category_id' => 'IAB26-2',
'parent_category_id' => 'IAB26'
],
[
'type' => '3',
'name' => 'Spyware/Malware',
'category_id' => 'IAB26-3',
'parent_category_id' => 'IAB26'
],
[
'type' => '3',
'name' => 'Copyright Infringement',
'category_id' => 'IAB26-4',
'parent_category_id' => 'IAB26'
],
[
'type' => '3',
'name' => 'Uncategorized',
'category_id' => 'IAB24'
]
I have tried this
foreach($row as $value) {
$this->execute('DELETE from categories WHERE category_id = '.$value['category_id'].'');
}
doesn't seem to work as it should. Is there is better Sql command for this kind of operation?
Your code is insecure because it's possible to inject SQL. So an attacker might execute whatever he wants in your SQL query.
If this is really CakePHP code, why aren't you using the ORM? You cleary should read https://book.cakephp.org/3.0/en/orm.html the Table Objects and Deleting Data section. If not don't use wrong tags.
Assuming this is done in a table object, the most simple way to do this is:
$ids = Hash::extract($data, '{n}.category_id');
if (!empty($ids)) {
$this->deleteAll([
'category_id IN' => $ids
]);
}
You probably just need to wrap the value you concatenate with quotes (because it's not numeric).
Something like this:
$this->execute('DELETE from categories WHERE category_id = "'.$value['category_id'].'"');
However, doing DELETE ... WHERE as suggested in one of the comments would yield better performance.
Also, note that if the data comes from the user then it may be susceptible to SQL injection, so you should read about and use parameterized queries rather than concatenation.
Using an IN clause
$list = array(); foreach ($row as $item) {
$list[] = "'{$item['category_id']}'";
}
$sql = 'DELETE from categories WHERE category_id IN ('.implode(',',$list).')';
$this->execute( $sql );

Search and view Elasticsearch results from an HTML

I am currently working on a project and as the title suggests, what I want to do is to be able to search from an HTML a cluster already uploaded on elasticsearch and preview the results back in the HTML.
I thought of using Logstash to send the search input from HTML to elasticsearch but I can't figure a way of viewing those results back in the HTML. In general what I want to do, is to be able to work with elasticsearch the way kibana does, but from a website.
Appreciate any possible help :)
use php-elastic official library(https://github.com/elastic/elasticsearch-php).
You can use the following code to get the search result:
$this->client = ClientBuilder::create()->setHosts(["ELASTICSEARCH_HOST:ELASTICSEARCH_PORT"])->build();
$queryBody = ["match_all" => new \stdClass()];
if($search) {
$queryBody = [
"match" => [
"_all" => $search
]
];
}
$params = [
"from" => $page * $this->pageSize, // if you want data for pagination
"size" => $this->pageSize, // if you want data for pagination
"index" => $index,
"type" => $type,
"_source_include" => $fields, // Your required field array
"body" => [
"query" => $queryBody
]
];
//Get the search result
$response = $this->client->search($params);