We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

How do I retrieve uncommitted data with isolated transaction?

Consider this, it is returning bool(false):

  // Database Tx
 $tx = (new TxManager())->get();

 $currency = new Currencies();
 $currency->setTransaction($tx);
 $currency->code = "AAA";
 $currency->symbol = "SYMB";
 $currency->name = "NAME";
 $currency->is_default = 1;
 $currency->create();

 $result = Currencies::findFirst([
     'conditions' => 'name= ?0',
     'bind' => ["NAME"],
     'for_update' => true
 ]);
 var_dump($result);

How can I retrieve the uncomitted data with find / findFirst() under the circumstances where reference to $currency is not available anymore.



85.5k

i may be wrong but this doesnt make sence ? Find/FindFirst will query the database, if you your model "create" has failed and there is no record in the database i dont see how find can fetch it.


if ($currency->create() === false){

$_SESSION['uncomited_obj'] = $currency;

}

this is something stupid, but just trying to show an idea.

Sorry if I didnt understand you

edited Oct '15

Here is the actual case, there's two models

  • Accounts (id, balance)
  • TransactionEntries (id, account_id, amount)

Everytime an transaction entry is updated, account balance will change accordingly to reflect the correct balance, there's a case where I will need to delete some transaction entries and create some transaction entries within one database transaction:

  // Database Tx
  $tx = (new TxManager())->get();

  // Transaction entry to delete
  $delTransaction = TransactionEntries::findFirst(1);
  $delTransaction->setTransaction($tx);
  $delTransaction->account->balance -= $delTransaction->amount; // Amount = 30, Balance = 30
  // Balance = 0 now, but not committed to database
  if ($delTransaction->delete() == false) {
      //THROW EXCEPTION
  }

  // New transaction
  $newTransaction = new TransactionEntries();
  $newTransaction->setTransaction($tx);
  $newTransaction->account_id = 1; // Same account as previous transaction entry.
  $newTransaction->amount = 50;
  if ($newTransaction->create() == false) {
  // THROW
  }

  // Update account
  $account = Accounts::findFirst(1);
  $account->balance += 50; // PROBLEM HERE: account balance is the original 30, not the latest which is 0.
  // Account balance = 80 which is wrong, should be 50
  if ($account->update() == false) {
  // THROW
  }

  $tx->commit();

I cant think of any easy way to overcome this hurdle.



85.5k

i think i would use workers to acomplish something like that. But i am not an expert.

But anyways the idea:

For every transaction create a job, with accound ID and amount (+/-), inside the workey, you can just update the value in the database accordingly.

And inside the page you can tell the information is refreshed every 1 sec/minutes or whatever. It's tricky but it is what banks are doing i think.

https://github.com/chrisboulton/php-resque

the other way is to pass the balance variable all over the place until you reach the "commit to the databases"


$current_amount = model:findFirst(1)->amount();

functions... bla bla bla

$current_amount = $amount - 30;

.... bla bla bla

update the model here