[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/infrastructure/storage/lisk/ -> LiskDAO.php (summary)

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

Defines 70 functions

  __construct()
  getEstablishedConnection()
  setEstablishedConnection()
  getConfiguration()
  getConfigOption()
  load()
  loadAll()
  loadAllWhere()
  loadOneWhere()
  loadRawDataWhere()
  reload()
  loadFromArray()
  loadAllFromArray()
  loadRelatives()
  loadOneRelative()
  putInSet()
  getInSet()
  setID()
  getID()
  getPHID()
  hasProperty()
  getAllLiskProperties()
  checkProperty()
  establishConnection()
  getAllLiskPropertyValues()
  makeEphemeral()
  isEphemeralCheck()
  save()
  replace()
  insert()
  update()
  delete()
  insertRecordIntoDatabase()
  shouldInsertWhenSaved()
  getTableName()
  getIDKey()
  getIDKeyForUse()
  generatePHID()
  willWriteData()
  didWriteData()
  willSaveObject()
  willReadData()
  didReadData()
  willDelete()
  didDelete()
  readField()
  writeField()
  openTransaction()
  saveTransaction()
  killTransaction()
  beginReadLocking()
  endReadLocking()
  beginWriteLocking()
  endWriteLocking()
  beginIsolateAllLiskEffectsToCurrentProcess()
  endIsolateAllLiskEffectsToCurrentProcess()
  shouldIsolateAllLiskEffectsToCurrentProcess()
  establishIsolatedConnection()
  beginIsolateAllLiskEffectsToTransactions()
  endIsolateAllLiskEffectsToTransactions()
  shouldIsolateAllLiskEffectsToTransactions()
  closeAllConnections()
  applyLiskDataSerialization()
  __call()
  call()
  __set()
  loadNextCounterID()
  getBinaryColumns()
  getSchemaColumns()
  getSchemaKeys()

Functions
Functions that are not part of a class:

__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