Как мне запускать транзакции в CakePHP3, получая идентификатор последней вставки и работать как для PostgreSQL, так и для MySQL?


person Kim Stacks    schedule 05.02.2015    source источник
comment
Это идеальный пример для сделки.   -  person Frank Heikens    schedule 05.02.2015
comment
Хорошо, тогда как мне получить последний идентификатор вставки для первого запроса, чтобы я мог запустить его во втором запросе для выполнения транзакции?   -  person Kim Stacks    schedule 05.02.2015


Ответы (2)


После выполнения запроса на вставку вы можете вызвать lastInsertId() с правильными аргументами, чтобы получить правильное значение:

$connection->transactional(function ($connection) {
    $statement = $connection->newQuery
        ->insert($fields)
        ->into($table)
        ->values($values)
        ->execute();

     $insertId = $statement->lastInsertId($table, 'id'); // id is primary key
});
person José Lorenzo Rodríguez    schedule 05.02.2015
comment
Я полагаю, мне нужно сделать это так: function ($connection) use ($fields, $table, $values)?? - person Kim Stacks; 06.02.2015
comment
Да, вы передаете аргументы, которые вам нужно передать :) - person José Lorenzo Rodríguez; 06.02.2015
comment
Не могли бы вы предложить мне использовать транзакцию для этого сценария? или вы бы предложили использовать afterSave или использовать оператор if, чтобы проверить, успешна ли первая вставка? Потому что я не могу найти saveAssociated в документах Cake3. поэтому я не уверен, как это сделать вместо этого. - person Kim Stacks; 06.02.2015
comment
save() в CakePHP 3 также сохраняет ассоциации. Кроме того, save всегда выполняется внутри транзакции. - person José Lorenzo Rodríguez; 06.02.2015
comment
Я понимаю. Спасибо. Я понял, что не могу использовать ассоциации, так как вторая вставка требует странных правых внешних соединений. Могу ли я по-прежнему использовать Cake3 ORM для написания правильного внешнего соединения, или я должен просто использовать необработанный запрос? мое правое внешнее соединение выглядит так INSERT INTO users_access_dynamic_views (dynamic_view_id, user_id, ordinal_ranking) SELECT ?, u.user_id, COUNT(uav.id) + 1 from users_access_dynamic_views uav RIGHT JOIN users_in_circles u ON uav.user_id = u.user_id WHERE u.circle_id = ? GROUP BY u.user_id - person Kim Stacks; 08.02.2015

Функция для получения последнего вставленного идентификатора в MySQL называется last_insert_id(), тогда как в PostgreSQL это lastval (). Поэтому либо вам нужно создать какое-то сопоставление между ними, либо вам нужно проверить, какой драйвер вы используете в CakePHP, а затем вызвать конкретную функцию.

Например, вы можете создать следующую функцию в PostgreSQL.

CREATE FUNCTION last_insert_id() RETURNS BIGINT AS $$
  SELECT lastval();
$$ LANGUAGE sql VOLATILE;

Затем вы можете вызвать его во втором запросе, и он будет работать как в MySQL, так и в PostgreSQL.

INSERT INTO users_access_dynamic_views
  (user_id, view_id)
VALUES
  (44, LAST_INSERT_ID());

Имейте в виду также, что PostgreSQL использует последовательности для генерации идентификаторов, поэтому простое использование lastval может привести к неожиданным результатам, когда задействованы триггеры (вставка данных куда-то сама по себе). Таким образом, всегда лучше указывать задействованную последовательность явно через currval.

CURRVAL(PG_GET_SERIAL_SEQUENCE('dynamic_views', 'view_id'))
person Kouber Saparev    schedule 05.02.2015