An PHP class to use for data objects, using JSON schema as a validation structure.
Dataset.Now define the json schema. A simple method is to supply a class constant JSON_SCHEMA with the schema value:
class SimpleExample extends Dataset {
const JSON_SCHEMA = '{"type": "object","required":["id"],"id":{"type":"integer"},"version":{"type":"string","default":"1.2.5"}}';
}
Most times however, your schema will live in a separate file. Therefore you will not define the class constant JSON_SCHEMA, rather provide the path to the json schema as the return value of the public static method pathToJsonSchema. You may follow the convention of appending .schema.json to the classname, if you wish, as shown here:
/**
* {@inheritdoc}
*/
protected static function pathToJsonSchema() {
return __DIR__ . '/DatasetAlpha.schema.json';
}
Now create a json schema file to define your dataset at the path defined above.
pattern keyword to define a regex expression that you do NOT include the delimiters like you do in PHP's preg_match. This is corrent JSON: "pattern": "\\?[^#]+", notice there are no delimiters.Then implement an instance in your code like this:
<?php
$data = ['id' => 123];
...
try {
$timer = Timer::dataset($data)->validate()->throwFirstProblem();
} catch (\Exception $exception) {
// Do something if validation failed.
}
static::You can provide class methods, constants, etc in your JSON schema files and they will be evaluated at runtime. For example, here we provide the regex pattern for the date property with a class constant, and the default value with a class method. The cornerstone of this process is that the value begin with static::.
"date": {
"type": "string",
"default": "static::defaultDate()",
"pattern": "static::REGEX_DATEISO8601"
},
$array = $data->get()$json = strval($data).$id = $data->id$id = $data->userId. Read about aliases for more info.Timer::getDefault('id').Timer::getDefaults()$data->getProblems.$data->throwFirstError::mutate.You may have aliases for property keys, which means you can access the same value using any of a number of keys. To define an alias use colon separation as seen below:
{
...
"properties": {
"mi:me:moi": {
"default": "myself",
"type": "string",
"pattern": "/^m.+/"
},
validate(), but read the docs there for what needs to happen.ignoreKey() instead, if possible.protected static function ignoreKey($key)
{
return $key === 'duration';
}
protected static function ignoreKey($key)
{
return strpos($key, '#') === 0;
}
static::ignoreKey() in your class.The time to do this is during ::import.
<?php
/**
* Import extra data based on a default value.
*
* In this example, the defaults set the user id by global var. During import
* we check for a user_id, either by import $data or the default data. Then we
* make sure the the $original import data doesn't contain session_id, and if
* so we pull that data from the user account object.
*/
class Alpha extends Dataset {
...
/**
* {@inheritdoc}
*/
protected static function defaults() {
global $user;
return [
'user_id' => $user->uid,
'session_id' => -1,
];
}
/**
* {@inheritdoc}
*/
public function import($data) {
$original = $data;
$data += static::getDefaults();
// Figure the session id based on the last time the user logged in.
// https://amplitude.zendesk.com/hc/en-us/articles/115002323627-Sessions
if ($data['user_id'] && empty($original['session_id'])) {
$account = user_load($data['user_id']);
// We will count our session based on last login.
// https://drupal.stackexchange.com/questions/21864/whats-the-difference-between-user-login-and-access#21873
$data['session_id'] = $account->login * 1000;
}
return parent::import($data);
}
}