Skip to content

Commit

Permalink
phalcon#13226 Code-examples + cleanup
Browse files Browse the repository at this point in the history
- adds const to Model to avoid typos
- add code examples
  • Loading branch information
chilimatic committed Dec 18, 2017
1 parent 2afde4a commit d71be21
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 46 deletions.
119 changes: 73 additions & 46 deletions phalcon/mvc/model.zep
Expand Up @@ -85,7 +85,6 @@ use Phalcon\Events\ManagerInterface as EventsManagerInterface;
*/
abstract class Model implements EntityInterface, ModelInterface, ResultInterface, InjectionAwareInterface, \Serializable, \JsonSerializable
{

protected _dependencyInjector;

protected _modelsManager;
Expand Down Expand Up @@ -117,6 +116,8 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface

protected _oldSnapshot = [];

const TRANSACTION_INDEX = "transaction";

const OP_NONE = 0;

const OP_CREATE = 1;
Expand Down Expand Up @@ -815,49 +816,59 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface
* }
*
* // encapsulate find it into an running transaction esp. useful for application unit-tests
* // or complex business logic where we wanna control which transactions are used.
*
* $myTransaction = new Transaction(\Phalcon\Di::getDefault());
* $myTransaction->begin();
* $newRobot = new Robot();
* $newRobot->setTransaction($myTransaction);
* $newRobot->save(['name' => 'test', 'type' => 'mechanical', 'year' => 1944]);
*
* $resultInsideTransaction = Robot::find(['name' => 'test', 'transaction' => $myTransaction]);
* $resultOutsideTransaction = Robot::find(['name' => 'test']);
*
* foreach ($setInsideTransaction as $robot) {
* echo $robot->name, "\n";
* }
*
* foreach ($setOutsideTransaction as $robot) {
* echo $robot->name, "\n";
* }
*
* // reverts all not commited changes
* $myTransaction->rollback();
*
* // creating two different transactions
* $myTransaction1 = new Transaction(\Phalcon\Di::getDefault());
* $myTransaction1->begin();
* $myTransaction2 = new Transaction(\Phalcon\Di::getDefault());
* $myTransaction2->begin();
*
* // add a new robot
* $newRobot = new Robot();
* $newRobot->setTransaction($myTransaction1);
* $newRobot->save(['name' => 'test', 'type' => 'mechanical', 'year' => 1944]);
*
* // this transaction will not find the robot.
* $resultOutsideExplicitTransaction = Robot::find(['name' => 'test', 'transaction' => $myTransaction2]);
* // this transaction will find the robot
* $resultInsideExplicitTransaction = Robot::find(['name' => 'test', 'transaction' => $myTransaction1]);
*
* // is using the transaction1 and will find the robot
* $resultInsideImplicitTransaction = $robot::find(['name' => 'test']);
* $transaction1->rollback();
* $transaction2->rollback();
*
* // or complex business logic where we wanna control which transactions are used.
*
* $myTransaction = new Transaction(\Phalcon\Di::getDefault());
* $myTransaction->begin();
* $newRobot = new Robot();
* $newRobot->setTransaction($myTransaction);
* $newRobot->save(['name' => 'test', 'type' => 'mechanical', 'year' => 1944]);
*
* $resultInsideTransaction = Robot::find(['name' => 'test', Model::TRANSACTION_INDEX => $myTransaction]);
* $resultOutsideTransaction = Robot::find(['name' => 'test']);
*
* foreach ($setInsideTransaction as $robot) {
* echo $robot->name, "\n";
* }
*
* foreach ($setOutsideTransaction as $robot) {
* echo $robot->name, "\n";
* }
*
* // reverts all not commited changes
* $myTransaction->rollback();
*
* // creating two different transactions
* $myTransaction1 = new Transaction(\Phalcon\Di::getDefault());
* $myTransaction1->begin();
* $myTransaction2 = new Transaction(\Phalcon\Di::getDefault());
* $myTransaction2->begin();
*
* // add a new robots
* $firstNewRobot = new Robot();
* $firstNewRobot->setTransaction($myTransaction1);
* $firstNewRobot->save(['name' => 'first-transaction-robot', 'type' => 'mechanical', 'year' => 1944]);
*
* $secondNewRobot = new Robot();
* $secondNewRobot->setTransaction($myTransaction2);
* $secondNewRobot->save(['name' => 'second-transaction-robot', 'type' => 'fictional', 'year' => 1984]);
*
* // this transaction will find the robot.
* $resultInFirstTransaction = Robot::find(['name' => 'first-transaction-robot', Model::TRANSACTION_INDEX => $myTransaction1]);
* // this transaction won't find the robot.
* $resultInSecondTransaction = Robot::find(['name' => 'first-transaction-robot', Model::TRANSACTION_INDEX => $myTransaction2]);
* // this transaction won't find the robot.
* $resultOutsideAnyExplicitTransaction = Robot::find(['name' => 'first-transaction-robot']);
*
* // this transaction won't find the robot.
* $resultInFirstTransaction = Robot::find(['name' => 'second-transaction-robot', Model::TRANSACTION_INDEX => $myTransaction2]);
* // this transaction will find the robot.
* $resultInSecondTransaction = Robot::find(['name' => 'second-transaction-robot', Model::TRANSACTION_INDEX => $myTransaction1]);
* // this transaction won't find the robot.
* $resultOutsideAnyExplicitTransaction = Robot::find(['name' => 'second-transaction-robot']);
*
* $transaction1->rollback();
* $transaction2->rollback();
* </code>
*/
public static function find(var parameters = null) -> <ResultsetInterface>
Expand Down Expand Up @@ -901,7 +912,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface
}
}

if fetch transaction, params["transaction"] {
if fetch transaction, params[self::TRANSACTION_INDEX] {
if transaction instanceof TransactionInterface {
query->setTransaction(transaction);
}
Expand Down Expand Up @@ -956,6 +967,22 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface
* );
*
* echo "The first virtual robot name is ", $robot->name;
*
* // behaviour with transaction
* $myTransaction = new Transaction(\Phalcon\Di::getDefault());
* $myTransaction->begin();
* $newRobot = new Robot();
* $newRobot->setTransaction($myTransaction);
* $newRobot->save(['name' => 'test', 'type' => 'mechanical', 'year' => 1944]);
*
* $findsARobot = Robot::findFirst(['name' => 'test', Model::TRANSACTION_INDEX => $myTransaction]);
* $doesNotFindARobot = Robot::findFirst(['name' => 'test']);
*
* var_dump($findARobot);
* var_dump($doesNotFindARobot);
*
* $transaction->commit();
* $doesFindTheRobotNow = Robot::findFirst(['name' => 'test']);
* </code>
*
* @param string|array parameters
Expand Down Expand Up @@ -991,7 +1018,7 @@ abstract class Model implements EntityInterface, ModelInterface, ResultInterface

let query = builder->getQuery();

if fetch transaction, params["transaction"] {
if fetch transaction, params[self::TRANSACTION_INDEX] {
if transaction instanceof TransactionInterface {
query->setTransaction(transaction);
}
Expand Down
28 changes: 28 additions & 0 deletions phalcon/mvc/model/query.zep
Expand Up @@ -63,6 +63,34 @@ use Phalcon\Db\DialectInterface;
* echo "Price: ", $row->cars->price, "\n";
* echo "Taxes: ", $row->taxes, "\n";
* }
*
* // with transaction
* use Phalcon\Mvc\Model\Query;
* use Phalcon\Mvc\Model\Transaction;
*
* // $di needs to have the service "db" registered for this to work
* $di = Phalcon\Di\FactoryDefault::getDefault();
*
* $phql = 'SELECT * FROM robot';
*
* $myTransaction = new Transaction($di);
* $myTransaction->begin();
*
* $newRobot = new Robot();
* $newRobot->setTransaction($myTransaction);
* $newRobot->type = "mechanical";
* $newRobot->name = "Astro Boy";
* $newRobot->year = 1952;
* $newRobot->save();
*
* $queryWithTransaction = new Query($phql, $di);
* $queryWithTransaction->setTransaction($myTransaction);
*
* $resultWithEntries = $queryWithTransaction->execute();
*
* $queryWithOutTransaction = new Query($phql, $di);
* $resultWithOutEntries = $queryWithTransaction->execute()
*
*</code>
*/
class Query implements QueryInterface, InjectionAwareInterface
Expand Down

0 comments on commit d71be21

Please sign in to comment.