Bien qu'il ne soit pas tout à fait comme Yii, il peut être fait comme une extension/composant, et est traité comme une commande normale, donc les transactions s'appliquent toujours. Il serait tout à fait possible de le configurer pour utiliser des paramètres plutôt que des chaînes de caractères dans la requête, et pourrait également implémenter la vérification des valeurs nulles et par défaut.
class CDbMultiInsertCommand extends CDbCommand{
/** @var CActiveRecord $class */
private $class;
/** @var string $insert_template */
private $insert_template = "insert into %s(%s) ";
/** @var string $value_template */
private $value_template = "(%s)";
/** @var string $query */
public $query;
/** @var CDbColumnSchema[] $columns */
private $columns;
/** @var boolean $fresh */
private $fresh;
/** @var CDbConnection $db */
private $db;
/** @param CActiveRecord $class
* @param CDbConnection $db
*/
public function __construct($class, $db = null){
$this->class = $class;
$this->createTemplate();
if(is_null($db)){
$this->db = Yii::app()->db;
}
else{
$this->db = $db;
}
}
private function createTemplate(){
$this->fresh = true;
$value_template = "";
$columns_string = "";
$this->columns = $this->class->getMetaData()->tableSchema->columns;
$counter = 0;
foreach($this->columns as $column){
/** @var CDbColumnSchema $column */
if($column->autoIncrement){
$value_template .= "0";
}
else if($column->type == "integer" || $column->type == "boolean" || $column->type == "float" || $column->type == "double") {
$value_template .= "%d";
}
else{
$value_template .= "\"%s\"";
}
$columns_string .= $column->name;
$counter ++;
if($counter != sizeof($this->columns)){
$columns_string .= ", ";
$value_template .= ", ";
}
}
$this->insert_template = sprintf($this->insert_template, $this->class->tableName(), $columns_string);
$this->value_template = sprintf($this->value_template, $value_template);
}
/** @param boolean $validate
* @param CActiveRecord $record
*/
public function add($record, $validate = true){
$values = array();
if($validate){
if(!$record->validate()){
return false;
}
}
$counter = 0;
foreach($this->columns as $column){
if($column->autoIncrement){
continue;
}
$values[$counter] = $this->class->{$column->name};
$counter ++;
}
if(!$this->fresh){
$this->query .= ",";
}
else{
$this->query = "values";
}
$this->fresh = false;
$this->query .= vsprintf($this->value_template, $values);
return true;
}
public function getConnection(){
return $this->db;
}
public function execute(){
$this->setText($this->insert_template." ".$this->query);
return parent::execute();
}
}
L'usage serait :
$transaction = Yii::app()->db->beginTransaction();
$multi = new CDbMultiInsertCommand(new Mymodel());
for ($i = 0;$i < 10;$i++){
$model = new Mymodel();
$model->x = $i;
$multi->add($model, $shouldBeValidated);
}
$multi->execute();
if ($transaction->active)
$transaction->commit();
Bien sûr, il pourrait être plus élaboré et étendu pour permettre des mises à jour, etc.
J'espère que cela vous aidera.