How move a save model outside a loop in Yii? - activerecord

I need to move outside a loop the $model->save() sentence, by example:
foreach ($nodes as $i => $node) {
$model = new Singer();
$model->name = $node['name'];
$model->birthDate = $node['birthDate'];
$model->save();
}
There is no way to save the model outside the loop? I mean if there is 100000 records in $nodes the save method will be executed 100000 times??
Thank you!

$values = array();
foreach ($nodes as $node) {
$values[]=array(
'name' => $node['name'],
'birthDate' => $node['birthDate']
);
}
Yii::app()->db->schema->getCommandBuilder()->createMultipleInsertCommand(Singer::model()->tableName(), $values)->execute();

There isn't any other solution. If you have 100,000 records, you have to iterate 100,00 times!
You can also use CDbCommand for faster response in this way:
$values = "";
foreach ($nodes as $i => $node) {
$values.= "(". $node['name'] . "," . $node['birthDate'] . ")" . ",";
}
$values = rtrim($values, ",") //remove last "," from $values
$sql = 'ISERT INTO "singer"(name, birthDate) VALUES '.$values;
$connection = Yii::app() -> db;
$command = $connection -> createCommand($sql);
$command -> execute();

Related

How to build a dynamic doctrine query?

I am trying to build a dynamic doctrine query. When I try like this, it works
$qb->andWhere($qb->expr()->orX(
$qb->expr()->andX(
$qb->expr()->eq('t.width', '245'),
$qb->expr()->eq('t.height', '45'),
),
$qb->expr()->andX(
$qb->expr()->eq('t.width', '225'),
$qb->expr()->eq('t.height', '65'),
)
));
But I will pass the key and value from the array.
My array looks like this:
[
0 => [
"width" => "245"
"height" => "45"
]
1 => [
"width" => "225"
"height" => "65"
]
]
Now, I tried following code.
$conditions = $qb->expr()->orX(
$qb->expr()->andX()
);
foreach ($wheres as $outerKey => $outerValue) {
foreach ($outerValue as $innerKey => $innerValue) {
$conditions->add("te.$innerKey = :innerValue");
$qb->setParameter('innerValue', $innerValue);
}
}
$qb->andWhere($conditions);
dd($qb->getDQL());
But the SQL returned is not the same as when I tried with static value.
So you can do this in 2 ways (that I could think of). First, using expressions like you showed above but with and extra private function:
private function getExpressions(QueryBuilder $qb, array $fields)
{
$andX = $qb->expr()->andX();
foreach ($fields as $field => $value) {
$andX->add($qb->expr()->eq('t.' . $field, $value));
}
return $andX;
}
public function getDQL($conditions)
{
$qb = $this->createQueryBuilder('t');
$orX = $qb->expr()->orX();
foreach ($conditions as $i => $fields) {
$orX->add($this->getExpressions($qb, $fields));
}
$qb->add('where', $orX);
dump($qb->getDQL());
exit;
}
For me it was a bit time consuming to figure this out. I actually did it a lot faster the way mentioned above (building the where clause manually):
$i = 0;
foreach ($conditions as $fields) {
$j = 0;
foreach ($fields as $field => $value){
$whereStr .= " " . $field . " = " . $value;
$j++;
if ($j < count($fields)){
$whereStr .= " AND";
}
}
$i++;
if ($i < count($conditions)){
$whereStr .= " OR";
}
}
If I understand your logic correctly this should work. You can switch the orX/andX expressions if I misunderstood your requirements.

How to properly update a array that has only one identifying id

I'm trying to update an array with objects inside something like this, with the current code I have it only saves the first one, I know that's the problem but I don't know how to fix it
array (
0 =>
array (
'option' => 'new',
),
1 =>
array (
'option' => 'ewrwer',
),
),
This is my current code, the line in question is
$option = SurveyQuestionOption::where('survey_question_id', $preg->id)->first();
How do I fix this so it cycles through all in the array questionOptions instead of just the first one? I tried ->get() but then the ->save() doesn't work.
public function update(Request $request, $id)
{
DB::beginTransaction();
$preg = SurveyQuestion::findOrFail($id);
$preg->question = $request->question;
$preg->survey_section_id = $request->survey_section_id;
$preg->response_type_id = $request->response_type_id;
$preg->optional = $request->optional;
$preg->save();
$ids = [];
if ($request->get('questionOptions')) {
foreach ($request->get('questionOptions') as $item) {
$option = SurveyQuestionOption::where('survey_question_id', $preg->id)->first();
if (empty($option)) {
$option = new SurveyQuestionOption();
$option->survey_question_id = $preg->id;
}
$option->option = $item['option'];
$option->save();
}
}
if (count($ids) > 0) {
SurveyQuestionOption::whereNotIn('id', $ids)->where('survey_question_id', $preg->id)->delete();
}
DB::commit();
return back();
}
Basically, when you use get, you get a collection, so you can't really use save on it. you need to do a foreach loop, and save in that. i.e; like this;
$options = SurveyQuestionOption::where('survey_question_id', $preg->id)->get();
foreach($options as $option){
if (empty($option)) {
$option = new SurveyQuestionOption();
$option->survey_question_id = $preg->id;
}
$option->option = $item['option'];
$option->save();
}
Note that you can't save $options if you don't use a foreach loop, as you're not specifying which instance of the collection to save it in.

foreach loop my code is as follows

$codes = test1,test2,test3;
$names = 1226261693assistenza-pc-1-1.jpeg,1226261693cobinhood.png,1226261693a.png;
foreach($codes as $k=>$v AND $names as $k2=>$v2){
echo '<TR><TD>$k</TD><TD>$v</TD><TD>$k2</TD><TD>$v2</TD></TR>;
}
This method didn't work for me. Any suggestions?
This method didn't work for me. Any suggestions?
Cause
Missed quotes -
$codes = test1,test2,test3;
$names = 1226261693assistenza-pc-1-1.jpeg,1226261693cobinhood.png,1226261693a.png;
Should be like this
$my_string_var = '<your string>'; OR
$my_string_var = "<your string>";
That is not valid - foreach($codes as $k=>$v AND $names as $k2=>$v2){ }
foreach operates on only one array at a time.
Solution
If you have string variable like below,
$codes = 'test1,test2,test3';
$names = '1226261693assistenza-pc-1-1.jpeg,1226261693cobinhood.png,1226261693a.png';
Then make array and combine using array_combine(), them and then loop it like below
$array = array_combine ( explode(',',$codes), explode(',', $names) );
/*
loop array as array_key => array_value
$k = your array key
$v = you array value
*/
foreach($array as $k=>$v)
{
echo "<TR><TD>$k</TD><TD>$v</TD></TR>";
}
Or else define array itself like below and loop it
$array = array(
/* array_key => array_value */
'test1' => '1226261693assistenza-pc-1-1.jpeg',
'test2' => '1226261693cobinhood.png'
);

Yii: save multiple records in one query

I'm trying to save a lot of CActiveRecord model objects in a loop.
I have something like this:
foreach ($array_of_items as $item) {
$values = array(
"title" => $item->title,
"content" => $item->content,
);
$object = new MyModel;
$object->attributes = $values;
$object->save();
}
In my case, this creates about 400 CActiveRecord objects. The saving process is really slow, because each save() queries the database.
Is there a way to save all those objects in one go?
Something like:
$objects = array();
foreach ($array_of_items as $item) {
$values = array(
"title" => $item->title,
"content" => $item->content,
);
$object = new MyModel;
$object->attributes = $values;
$objects[] = $object;
}
save_all_objects($objects);
I could not find anything on the subject. Anyone?
you can validate() your model, and if it was ok you can append it so a sql text for insert,
and after your loop, just use databases commandBuilder() and execute your prepared text
$sql = '';
if($object->validate())
{
$sql .= ',("' . $object->attr1 . '")'// append to script,(you get the idea, you need to also make a correct values)
}
...
if(!empty($sql))
{
$sql = 'INSERT INTO table (attr1) Values' . $sql;// make complete script
// execute that command
}
Since v1.1.14, the method createMultipleInsertCommand() of CDbCommandBuilder class is available.
For insert multi rows, Put this code in components folder under GeneralRepository.php file name.
<?php
class GeneralRepository
{
/**
* Creates and executes an INSERT SQL statement for several rows.
* By: Nabi K.A.Z. <www.nabi.ir>
* Version: 0.1.0
* License: BSD3
*
* Usage:
* $rows = array(
* array('id' => 1, 'name' => 'John'),
* array('id' => 2, 'name' => 'Mark')
* );
* GeneralRepository::insertSeveral(User::model()->tableName(), $rows);
*
* #param string $table the table that new rows will be inserted into.
* #param array $array_columns the array of column datas array(array(name=>value,...),...) to be inserted into the table.
* #return integer number of rows affected by the execution.
*/
public static function insertSeveral($table, $array_columns)
{
$connection = Yii::app()->db;
$sql = '';
$params = array();
$i = 0;
foreach ($array_columns as $columns) {
$names = array();
$placeholders = array();
foreach ($columns as $name => $value) {
if (!$i) {
$names[] = $connection->quoteColumnName($name);
}
if ($value instanceof CDbExpression) {
$placeholders[] = $value->expression;
foreach ($value->params as $n => $v)
$params[$n] = $v;
} else {
$placeholders[] = ':' . $name . $i;
$params[':' . $name . $i] = $value;
}
}
if (!$i) {
$sql = 'INSERT INTO ' . $connection->quoteTableName($table)
. ' (' . implode(', ', $names) . ') VALUES ('
. implode(', ', $placeholders) . ')';
} else {
$sql .= ',(' . implode(', ', $placeholders) . ')';
}
$i++;
}
$command = Yii::app()->db->createCommand($sql);
return $command->execute($params);
}
}
And usage anywhere:
$rows = array(
array('id' => 1, 'name' => 'John'),
array('id' => 2, 'name' => 'Mark')
);
GeneralRepository::insertSeveral(User::model()->tableName(), $rows);
https://www.yiiframework.com/extension/yii-insert-multi-rows

How to get parameters in JFormField from a disabled plugin in Joomla 1.6/2.5?

How i can get some parameters from a disabled/not yet actived plugin in joomla 1.6/2.5?
$module = JPluginHelper::getPlugin('system','myplugin');
$moduleParams = new JParameter($module->params);
$val = $moduleParams->get("key");
This method didn't work becouse i need to use within an element JFormField generator.
Thanks for help!
With JPluginHelper::getPlugin it's possible to access only enabled plugins, so here's the code for direct access to database.
// Build query
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select( 'params' )
->from( '#__extensions' )
->where( 'type = ' . $db->q('plugin') )
->where( 'folder = ' . $db->q('authentication') ) // Plugin type
->where( 'element = ' . $db->q('gmail') ) // Plugin element
;
// Execute query
$db->setQuery($query);
try
{
$result = $db->loadResult();
}
catch (RuntimeException $e)
{
return false;
}
// Parse parameters
if (!empty($result))
{
$params = new JRegistry($result);
$val = $params->get('key', 'defaultValue');
}
You may store query results in in the JFormField Object so save database queries in case field is availabile multiple times.
protected $results = null;
Perhaps you may want to try this:
// Get plugin parameters
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('`params`')
->from ('`#__extensions`')
->where ("`type` = 'plugin'")
->where ("`folder` = 'system'")
->where ("`element` = 'myplugin'");
$db->setQuery($query);
$res = json_decode($db->loadResult(), true);
$val = $res['key'];
Just find the answer by myself.
$data = null;
foreach ((array) $this->form as $k => $v) {
if($val instanceof JRegistry){
$data = &$v;
break;
}
}
$data = $data->toArray();
$val = $data['params']['key'];
Thanks! Bye!

Resources