如何在复制执行时同步不同的主键值?
How can I sync differing primary key values on replicating execute?
我有两个连接,d
和 c
。基本上,无论我在 d
的某些模型上做了什么更改,它也需要在 c
上复制。这是执行此操作的代码:
public function execute()
{
if ($this->isReplicate()) {
$primaryKey = $this->_repository->getPrimaryKey();
$replica = clone $this;
$replica->setConnection(ConnectionManager::get('c'));
$replica->execute();
//$this->_repository->{$primaryKey} = $replica->getRepository()->{$primaryKey};
}
$result = parent::execute();
return $result;
}
注释行将负责同步主键,但这当然行不通,因为 _repository
表示 table
,但是,我需要应用行级更改。我如何确保同步此查询创建的所有新记录?
此代码位于 App\ORM\Query
命名空间中,extends
Cake\ORM\Query
.
我已经设法用下面的代码解决了这个问题(逻辑在评论中解释):
/**
* Overrides a method with the same name to handle synchronizations with c
*/
public function execute()
{
//Some tables need replication. If this is such a table, then we need to perform some extra steps. Otherwise we would just call the parent
//Method
if ($this->isReplicate()) {
//Getting the table
$table = $this->_repository->getTable();
//Replicating the query
$replica = clone $this;
//Setting the connection of the replica to c, because we need to apply the district changes to central
$replica->setConnection(ConnectionManager::get('c'));
//We execute the replica first, because we will need to refer c IDs and not the other way around
$replica->execute();
//If this is an insert, then we need to handle the ids as well
if (!empty($this->clause('insert'))) {
//We load the primary key's name to use it later to find the maximum value
$primaryKey = $this->_repository->getPrimaryKey();
//We get the highest ID value, which will always be a positive number, because we have already executed the query at the replica
$maxID = $this->getConnection()
->execute("SELECT {$primaryKey} FROM {$table} ORDER BY {$primaryKey} DESC LIMIT 0, 1")
->fetchAll('assoc')[0][$primaryKey];
//We get the columns
$columns = $this->clause('values')->getColumns();
//In order to add the primary key
$columns[] = $primaryKey;
//And then override the insert clause with this adjusted array
$this->insert($columns);
//We get the values
$values = $this->clause('values')->getValues();
//And their count
$count = count($values);
//There could be multiple rows inserted already into the replica as part of this query, we need to replicate all their IDs, without
//assuming that there is a single inserted record
for ($index = 0; $index < $count; $index++) {
$values[$index][$primaryKey] = $maxID - $count + $index + 1;
}
//We override the values clause with this adjusted array, which contains PK values as well
$this->clause('values')->values($values);
}
//We nevertheless execute the query in any case, independently of whether it was a replicate table
//If it was a replicate table, then we have already made adjustments to the query in the if block
return parent::execute();
}
}
我有两个连接,d
和 c
。基本上,无论我在 d
的某些模型上做了什么更改,它也需要在 c
上复制。这是执行此操作的代码:
public function execute()
{
if ($this->isReplicate()) {
$primaryKey = $this->_repository->getPrimaryKey();
$replica = clone $this;
$replica->setConnection(ConnectionManager::get('c'));
$replica->execute();
//$this->_repository->{$primaryKey} = $replica->getRepository()->{$primaryKey};
}
$result = parent::execute();
return $result;
}
注释行将负责同步主键,但这当然行不通,因为 _repository
表示 table
,但是,我需要应用行级更改。我如何确保同步此查询创建的所有新记录?
此代码位于 App\ORM\Query
命名空间中,extends
Cake\ORM\Query
.
我已经设法用下面的代码解决了这个问题(逻辑在评论中解释):
/**
* Overrides a method with the same name to handle synchronizations with c
*/
public function execute()
{
//Some tables need replication. If this is such a table, then we need to perform some extra steps. Otherwise we would just call the parent
//Method
if ($this->isReplicate()) {
//Getting the table
$table = $this->_repository->getTable();
//Replicating the query
$replica = clone $this;
//Setting the connection of the replica to c, because we need to apply the district changes to central
$replica->setConnection(ConnectionManager::get('c'));
//We execute the replica first, because we will need to refer c IDs and not the other way around
$replica->execute();
//If this is an insert, then we need to handle the ids as well
if (!empty($this->clause('insert'))) {
//We load the primary key's name to use it later to find the maximum value
$primaryKey = $this->_repository->getPrimaryKey();
//We get the highest ID value, which will always be a positive number, because we have already executed the query at the replica
$maxID = $this->getConnection()
->execute("SELECT {$primaryKey} FROM {$table} ORDER BY {$primaryKey} DESC LIMIT 0, 1")
->fetchAll('assoc')[0][$primaryKey];
//We get the columns
$columns = $this->clause('values')->getColumns();
//In order to add the primary key
$columns[] = $primaryKey;
//And then override the insert clause with this adjusted array
$this->insert($columns);
//We get the values
$values = $this->clause('values')->getValues();
//And their count
$count = count($values);
//There could be multiple rows inserted already into the replica as part of this query, we need to replicate all their IDs, without
//assuming that there is a single inserted record
for ($index = 0; $index < $count; $index++) {
$values[$index][$primaryKey] = $maxID - $count + $index + 1;
}
//We override the values clause with this adjusted array, which contains PK values as well
$this->clause('values')->values($values);
}
//We nevertheless execute the query in any case, independently of whether it was a replicate table
//If it was a replicate table, then we have already made adjustments to the query in the if block
return parent::execute();
}
}