As an example, the implementation for users looks like this:
{jinja{ codebox(
- "php",
- "php/api/sitemaps/UserSitemapObject.class.php",
- "files/lib/system/sitemap/object/UserSitemapObject.class.php"
+ title="files/lib/system/sitemap/object/UserSitemapObject.class.php",
+ language="php",
+ filepath="php/api/sitemaps/UserSitemapObject.class.php"
) }}
Next, the sitemap object must be registered as an object type:
For any type of object related to events, you have to define an object type for the object type definition `com.woltlab.wcf.notification.objectType`:
{jinja{ codebox(
- "xml",
- "php/api/user_notifications/objectType.xml",
- "objectType.xml"
+ title="objectType.xml",
+ language="xml",
+ filepath="php/api/user_notifications/objectType.xml"
) }}
The referenced class `FooUserNotificationObjectType` has to implement the [IUserNotificationObjectType](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/notification/object/type/IUserNotificationObjectType.class.php) interface, which should be done by extending [AbstractUserNotificationObjectType](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/notification/object/type/AbstractUserNotificationObjectType.class.php).
{jinja{ codebox(
- "php",
- "php/api/user_notifications/FooUserNotificationObjectType.class.php",
- "files/lib/system/user/notification/object/type/FooUserNotificationObjectType.class.php"
+ title="files/lib/system/user/notification/object/type/FooUserNotificationObjectType.class.php",
+ language="php",
+ filepath="php/api/user_notifications/FooUserNotificationObjectType.class.php"
) }}
You have to set the class names of the database object (`$objectClassName`) and the related list (`$objectListClassName`).
Additionally, you have to create a class that implements the [IUserNotificationObject](https://github.com/WoltLab/WCF/blob/master/wcfsetup/install/files/lib/system/user/notification/object/IUserNotificationObject.class.php) whose name you have to set as the value of the `$decoratorClassName` property.
{jinja{ codebox(
- "php",
- "php/api/user_notifications/FooUserNotificationObject.class.php",
- "files/lib/system/user/notification/object/FooUserNotificationObject.class.php"
+ title="files/lib/system/user/notification/object/FooUserNotificationObject.class.php",
+ language="php",
+ filepath="php/api/user_notifications/FooUserNotificationObject.class.php"
) }}
- The `getTitle()` method returns the title of the object.
An example file might look like this:
{jinja{ codebox(
- "xml",
- "php/api/user_notifications/userNotificationEvent.xml",
- "userNotificationEvent.xml"
+ title="userNotificationEvent.xml",
+ language="xml",
+ filepath="php/api/user_notifications/userNotificationEvent.xml"
) }}
Here, you reference the user notification object type created via `objectType.xml`.
In `AbstractSharedUserNotificationEvent::prepare()`, you can, for example, tell runtime caches to prepare to load certain objects which then are loaded all at once when the objects are needed.
{jinja{ codebox(
- "php",
- "php/api/user_notifications/FooUserNotificationEvent.class.php",
- "files/lib/system/user/notification/event/FooUserNotificationEvent.class.php"
+ title="files/lib/system/user/notification/event/FooUserNotificationEvent.class.php",
+ language="php",
+ filepath="php/api/user_notifications/FooUserNotificationEvent.class.php"
) }}
- The `$stackable` property is `false` by default and has to be explicitly set to `true` if stacking of notifications should be enabled.
Some database objects provide static getters, either if they are decorators or for a unique combination of database table columns, like `wcf\data\box\Box::getBoxByIdentifier()`:
{jinja{ codebox(
- "php",
- "php/code-style/Box.class.php",
- "files/lib/data/box/Box.class.php"
+ title="files/lib/data/box/Box.class.php",
+ language="php",
+ filepath="php/code-style/Box.class.php"
) }}
Such methods should always either return the desired object or `null` if the object does not exist.
The basic model derives from `wcf\data\DatabaseObject` and provides a convenient constructor to fetch a single row or construct an instance using pre-loaded rows.
{jinja{ codebox(
- "php",
- "php/database-objects/Example.class.php",
- "files/lib/data/example/Example.class.php"
+ title="files/lib/data/example/Example.class.php",
+ language="php",
+ filepath="php/database-objects/Example.class.php"
) }}
The class is intended to be empty by default and there only needs to be code if you want to add additional logic to your model. Both the class name and primary key are determined by `DatabaseObject` using the namespace and class name of the derived class. The example above uses the namespace `wcf\…` which is used as table prefix and the class name `Example` is converted into `exampleID`, resulting in the database table name `wcfN_example` with the primary key `exampleID`.
If you already have a `DatabaseObject` class and would like to extend it with additional data or methods, for example by providing a class `ViewableExample` which features view-related changes without polluting the original object, you can use `DatabaseObjectDecorator` which a default implementation of a decorator for database objects.
{jinja{ codebox(
- "php",
- "php/database-objects/ViewableExample.class.php",
- "files/lib/data/example/ViewableExample.class.php"
+ title="files/lib/data/example/ViewableExample.class.php",
+ language="php",
+ filepath="php/database-objects/ViewableExample.class.php"
) }}
It is mandatory to set the static `$baseClass` property to the name of the decorated class.
Adding, editing and deleting models is done using the `DatabaseObjectEditor` class that decorates a `DatabaseObject` and uses its data to perform the actions.
{jinja{ codebox(
- "php",
- "php/database-objects/ExampleEditor.class.php",
- "files/lib/data/example/ExampleEditor.class.php"
+ title="files/lib/data/example/ExampleEditor.class.php",
+ language="php",
+ filepath="php/database-objects/ExampleEditor.class.php"
) }}
The editor class requires you to provide the fully qualified name of the model, that is the class name including the complete namespace. Database table name and index key will be pulled directly from the model.
Every row is represented as a single instance of the model, but the instance creation deals with single rows only. Retrieving larger sets of rows would be quite inefficient due to the large amount of queries that will be dispatched. This is solved with the `DatabaseObjectList` object that exposes an interface to query the database table using arbitrary conditions for data selection. All rows will be fetched using a single query and the resulting rows are automatically loaded into separate models.
{jinja{ codebox(
- "php",
- "php/database-objects/ExampleList.class.php",
- "files/lib/data/example/ExampleList.class.php"
+ title="files/lib/data/example/ExampleList.class.php",
+ language="php",
+ filepath="php/database-objects/ExampleList.class.php"
) }}
The following code listing illustrates loading a large set of examples and iterating over the list to retrieve the objects.
Of course, you do not have to set the property after creating the list object, you can also set it by creating a dedicated class:
{jinja{ codebox(
- "php",
- "php/database-objects/ViewableExampleList.class.php",
- "files/lib/data/example/ViewableExampleList.class.php"
+ title="files/lib/data/example/ViewableExampleList.class.php",
+ language="php",
+ filepath="php/database-objects/ViewableExampleList.class.php"
) }}
The `AbstractDatabaseObjectAction` solves both problems by wrapping around the editor class and thus provide an additional layer between the action that should be taken and the actual process. The first problem is solved by a fixed set of events being fired, the second issue is addressed by having a single entry point for all data editing.
{jinja{ codebox(
- "php",
- "php/database-objects/ExampleAction.class.php",
- "files/lib/data/example/ExampleAction.class.php"
+ title="files/lib/data/example/ExampleAction.class.php",
+ language="php",
+ filepath="php/database-objects/ExampleAction.class.php"
) }}
### Executing an Action