Optimize Multiple database update - mysql

I am using laravel in my app.
So now I need to update many rows on DB once a day with Cron job.
If I will use the update option built-in laravel I need to do something like this:
// for example, the update info in array
$arrayToUpadte = [
[
'numberId' => '0500000000',
'usagePer' => '4.5'
],
[
'numberId' => '0500000001',
'usagePer' => '5.6'
],
[
'numberId' => '0500000002',
'usagePer' => '8.1'
],
[
'numberId' => '0500000003',
'usagePer' => '0.3'
]
];
// update will do one query to db every update!!
foreach( $arrayToUpadte as $updates ){
\App\Phonelines::where( 'numberId', '=', $updates['numberId'] )->update([
'usagePer' => $updates['usagePer']
]);
}
So my question is how I can Improve code to have as few queries as possible?
If I have this in a regular PHP project I would do it like this:
$newValues = [];
foreach( $arrayToUpadte as $updates ){
$newValues[] = $updates['numberId'] . ',' . $updates['usagePer'];
}
$newValues = implode( '),(', $newValues );
$mysqli -> query( "
INSERT INTO `phonelines` ( `numberId`, `usagePer` ) VALUES (" . $newValues . ")
ON DUPLICATE KEY
UPDATE `usagePer` = VALUES( `usagePer` );
" );
Is there a way to do this in Laravel's Framework?

you can use this :
DB::raw("INSERT INTO `phonelines` ( `numberId`, `usagePer` )
VALUES (" . $newValues . ") ON DUPLICATE KEY
UPDATE `usagePer` = VALUES( `usagePer` )") ;

Related

Missing required parameter in yii2 Search

i want to search the stock till a particular date. User will fill this date form. The first page where user go to input the date field is _formtilldate.
Controller action -
public function actionIndex3() {
//$enddate = '2018-03-01';
$searchModel1 = new SellitemSearch();
$dataProvider1 = $searchModel1->search ( Yii::$app->request->queryParams );
//$searchModel2 = new PuritemtilldateSearch();
//$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams);
return $this->render ( '_formtilldate' , [
'model1' => $searchModel1 ,
//'enddate' => $enddate,
//'model2' => $searchModel2,
//'searchModel1' => $searchModel2,
] );
}
And the form field
<?php
$form = ActiveForm::begin ( [
'id' => 'form-id' ,
'action' => [ '/stock/sellitem/stocktilldate' , 'enddate' => $model1->enddate ] ,
'method' => 'get' ,
'enableClientScript' => false ,
] );
?>
<?=
$form->field ( $model1 , 'enddate' )->widget (
DatePicker::className () , [
// inline too, not bad
'options' => [ 'placeholder' => 'End Date ...' , 'id' => 'enddate1' ] ,
'inline' => false ,
//'id' => 'startdate1',
// modify template for custom rendering
//'template' => '<div class="well well-sm" style="background-color: #fff; width:250px">{input}</div>',
'clientOptions' => [
'autoclose' => true ,
'todayHighlight' => true ,
'format' => 'yyyy-mm-dd'
]
] );
?>
On clicking on the submit button, the search query runs -
Controller Action -
public function actionStocktilldate( $enddate ) {
//$enddate = '2018-03-01';
$searchModel1 = new SellitemtilldateSearch();
$dataProvider1 = $searchModel1->search ( Yii::$app->request->queryParams );
//$searchModel2 = new PuritemtilldateSearch();
//$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams);
return $this->render ( 'indexstocktilldate' , [
//'enddate' => $enddate,
'searchModel1' => $searchModel1 ,
'dataProvider1' => $dataProvider1 ,
//'searchModel2' => $searchModel2,
//'dataProvider2' => $dataProvider2,
] );
}
Search Model -
public function search( $params , $enddate ) {
//$query = Sellitem::find();
$subQuery1 = (new Query() )->select ( [ 'pi_upc' , 'sum(pi_qty) as purchased' ] )->from ( 'puritem' )->leftJoin ( 'pursum' , 'pursum.ps_id = puritem.psi_id' )->andwhere ( [ '<' , 'pursum.ps_date' , $enddate ] )->groupby ( 'pi_upc' );
$subQuery2 = (new Query() )->select ( [ 'si_iupc' , 'sum(si_qty) as sold' ] )->from ( 'sellitem' )->leftJoin ( 'sellsum' , 'sellsum.ss_id = sellitem.si_ssid' )->andwhere ( [ '<' , 'sellsum.ss_date' , $enddate ] )->groupby ( 'si_iupc' );
$subQuery3 = (new Query() )->select ( [ 'i_upc' , 'i_category' , 'i_brand' , 'i_desc' , 'i_unit' , 'i_buyprice' , 'coalesce(p.purchased,0) as purchased' ] )->from ( 'item' )->leftJoin ( [ 'p' => $subQuery1 ] , 'p.pi_upc = i_upc' );
$query = (new Query() )->select ( [ 'tp.i_upc as upc' , 'tp.i_category as category' , 'tp.i_brand as brand' , 'tp.i_desc as description' , 'tp.i_unit as unit' , 'tp.purchased as purchased' , 'coalesce(ts.sold,0) as sold' , '(coalesce(purchased,0) - coalesce(sold,0)) as stock' , 'tp.i_buyprice as rate' , 'round(((coalesce(purchased,0) - coalesce(sold,0))*tp.i_buyprice),2) as value' ] )->from ( [ 'tp' => $subQuery3 ] )->leftJoin ( [ 'ts' => $subQuery2 ] , 'ts.si_iupc = tp.i_upc' );
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query ,
'pagination' => [
'pageSize' => 10000000000 ,
] ,
]);
......
}
Now, in the url I can see the parameter got passed -
http://localhost/chayanika/frontend/web/index.php?r=stock%2Fsellitem%2Fstocktilldate&SellitemSearch%5Benddate%5D=2018-08-13
But, I'm getting error -
Bad Request (#400)
Missing required parameter: enddate
I'm not getting where I'm missing it.
I made a bit progress here -
I just learned that the date I'm getting in the URL is coming from the Action in the form. But it's not of much use so far.
If I change the controller action a bit, I get a result -
public function actionStocktilldate() {
$enddate = date ( 'Y-m-d' );
//$enddate = yii::$app->request->get('enddate');
//var_dump($enddate);
$searchModel1 = new SellitemtilldateSearch();
$dataProvider1 = $searchModel1->search ( Yii::$app->request->queryParams , $enddate );
//$searchModel2 = new PuritemtilldateSearch();
//$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams);
return $this->render ( 'indexstocktilldate' , [
//'enddate' => $enddate,
'searchModel1' => $searchModel1 ,
'dataProvider1' => $dataProvider1 ,
//'searchModel2' => $searchModel2,
//'dataProvider2' => $dataProvider2,
] );
}
Please tell me how can I pass the date collected by the form to this controller.
In your url, I don't see enddate param, I just see:
frontend/web/index.php?r=stock/sellitem/stocktilldate&SellitemSearch[enddate]=2018-08-13"
It is SellitemSearch[enddate], not enddate
You should modify your url to
frontend/web/index.php?r=stock/sellitem/stocktilldate&enddate=2018-08-13"
or remove $enddate param from actionStocktilldate function.
How is action parameter treated in ActiveForm.
Query parameters in the action are ignored for GET method. We use
hidden fields to add them back Hidden inputs are created and they are
submitted so your form action goes to the right place.
So if you look into the form source from your browser there is a hidden input created with the name enddate which will be submitted automatically.
<form id="w0" action="http://localhost/chayanika/frontend/web/index.php?r=/stock/sellitem/stocktilldate" method="get">
<input type="hidden" name="enddate" value="2018-03-01"><button type="submit">Submit</button>
</form>
Reason
But in your case, it isn't submitting because there isn't any hidden field being created. Why? because the assignment of your $model->enddate is returning null. Make sure there is a valid timestamp or date string saved.
Track
Go to line 395 of \yii\web\UrlManager function createUrl($params).
If you are using enablePrettyUrl=>true then it will enter the first check and in the foreach it appends the query string params as key where value!==null.
if($this->enablePrettyUrl){
$cacheKey = $route . '?';
foreach($params as $key => $value){
if($value !== null){
$cacheKey .= $key . '&';
}
}
if you are using enablePrettyUrl=>false then it will skip to the last section
$url = "$baseUrl?{$this->routeParam}=" . urlencode($route);
if(!empty($params) && ($query = http_build_query($params)) !== ''){
$url .= '&' . $query;
}
return $url . $anchor;
and there it will fail the check if(!empty($params) && ($query = http_build_query($params)) !== ''){ as http_build_query($params) returns empty string for an array having a key with null value.
So make sure you have a date save and the current model does not have the date saved in database as null

Getting a raw SQL query with variables in Yii1

Is Yii1 has any native methods to get the raw SQL with variables built?
I try to get a complex query built on a few subqueries using CDbExpression and CommandBuilder. I got this as a result:
SELECT * FROM `news` `t` WHERE id IN (:ycp0, :ycp1, :ycp2, :ycp3, :ycp4) LIMIT 5
The dump of the criteria content:
CDbCriteria Object (
[select] => *
[condition] => id IN (:ycp0, :ycp1, :ycp2, :ycp3, :ycp4)
...
[params] => Array(
[:ycp0] => CDbExpression Object(
[expression] => SELECT id FROM `news` `t` WHERE (rubric=:rb1) AND (:im2 & `im`=:im2) LIMIT 1
[params] => Array(
[:rb1] => 1
[:im2] => 2
)
)
...
)
)
I expected for compiled query string like this:
SELECT * FROM .. WHERE id IN(
(SELECT id FROM .. WHERE .. ORDER BY .. LIMIT 1),
(SELECT id FROM .. WHERE .. ORDER BY .. LIMIT 1)
) ORDER BY .. LIMIT 5
This is what I do in my code
$criteria = new CDbCriteria( ... );
$sql = $this->commandBuilder->createFindCommand($tableName, $criteria)->getText();
$queries[] = new CDbExpression($sql, $criteria->params);
Then I try to combine subqueries to one complex query
$criteria = new CDbCriteria( ... );
$criteria->addInCondition('id', $queries);
And finally, I try to get the result as SQL-query
$sql = $this->commandBuilder->createFindCommand($tableName, $criteria)->getText();
You get the SQL with params, as you have
$sql = $this->commandBuilder->createFindCommand($tableName, $criteria)->getText();
Then get the params enclosed in quotes:
$params = array_map(function($param) { return '"' . $param . '"'; }, $criteria->params);
Finally, replace the pairs:
echo strtr($sql, $params);
You can use enableParamLogging in your db config (boolean). You can set it up so it's used conditionally -- make sure to not use it in production.
'db' => [
'connectionString' => 'mysql:host=' . $dbhost . ';port=' . $dbport . ';dbname=' . $dbname,
'emulatePrepare' => true,
'username' => $db_user,
'password' => $db_pass,
'schemaCachingDuration' => 3600,
'charset' => 'utf8',
'enableProfiling' => $db_profile,
'enableParamLogging' => $db_params,
],
Then you can add 'class'=>'CWebLogRoute' to your log routes if you want to see all the output in your browser. docs
I think you want to do something like this:
$criteria = ...;
$command = $builder->createFindCommand($schema->getTable('name_of_table'), $criteria);
$results = $command->text;
There are few other options to perform the same thing but i will suggest you
should use the following
$results = MyModel::model()->findAllBySql("...");
Or you can prefer the following :
Sub-queries ActiveRecord Yii

Wordpress Insert Query not working

I am creating web services for an App, but I am stuck with a insert query. Actually I made a rating system and want to insert value in database with wordpress standard.
Here is my query:
$res = $wpdb->query( $wpdb->prepare(
"INSERT INTO $table_name(rating_postid, rating_posttile, rating_rating, rating_username, rating_userid) VALUES (%d, %s, %d, %s, $d )",
array(
$rating_postid,
$post_title,
$post_rating,
$user_name,
$rating_userid
)
)
);
and here is the other one:
$res = $wpdb->insert(
$table_name,
array(
'rating_postid' => $rating_postid,
'rating_posttile' => $post_title,
'rating_rating' => $post_rating,
'rating_username' => $user_name,
'rating_userid' => $rating_userid
)
);
But no one is working, why?
if($res){
echo 'inserted';
}else{
echo 'not inserted';
}
I am getting else part alwasy
I used these queries very often and they worked me very well, But I am not sure what's wrong with them now... :(
Try this.
$wpdb->insert(
$table_name,
array(
'rating_postid' => $rating_postid,
'rating_posttile' => $post_title,
'rating_rating' => $post_rating,
'rating_username' => $user_name,
'rating_userid' => $rating_userid
),
array(
'%d',
'%s',
'%s',
'%s',
'%d'
)
);
Declaring $wpdb as global and using it to execute an SQL query statement that returns a PHP object
global $wpdb;
$table_name = $wpdb->prefix . "YOUR_TABLE_NAME"; // Enter without prefix
$data = array(
'rating_postid' => $rating_postid,
'rating_posttile' => $post_title,
'rating_rating' => $post_rating,
'rating_username' => $user_name,
'rating_userid' => $rating_userid
);
$result = $wpdb->insert($table_name, $data);
if( $result ){
echo "Inserted..!";
}else{
echo "Something wrong..!";
$wpdb->show_errors();
}

ON DUPLICATE KEY UPDATE Query in Laravel4

How do I transform this
DB::table('partners')->insert(array($data));
laravel Query to have ON DUPLICATE KEY UPDATE
the structure look like
$data['program_name'] = $program['program']['_'];
$data['program_id'] = $program_id;
$data['status'] = $program['status'];
$data['shop_name'] = $shop->name;
$data['shop_logo'] = $shop->image;
$data['shop_description'] = $shop->description;
where program_id is unique
Use something like this (feel free to correct because it's untested):
DB::statement( 'INSERT INTO partners VALUES (' . implode( ',',
array_map( function( $val ) { return ":$val"; } , array_keys($data) )
) . ') ON DUPLICATE KEY UPDATE ' . implode( ',',
array_map( function( $val ) { return "$val = VALUES($val)"; } , array_keys($data) )
), $data);
I created a package that will wrapped INSERT ON DUPLICATE KEY UPDATE
https://packagist.org/packages/yadakhov/insert-on-duplicate-key
$users = [
['id' => 1, 'email' => 'user1#email.com', 'name' => 'User One'],
['id' => 2, 'email' => 'user2#email.com', 'name' => 'User Two'],
['id' => 3, 'email' => 'user3#email.com', 'name' => 'User Three'],
];
User::insertOnDuplicateKey($users);
// produces:
INSERT INTO `test_user_table`(`id`,`email`,`name`) VALUES
(1,'user1#email.com','User One'), (2,'user3#email.com','User Two'), (3,'user3email.com','User Three')
ON DUPLICATE KEY UPDATE `id` = VALUES(`id`), `email` = VALUES(`email`), `name` = VALUES(`name`)

FB:registration - array doesnt save any data

I did the Facebook Registration Plugin like in the official Facebook tutorial and with this code there it shows the total Array on screen:
if ($_REQUEST) {
echo '<p>signed_request contents:</p>';
$response = parse_signed_request($_REQUEST['signed_request'],
FACEBOOK_SECRET);
echo '<pre>';
print_r($response);
echo '</pre>';
} else {
echo '$_REQUEST is empty';
}
this brings me the following array:
signed_request contents:
Array
(
[algorithm] => HMAC-SHA256
[expires] => 1324xxxx400
[issued_at] => 132446xxx80
[oauth_token] => AAADRjT73VhwBALl6Gb3EVarvyGU7xxxxxxxxxxxxxxxxxxxSAUuoZAGlydkX2pH3
[registration] => Array
(
[name] => Philipp Mail
[email] => p.mail#xxxxde
[location] => Array
(
[name] => Munich, Germany
[id] => 1.1604xxxxxx286E+14
)
[birthday] => xx/xx/19x7
)
[registration_metadata] => Array
(
[fields] => [{'name':'name'}, {'name':'email'}, {'name':'location'}, {'name':'birthday'}]
)
[user] => Array
(
[country] => de
[locale] => de_DE
)
[user_id] => 10xxxxxxx5426
)
Now I changed it for storing several data to mysql:
if ($_REQUEST) {
echo '<p>signed_request contents:</p>';
$response = parse_signed_request($_REQUEST['signed_request'],
FACEBOOK_SECRET);
$name_arr = explode(' ',$name,2);
$vname = $name_arr[0];
$zname = isset($name_arr[1])?$name_arr[1]:'';
$email = $response["registration"]["email"];
$ort = $response["registration"]["location"]["name"];
$anrede = $response["registration"]["gender"];
$geburtstag = $response["registration"]["birthday"];
// Connecting to database
mysql_connect($dbhost, $dbuser, $dbpass) or die("MySQL Error: " . mysql_error());
mysql_select_db($dbname) or die("MySQL Error: " . mysql_error());
// Inserting into users table
$result = mysql_query("INSERT INTO REKRU_mem (mem_id, vname, zname, ort, email, userpass, chili, regdatum, geburtstag, fbuid)
VALUES
(NULL, '$vname', '$zname', '$ort', '$email', MD5('".$gesamtpass."'),'$chili', '0000-00-00 00:00:00', '$geburtstag', '$user_fbid')");
if($result){
// GOT RESULTS
}
else
{
// Error in storing
}
}
else
{
echo '$_REQUEST is empty';
}
When I look in mysql after a registration there is a new line but it saves only the actual registration time. Can anyone of U see what is my mistake?
do not use this code in a plublic Area! You can make a SQL-Injection (could also be the problem why you cannot insert).
Try this instead of the mysql_query:
$vname = mysql_real_escape_string($vname);
$zname = mysql_real_escape_string($zname);
$ort = mysql_real_escape_string($ort);
$email = mysql_real_escape_string($email);
$gesamtpass = mysql_real_escape_string($gesamtpass);
$chili = mysql_real_escape_string($chili);
$geburtstag = mysql_real_escape_string($geburtstag);
$user_fbid = mysql_real_escape_string($user_fbid);
$result = mysql_query("INSERT INTO REKRU_mem (mem_id, vname, zname, ort, email, userpass, chili, regdatum, geburtstag, fbuid)
VALUES (NULL, '".$vname."', '".$zname."', '".$ort."', '".$email."', MD5('".$gesamtpass."'),'".$chili."', '0000-00-00 00:00:00', '".$geburtstag."', '".$user_fbid."')");