[ Index ] |
PHP Cross Reference of Phabricator |
[Source view] [Print] [Project Stats]
Simple object-authoritative data access object that makes it easy to build stuff that you need to save to a database. Basically, it means that the amount of boilerplate code (and, particularly, boilerplate SQL) you need to write is greatly reduced. Lisk makes it fairly easy to build something quickly and end up with reasonably high-quality code when you're done (e.g., getters and setters, objects, transactions, reasonably structured OO code). It's also very thin: you can break past it and use MySQL and other lower-level tools when you need to in those couple of cases where it doesn't handle your workflow gracefully.
File Size: | 1840 lines (54 kb) |
Included or required: | 0 times |
Referenced: | 0 times |
Includes or requires: | 0 files |
__construct() X-Ref |
Build an empty object. return: obj Empty object. |
getEstablishedConnection($mode) X-Ref |
Get an existing, cached connection for this object. param: mode Connection mode. return: AprontDatabaseConnection|null Connection, if it exists in cache. |
setEstablishedConnection($mode,AphrontDatabaseConnection $connection,$force_unique = false) X-Ref |
Store a connection in the connection cache. param: mode Connection mode. param: AphrontDatabaseConnection Connection to cache. return: this |
getConfiguration() X-Ref |
Change Lisk behaviors, like ID configuration and timestamps. If you want to change these behaviors, you should override this method in your child class and change the options you're interested in. For example: public function getConfiguration() { return array( Lisk_DataAccessObject::CONFIG_EXAMPLE => true, ) + parent::getConfiguration(); } The available options are: CONFIG_IDS Lisk objects need to have a unique identifying ID. The three mechanisms available for generating this ID are IDS_AUTOINCREMENT (default, assumes the ID column is an autoincrement primary key), IDS_MANUAL (you are taking full responsibility for ID management), or IDS_COUNTER (see below). InnoDB does not persist the value of `auto_increment` across restarts, and instead initializes it to `MAX(id) + 1` during startup. This means it may reissue the same autoincrement ID more than once, if the row is deleted and then the database is restarted. To avoid this, you can set an object to use a counter table with IDS_COUNTER. This will generally behave like IDS_AUTOINCREMENT, except that the counter value will persist across restarts and inserts will be slightly slower. If a database stores any DAOs which use this mechanism, you must create a table there with this schema: CREATE TABLE lisk_counter ( counterName VARCHAR(64) COLLATE utf8_bin PRIMARY KEY, counterValue BIGINT UNSIGNED NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CONFIG_TIMESTAMPS Lisk can automatically handle keeping track of a `dateCreated' and `dateModified' column, which it will update when it creates or modifies an object. If you don't want to do this, you may disable this option. By default, this option is ON. CONFIG_AUX_PHID This option can be enabled by being set to some truthy value. The meaning of this value is defined by your PHID generation mechanism. If this option is enabled, a `phid' property will be populated with a unique PHID when an object is created (or if it is saved and does not currently have one). You need to override generatePHID() and hook it into your PHID generation mechanism for this to work. By default, this option is OFF. CONFIG_SERIALIZATION You can optionally provide a column serialization map that will be applied to values when they are written to the database. For example: self::CONFIG_SERIALIZATION => array( 'complex' => self::SERIALIZATION_JSON, ) This will cause Lisk to JSON-serialize the 'complex' field before it is written, and unserialize it when it is read. CONFIG_BINARY You can optionally provide a map of columns to a flag indicating that they store binary data. These columns will not raise an error when handling binary writes. CONFIG_COLUMN_SCHEMA Provide a map of columns to schema column types. CONFIG_KEY_SCHEMA Provide a map of key names to key specifications. CONFIG_NO_TABLE Allows you to specify that this object does not actually have a table in the database. return: dictionary Map of configuration options to values. |
getConfigOption($option_name) X-Ref |
Determine the setting of a configuration option for this class of objects. param: const Option name, one of the CONFIG_* constants. return: mixed Option value, if configured (null if unavailable). |
load($id) X-Ref |
Load an object by ID. You need to invoke this as an instance method, not a class method, because PHP doesn't have late static binding (until PHP 5.3.0). For example: $dog = id(new Dog())->load($dog_id); param: int Numeric ID identifying the object to load. return: obj|null Identified object, or null if it does not exist. |
loadAll() X-Ref |
Loads all of the objects, unconditionally. return: dict Dictionary of all persisted objects of this type, keyed |
loadAllWhere($pattern ) X-Ref |
Load all objects which match a WHERE clause. You provide everything after the 'WHERE'; Lisk handles everything up to it. For example: $old_dogs = id(new Dog())->loadAllWhere('age > %d', 7); The pattern and arguments are as per queryfx(). param: string queryfx()-style SQL WHERE clause. param: ... Zero or more conversions. return: dict Dictionary of matching objects, keyed on ID. |
loadOneWhere($pattern ) X-Ref |
Load a single object identified by a 'WHERE' clause. You provide everything after the 'WHERE', and Lisk builds the first half of the query. See loadAllWhere(). This method is similar, but returns a single result instead of a list. param: string queryfx()-style SQL WHERE clause. param: ... Zero or more conversions. return: obj|null Matching object, or null if no object matches. |
loadRawDataWhere($pattern ) X-Ref |
No description |
reload() X-Ref |
Reload an object from the database, discarding any changes to persistent properties. This is primarily useful after entering a transaction but before applying changes to an object. return: this |
loadFromArray(array $row) X-Ref |
Initialize this object's properties from a dictionary. Generally, you load single objects with loadOneWhere(), but sometimes it may be more convenient to pull data from elsewhere directly (e.g., a complicated join via @{method:queryData}) and then load from an array representation. param: dict Dictionary of properties, which should be equivalent to return: this |
loadAllFromArray(array $rows) X-Ref |
Initialize a list of objects from a list of dictionaries. Usually you load lists of objects with @{method:loadAllWhere}, but sometimes that isn't flexible enough. One case is if you need to do joins to select the right objects: function loadAllWithOwner($owner) { $data = $this->queryData( 'SELECT d.* FROM owner o JOIN owner_has_dog od ON o.id = od.ownerID JOIN dog d ON od.dogID = d.id WHERE o.id = %d', $owner); return $this->loadAllFromArray($data); } This is a lot messier than @{method:loadAllWhere}, but more flexible. param: list List of property dictionaries. return: dict List of constructed objects, keyed on ID. |
loadRelatives(LiskDAO $object,$foreign_column,$key_method = 'getID',$where = '') X-Ref |
This method helps to prevent the 1+N queries problem. It happens when you execute a query for each row in a result set. Like in this code: COUNTEREXAMPLE, name=Easy to write but expensive to execute $diffs = id(new DifferentialDiff())->loadAllWhere( 'revisionID = %d', $revision->getID()); foreach ($diffs as $diff) { $changesets = id(new DifferentialChangeset())->loadAllWhere( 'diffID = %d', $diff->getID()); // Do something with $changesets. } One can solve this problem by reading all the dependent objects at once and assigning them later: COUNTEREXAMPLE, name=Cheaper to execute but harder to write and maintain $diffs = id(new DifferentialDiff())->loadAllWhere( 'revisionID = %d', $revision->getID()); $all_changesets = id(new DifferentialChangeset())->loadAllWhere( 'diffID IN (%Ld)', mpull($diffs, 'getID')); $all_changesets = mgroup($all_changesets, 'getDiffID'); foreach ($diffs as $diff) { $changesets = idx($all_changesets, $diff->getID(), array()); // Do something with $changesets. } The method @{method:loadRelatives} abstracts this approach which allows writing a code which is simple and efficient at the same time: name=Easy to write and cheap to execute $diffs = $revision->loadRelatives(new DifferentialDiff(), 'revisionID'); foreach ($diffs as $diff) { $changesets = $diff->loadRelatives( new DifferentialChangeset(), 'diffID'); // Do something with $changesets. } This will load dependent objects for all diffs in the first call of @{method:loadRelatives} and use this result for all following calls. The method supports working with set of sets, like in this code: $diffs = $revision->loadRelatives(new DifferentialDiff(), 'revisionID'); foreach ($diffs as $diff) { $changesets = $diff->loadRelatives( new DifferentialChangeset(), 'diffID'); foreach ($changesets as $changeset) { $hunks = $changeset->loadRelatives( new DifferentialHunk(), 'changesetID'); // Do something with hunks. } } This code will execute just three queries - one to load all diffs, one to load all their related changesets and one to load all their related hunks. You can try to write an equivalent code without using this method as a homework. The method also supports retrieving referenced objects, for example authors of all diffs (using shortcut @{method:loadOneRelative}): foreach ($diffs as $diff) { $author = $diff->loadOneRelative( new PhabricatorUser(), 'phid', 'getAuthorPHID'); // Do something with author. } It is also possible to specify additional conditions for the `WHERE` clause. Similarly to @{method:loadAllWhere}, you can specify everything after `WHERE` (except `LIMIT`). Contrary to @{method:loadAllWhere}, it is allowed to pass only a constant string (`%` doesn't have a special meaning). This is intentional to avoid mistakes with using data from one row in retrieving other rows. Example of a correct usage: $status = $author->loadOneRelative( new PhabricatorCalendarEvent(), 'userPHID', 'getPHID', '(UNIX_TIMESTAMP() BETWEEN dateFrom AND dateTo)'); param: LiskDAO Type of objects to load. param: string Name of the column in target table. param: string Method name in this table. param: string Additional constraints on returned rows. It supports no return: list Objects of type $object. |
loadOneRelative(LiskDAO $object,$foreign_column,$key_method = 'getID',$where = '') X-Ref |
Load referenced row. See @{method:loadRelatives} for details. param: LiskDAO Type of objects to load. param: string Name of the column in target table. param: string Method name in this table. param: string Additional constraints on returned rows. It supports no return: LiskDAO Object of type $object or null if there's no such object. |
putInSet(LiskDAOSet $set) X-Ref |
No description |
getInSet() X-Ref |
No description |
setID($id) X-Ref |
Set unique ID identifying this object. You normally don't need to call this method unless with `IDS_MANUAL`. param: mixed Unique ID. return: this |
getID() X-Ref |
Retrieve the unique ID identifying this object. This value will be null if the object hasn't been persisted and you didn't set it manually. return: mixed Unique ID. |
getPHID() X-Ref |
No description |
hasProperty($property) X-Ref |
Test if a property exists. param: string Property name. return: bool True if the property exists. |
getAllLiskProperties() X-Ref |
Retrieve a list of all object properties. This list only includes properties that are declared as protected, and it is expected that all properties returned by this function should be persisted to the database. Properties that should not be persisted must be declared as private. return: dict Dictionary of normalized (lowercase) to canonical (original |
checkProperty($property) X-Ref |
Check if a property exists on this object. return: string|null Canonical property name, or null if the property |
establishConnection($mode, $force_new = false) X-Ref |
Get or build the database connection for this object. param: string 'r' for read, 'w' for read/write. param: bool True to force a new connection. The connection will not return: LiskDatabaseConnection Lisk connection object. |
getAllLiskPropertyValues() X-Ref |
Convert this object into a property dictionary. This dictionary can be restored into an object by using @{method:loadFromArray} (unless you're using legacy features with CONFIG_CONVERT_CAMELCASE, but in that case you should just go ahead and die in a fire). return: dict Dictionary of object properties. |
makeEphemeral() X-Ref |
Make an object read-only. Making an object ephemeral indicates that you will be changing state in such a way that you would never ever want it to be written back to the storage. |
isEphemeralCheck() X-Ref |
No description |
save() X-Ref |
Persist this object to the database. In most cases, this is the only method you need to call to do writes. If the object has not yet been inserted this will do an insert; if it has, it will do an update. return: this |
replace() X-Ref |
Save this object, forcing the query to use REPLACE regardless of object state. return: this |
insert() X-Ref |
Save this object, forcing the query to use INSERT regardless of object state. return: this |
update() X-Ref |
Save this object, forcing the query to use UPDATE regardless of object state. return: this |
delete() X-Ref |
Delete this object, permanently. return: this |
insertRecordIntoDatabase($mode) X-Ref |
Internal implementation of INSERT and REPLACE. param: const Either "INSERT" or "REPLACE", to force the desired mode. |
shouldInsertWhenSaved() X-Ref |
Method used to determine whether to insert or update when saving. return: bool true if the record should be inserted |
getTableName() X-Ref |
Retrieve the database table name. By default, this is the class name. return: string Table name for object storage. |
getIDKey() X-Ref |
Retrieve the primary key column, "id" by default. If you can not reasonably name your ID column "id", override this method. return: string Name of the ID column. |
getIDKeyForUse() X-Ref |
No description |
generatePHID() X-Ref |
Generate a new PHID, used by CONFIG_AUX_PHID. return: phid Unique, newly allocated PHID. |
willWriteData(array &$data) X-Ref |
Hook to apply serialization or validation to data before it is written to the database. See also @{method:willReadData}. |
didWriteData() X-Ref |
Hook to perform actions after data has been written to the database. |
willSaveObject() X-Ref |
Hook to make internal object state changes prior to INSERT, REPLACE or UPDATE. |
willReadData(array &$data) X-Ref |
Hook to apply serialization or validation to data as it is read from the database. See also @{method:willWriteData}. |
didReadData() X-Ref |
Hook to perform an action on data after it is read from the database. |
willDelete() X-Ref |
Hook to perform an action before the deletion of an object. |
didDelete() X-Ref |
Hook to perform an action after the deletion of an object. |
readField($field) X-Ref |
Reads the value from a field. Override this method for custom behavior of @{method:getField} instead of overriding getField directly. param: string Canonical field name return: mixed Value of the field |
writeField($field, $value) X-Ref |
Writes a value to a field. Override this method for custom behavior of setField($value) instead of overriding setField directly. param: string Canonical field name param: mixed Value to write |
openTransaction() X-Ref |
Increase transaction stack depth. return: this |
saveTransaction() X-Ref |
Decrease transaction stack depth, saving work. return: this |
killTransaction() X-Ref |
Decrease transaction stack depth, discarding work. return: this |
beginReadLocking() X-Ref |
Begins read-locking selected rows with SELECT ... FOR UPDATE, so that other connections can not read them (this is an enormous oversimplification of FOR UPDATE semantics; consult the MySQL documentation for details). To end read locking, call @{method:endReadLocking}. For example: $beach->openTransaction(); $beach->beginReadLocking(); $beach->reload(); $beach->setGrainsOfSand($beach->getGrainsOfSand() + 1); $beach->save(); $beach->endReadLocking(); $beach->saveTransaction(); return: this |
endReadLocking() X-Ref |
Ends read-locking that began at an earlier @{method:beginReadLocking} call. return: this |
beginWriteLocking() X-Ref |
Begins write-locking selected rows with SELECT ... LOCK IN SHARE MODE, so that other connections can not update or delete them (this is an oversimplification of LOCK IN SHARE MODE semantics; consult the MySQL documentation for details). To end write locking, call @{method:endWriteLocking}. return: this |
endWriteLocking() X-Ref |
Ends write-locking that began at an earlier @{method:beginWriteLocking} call. return: this |
beginIsolateAllLiskEffectsToCurrentProcess() X-Ref |
endIsolateAllLiskEffectsToCurrentProcess() X-Ref |
shouldIsolateAllLiskEffectsToCurrentProcess() X-Ref |
establishIsolatedConnection($mode) X-Ref |
beginIsolateAllLiskEffectsToTransactions() X-Ref |
endIsolateAllLiskEffectsToTransactions() X-Ref |
shouldIsolateAllLiskEffectsToTransactions() X-Ref |
closeAllConnections() X-Ref |
No description |
applyLiskDataSerialization(array &$data, $deserialize) X-Ref |
Applies configured serialization to a dictionary of values. |
__call($method, $args) X-Ref |
Black magic. Builds implied get*() and set*() for all properties. param: string Method name. param: list Argument vector. return: mixed get*() methods return the property value. set*() methods |
call($method, $args) X-Ref |
__set($name, $value) X-Ref |
Warns against writing to undeclared property. |
loadNextCounterID(AphrontDatabaseConnection $conn_w,$counter_name) X-Ref |
Increments a named counter and returns the next value. param: AphrontDatabaseConnection Database where the counter resides. param: string Counter name to create or increment. return: int Next counter value. |
getBinaryColumns() X-Ref |
No description |
getSchemaColumns() X-Ref |
No description |
getSchemaKeys() X-Ref |
No description |
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |