Database Queries

Manifesto currently works only with MySQL databases. There is a Connection class that handles the most rudimentary aspects of connecting to the database, and you should be able to use Manifesto for most activities without ever having to establishing a database connection manually.

The Oracle class (as in “ask the Oracle at Delphi”, not the database company) is the parent of all database-querying classes. The properties of the Oracle class correspond largely to the various components of a database query. The most significant properties are:

  • tablename
  • selectfields
  • where_clause
  • set_clause
  • orderby
  • groupby
  • limit_count
  • limit_start
  • object_class

So you can construct a query on any table as follows:

$oracle = new Oracle;
$oracle->set_tablename('mytable');
$oracle->set_selectfields('mytable.*');
$oracle->set_where_clause('objectid > 256');
$oracle->set_limit_count(10);
$oracle->set_orderby('lastname');
$oracle->get_record(); // see below for more information on this method

And this will construct a query that looks like

SELECT mytable.* FROM mytable WHERE objectid > 256 LIMIT 10 ORDER BY lastname;

That would be the long way. Most classes are built with their own Oracle class that extends the parent Oracle, so, for example, a “MediaOracle” might include a constructor method that sets reasonable defaults, e.g.

function MediaOracle() {
        $this->set_tablename('media');
        $this->set_selectfields('media.*');
        $this->set_orderby('created_datetime DESC');
}

So that you can use it more efficiently for your own queries, like

$oracle = new MediaOracle();
$oracle->set_where_clause("mime_type = 'image'")->get_record();

Building the query programmatically

One of the benefits to this long-hand way to build database queries is that it accommodates the modular nature of Manifesto. One module can be configured to programmatically modify the database queries generated by another module (when granted the proper permissions), so there must be a modular query-building structure that allows for that level of cooperation.

Generally speaking, you’ll always start with an Oracle object, traditionally named $oracle:

``Ex: $oracle = new Oracle();``

set_module

Sets the name of the module responsible for this query. Used largely for auditing and tracking purposes.

Ex: $oracle->set_module('accounts');

set_tablename

This method sets the primary database table to be queried. If a query will join multiple tables, this method should be used to set the first table, and add_tablename should be used for the rest. This method designates the initial table as the $master table as well, and that is used by some common join queries (e.g. hash_category joins) to know which table’s objectid to join on. This method is destructive in that subsequent calls will overwrite the initial fields.

Ex: $oracle->set_tablename('users');

add_tablename

This method adds a table to the initial query. It is generally used in conjunction with a modification to the SELECT clause and/or to the WHERE clause (otherwise, why are you joining the table?). This method is non-destructive and additive in that subsequent calls will append to the existing query.

Ex: $oracle->add_tablename('user_address');

set_selectfields

This method sets the initial SELECT part of the query (minus the word select), listing the fields you wish to retrieve from the query. Because Manifesto is modular, it is often possible for other modules to add tablenames and select fields to the initial query, so it is standard practice to include full table.fieldname references in the SELECT section to avoid name collisions. This method is destructive in that subsequent calls will overwrite the initial fields.

Ex: $oracle->set_selectfields('users.*,user_address.label');

add_selectfields

This method adds one or more fields to the SELECT portion of a query. It must be used in conjunction with add_tablename because you must be joining the table from which you are selecting the fields. This method is non-destructive and additive in that subsequent calls will append to the existing query.

Ex: $oracle->add_selectfields('user_address.city,user_address.state');

set_where_clause

This method establishes the conditions for the query in the WHERE clause. This method is always additive in that calls will always append to the existing query. The most basic example is to pass in a simple comparitive statement like "objectid = 23". While multiple calls to this method may be chained together, you may also directly pass in more complex statements like "objectid = 23 AND (post_date > '2018-01-01' OR status = 'New')". See more examples below.

Ex: $oracle->set_where_clause("'users.status = 'Active'");

or

Ex: $oracle->set_where_clause("objectid = 23 AND (post_date > '2018-01-01' OR status = 'New'))"

prepend_where_clause

This behaves almost exactly like set_where_clause, but it is inserted at the beginning of the WHERE clause during execution. Normally, this shouldn’t be necessary, but it can be used to help manually optimize queries by adjusting the priority of the conditions.

Ex: $oracle->prepend_where_clause("'users.status = 'Active'");

set_having_clause

This sets the HAVING portion of a query. This method is destructive in that subsequent calls will overwrite the initial fields.

Ex: $oracle->set_having_clause('depth > 1');

set_join

This method allows you to pass in an entire straight join statement in a single call.

$oracle->set_join('hash_categories ON (hash_categories.reference_id = othertable.objectid)');

This method is always additive in that calls will always append to the existing query.

set_left_join

This method allows you to pass in an entire left join statement in a single call.

$oracle->set_left_join("hash_categories ON (hash_categories.reference_id = othertable.objectid AND hash_categories.reference_class = 'Book')");

This method is always additive in that calls will always append to the existing query.

set_right_join

This method allows you to pass in an entire right join statement in a single call.

$oracle->set_right_join('hash_categories ON (hash_categories.reference_id = othertable.objectid)');

This method is always additive in that calls will always append to the existing query.

set_union

This method allows you to pass in a whole other Oracle object to join the two combined queries with a UNION statement.e.g.:

$oracle = new CategoryOracle();
$oracle->set_where_clause('deleted = 0');
$oracle2 = new CustomCategoryOracle();
$oracle2->set_where_clause('deleted = 0');
$oracle->set_union($oracle2);
$oracle->get_record();

The results will be the union of all the non-deleted Category responses with all of the non-deleted CustomCategory responses.

get_count

After the query parameters are all set on the Oracle, get_count() executes a modified version of your query without limit_count to get a total count of all possible responses before limiting your query results. This allows for Manifesto to properly calculate the pagination of results, but it is also useful to avoid the expense of a more complicated database query that may not return any results.

It returns the total count of results, and stores this result in $oracle->total_count.

Ex: $total = $oracle->get_count();

get_record

This is the final call to build the query and execute the database request. By default, this method executes the query, loops through theh results, and _instantiates some instance of a ManifestoObject for each result in the database,_ as designated by the object_class of the Oracle. If you wish to access the results of the query as an array of associative arrays instead, simply pass false as the only parameter to this method.

Note: This method does not return the result array. It sets the response_count, total_count, response_array, and object_array properties of the Oracle, which may then be accessed later. This method returns the Oracle object itself, so it may be chained together with other methods.

``Ex: $oracle->get_record(); // to return an array of objects ``

or

Ex: $oracle->get_record(false); // to return an array of associative arrays, one per row`