I have two connections, d
and c
. Basically, whatever changes I do on certain models of d
, it needs to be replicated at c
as well. This is the code doing it:
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;
}
The commented line would be responsible for syncing the primary keys, but of course this is not working, because _repository
represents a table
, yet, I need to apply row-level changes. How could I ensure that all new records created by this query will be synced?
This code is located in the App\ORM\Query
namespace, which extends
Cake\ORM\Query
.
I have managed to resolve the issue with the code that follows (the logic is explained in the comments):
/**
* 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();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.