ingenious
ingenious

Reputation: 772

Yii2: get raw sql of model->save()

I want to add record to a table with ActiveRecord.

Here is my code:

$model = new Article();
$model->title = 'test title';
$model->content = 'test content';
$model->category_id = 1;
$model->author_id = 1;
if ($model->validate()) {
    $model->save();
}

$model->validate() returns true, but $model->save() returns false.

How to find generated raw sql of $model->save()?

Meanwhile:

$model->save()->rawSql is null and $model->getErrors() returns empty array.

In debug, all queries are logged, but I did not find any insert or update query.

Upvotes: 7

Views: 11360

Answers (2)

borracciaBlu
borracciaBlu

Reputation: 4225

This code won't show you exactly the raw sql but you'll get the query pre binding and the params

try {
    // this will simulate $model->save();
    $builder = $model->getCommandBuilder();
    $table = $model->getTableSchema();
    $command = $builder->createInsertCommand($table, $model->getAttributes());
    $command->_connection->enableParamLogging = true;
    $command->execute();
} catch (Exception $e) {
    // getText() will print the query with the binding params
    // getAttributes() will give you the attributes injected
    var_dump($command->getText());               
    var_dump($model->getAttributes());
    die();
}

The result will look like:

"INSERT INTO `fruit` (`order`, `name`, `season`) VALUES (:yp0, :yp1,:yp2)"

array(2) {
  ["order"] =>  int(1),
  ["name"] =>  null,
  ["season"] =>  null
}

Upvotes: 1

arogachev
arogachev

Reputation: 33548

$model->save()->rawSql call can not return null, it must throw an exception that you are trying to access property of non-object. $model->save() returns boolean value - either query executed successfully or not.

If $model->getErrors() returns empty array and query was not executed at all I'm pretty sure that something is wrong with model event handlers, especially beforeSave(), check it, it should not return false. Also check attached behaviors event handlers.

As for getting query. It's useless if it simply was not executed, but if it was, here are some ways to achieve it:

1) Probably the best way. Use debug panel. I also mentioned it here.

2) Look at logs as @robsch adviced.

You can't directly get raw SQL in code with $model->save(), It will call either insert() or update(). If you are interested, here is the part of code for insertInternal():

$values = $this->getDirtyAttributes($attributes);
if (empty($values)) {
    foreach ($this->getPrimaryKey(true) as $key => $value) {
        $values[$key] = $value;
    }
}
$db = static::getDb();
$command = $db->createCommand()->insert($this->tableName(), $values);
if (!$command->execute()) {
    return false;
}

If you call $command->rawSql you will get raw sql but you can't do that outside because the command is formed internally.

P.S. This piece of code:

if ($model->validate()) {
    $model->save();
}

doesn't make sense because $model->save() will call $model->validate() internally.

Upvotes: 5

Related Questions