Search code examples
yiisql-updatedatabase-migrationyii-migrations

CDbMigration::update does not work inside foreach loop


Following this question. There is something wrong, when using CDbMigration::update() inside foreach loop.

This code does not work correctly:

//This is executed inside Yii migration, so $this is CDbMigration.

foreach($idMap as $menuId=>$pageId)
{
    $this->update
    (
        'menus_items',
        array('link'=>'/content/show?id='.$pageId),
        array('id = '.$menuId)
    );
}

For each item in $idMap value of $pageId is always the same and equals value of last item in $idMap array. Therefore, every menu item points to the same URL.

This code works like a charm:

foreach($idMap as $menuId=>$pageId)
{
    $sql = "UPDATE `menus_items` SET link = '/content/show?id=".$pageId."' WHERE id = ".$menuId."; ";

    Yii::app()->db->createCommand($sql)->execute();
}

For each item in $idMap value of $pageId is always different and equals value of current item in $idMap array. Therefore, every menu item points to correct URL.

The same goes, when executing all statements in one SQL query:

$sql = '';

foreach($idMap as $menuId=>$pageId)
{
    $sql .= "UPDATE `menus_items` SET link = '/content/show?id=".$pageId."' WHERE id = ".$menuId."; ";
}

Yii::app()->db->createCommand($sql)->execute();

Again, everything is OK.

Why using CDbMigration::update() fails, while direct SQL execution works like a charm?


Solution

  • I don't think you are providing the criteria parameter properly @ array('id = '.$menuId) . You should use a string if you want to send it like that, putting it in an array presumes you are mapping out the conditions in a key => value pair. Also you should be wrapping the value constraint in quotes id = "$menuId".