Skip to content

Commit

Permalink
Incrementally improve Omeka_Record docs
Browse files Browse the repository at this point in the history
- explicitly mention mandatory ID column
- fix a bunch of incorrect names and formatting
- slightly flesh out info on DB tables and installing
- add sections

(fix #45)
  • Loading branch information
zerocrates committed Sep 3, 2019
1 parent b5dcc4d commit e9d5d83
Showing 1 changed file with 45 additions and 15 deletions.
60 changes: 45 additions & 15 deletions source/Tutorials/understandingOmeka_Record_AbstractRecord.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,73 @@
Understanding Omeka_Record_AbstractRecord
#########################################

:php:class:`Omeka_Record_AbstractRecord` is the heart of the ORM for Omeka. It is an abtract class that is extended to create the models for
Omeka and its plugins. Each class extending ``Omeka_Record_AbstractRecord`` corresponds to a database table, with each row representing an
individual record. Table columns correspond to public properties of the class.

:php:class:`Omeka_Plugin_AbstractRecord` is extended to create the models for Omeka and its plugins. It corresponds to a database table, with each row representing an individual record. Table columns correspond to public properties of the class.
In plugins, it's best practice to include the name of the plugin at the beginning of each model name, to avoid any potential conflicts with
models from the core or other plugins.

Classes extending ``Omeka_Record_AbstractRecord`` are placed in the ``models`` folder of a plugin (or ``application/models`` in the core).
You can choose to keep the model classes all directly under the ``models`` folder or organize them into subfolders. Omeka will work with
either organizational style, but as with all other class files, additional levels of the folder structure must have corresponding underscores
in the class name. For example, a model named ``MyPluginThing`` would be located at ``<plugin folder>/models/MyPluginThing.php``, while one named
``MyPlugin_Thing`` would be located at ``<plugin folder/models/MyPlugin/Thing.php``.

.. code-block:: php
class MyThing extends Omeka_Plugin_AbstractRecord
class MyPluginThing extends Omeka_Record_AbstractRecord
{
/**
* text Text for the MyThing
*/
* text Text for the Thing
*/
public $text;
}
Note that an `$id` property is inherited from `Omeka_Plugin_AbstractRecord`.
Note that an ``$id`` property is inherited from ``Omeka_Plugin_AbstractRecord``. All Omeka ORM models have an ``id`` property/column
representing the primary key. Tables that would normally have a composite primary key, like "junction" tables representing
many-to-many relationships, must either have a redundant ``id`` column or be managed outside the ORM.

***************
Database tables
***************

To create the database table for a plugin, use Omeka's `install` hook. It will inflect the classes name to make it plural and underscored. For example, a model called `MyThing` will have a table called `my_things`.
The Omeka convention is for table names to be underscore-separated and pluralized (i.e. a ``MyPluginThing`` model will correspond to a table
``my_plugin_things`` in the database). This convention can be overridden if necessary in the corresponding ``Table`` model. Accessing a model
name as a property (``$db->MyPluginThing``) from the DB object will return the table name for that model, correctly prepended with the user's
configured database prefix. This is the preferred way to get the table name when needed for SQL queries (like a ``CREATE TABLE`` query).

For example this code in a plugin's `install` hook will create the table for the above model.
To create the tables in the database table for a plugin, use the :doc:`install hook </Reference/hooks/install>`. The table must contain
a column for each public property of the model, as well as an auto-incrementing ``id`` column as the primary key. For example, this code
in a plugin would create a table for the above model:

.. code-block:: php
protected $_hooks = array('install' /* ... */);
/* ... */
public function hookInstall() {
$db = $this->_db;
$sql = "
CREATE TABLE IF NOT EXISTS `$db->MyThing` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`text` text NOT NULL,
. . .
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
CREATE TABLE IF NOT EXISTS `$db->MyPluginThing` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci";
$db->query($sql);
}
Other features like additional indexes besides the primary key would be specified in the CREATE TABLE statement when necessary.

Plugins that create tables should drop them in their :doc:`uninstall hook </Reference/hooks/uninstall>`.

********************
Events and callbacks
********************

The abstract record contains callback functions creating, reading, updating, and deleting records, both before and after those actions. These are helpful if any automatic processing should be done during those operations.

For example, to append a message to text as the record is saved, override the `beforeSave()` callback.
For example, to append to the ``text`` column before the record is saved, override the ``beforeSave()`` callback.

.. code-block:: php
Expand Down

2 comments on commit e9d5d83

@teo1978
Copy link

@teo1978 teo1978 commented on e9d5d83 Sep 3, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the 'id' field actually have to be the primary key though? Isn't it enough for it to be an index and auto-increment?

I created my junction table with the primary key made by the two "foreign" keys, and the redundant 'id' column being just auto-increment and index, and so far I haven't had issues.

Comments in the source code, I seem to remember, said something like "preferably the primary key" or something like that.

@zerocrates
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ORM doesn't know the difference between... really anything that's going on on the database side of things, it just bakes in assumptions about what columns will exist and how they (id in particular) behave. In the context of the documentation I think it's clearer to just say "it's the primary key" vs. "it's an auto-incrementing unique key, usually the primary key".

Technically even auto-incrementing need not be necessary if you're careful about assigning IDs "correctly" but it's really not something we'd want to be drawing attention to.

Please sign in to comment.