Skip to content
This repository was archived by the owner on Dec 11, 2022. It is now read-only.

Entity Querying

hperrin edited this page Oct 4, 2014 · 30 revisions

The real power behind Nymph is the entity querying system. After all, what's the use of having complex data and relationships if you can't find them?

The simplest way to get an entity is usually its factory static method. The Entity class, and probably most other classes that extend it, expect a GUID as an argument. However, the author of an entity's class can use whatever they like as arguments. For example, the user class in 2be takes either a GUID or a username. Usually the method will return a brand new entity if the queried entity is not found.

ℹ️ Tip: If you're using a user provided value as the GUID, casting it to an int will ensure it is evaluated as a GUID. Also, non-numeric values will be evaluated as 0, resulting in a new entity, since no entity has GUID 0. Then you can determine if it was found by checking that guid is set.

Getting Entities Using the Factory Method
```php // Most entities use a GUID. $baz = FoobarBaz::factory((int) $_REQUEST['id']);

if (!isset($baz->guid)) { echo 'The specified baz cannot be found!'; return; }

// When selecting a user in 2be, you can use a GUID or a username. $cronUser = User::factory('cron'); if (!isset($cronUser->guid)) { echo 'Can't find the cron user! Have you created one yet?'; return; }

// If the script made it to this point, both $baz and $cronUser were found! echo 'Hooray! I found the baz you wanted and the cron user!';


The really powerful way of querying entities is Nymph's `getEntities` and `getEntity` methods.

The first argument to these methods is an options array. It is an associative array in PHP or an object in JS. The options array can be empty, in which case the `Entity` class will be used for returned entities. The following is a list of options which Nymph supports.

<div dir="rtl">Entity Querying Options</div>
Option | Type | Default | Description
------ | ---- | ------- | -----------
class | string | "Entity" | The class used to create each entity. It must have a factory static method that returns a new instance.
limit | int | null | The limit of entities to be returned. Not needed when using getEntity, as it always returns only one.
offset | int | 0 | The offset from the oldest (or newest if reversed) matching entity to start retrieving.
reverse | bool | false | If true, entities will be retrieved from newest to oldest. Therefore, offset will be from the newest entity.
sort | string | "cdate" | How to sort the entities. Accepts "guid", "cdate", and "mdate".

A plugin or Nymph driver is free to add extra options, but you should consider prepending its name to the name of the option. For example, if your plugin, EntityVersions, wants to add the option "date", it should use "EntityVersionsDate".

Every argument following the options array is a selector. A selector is an associative array (object in JS) of criteria. An entity must match each selector's criteria to be returned. The first member of the array (the value at index 0, or the "type" entry in JS) is the type of selector, which determines how the criteria are matched against an entity's data.

<div dir="rtl">Entity Selector Types</div>
Type | Name | Description
---- | ---- | -----------
& | And | All values in the selector must be true.
\| | Or | At least one value in the selector must be true.
!& | Not And | All values in the selector must be false.
!\| | Not Or | At least one value in the selector must be false.

The subsequent members of the array are the criteria of the selector. They must be in the form `$selector['name'] = $value`, or `$selector['name'] = array($value1, $value2,...)`. They can be negated by prepending a bang (!) to the name, such as `$selector['!tag'] = 'user'`.

<div dir="rtl">Entity Selector Criteria</div>
Name | Value | Condition | Example Selector | Matching Entity
---- | ----- | --------- | ---------------- | ---------------
guid | A GUID. | True if the entity's GUID is equal. | array('&', 'guid' => 12) | $entity->guid = 12;
tag | A tag. | True if the entity has the tag. | array('&', 'tag' => 'foobar') | $entity->addTag('foobar');
isset | A name. | True if the named variable exists and is not null. | array('&', 'isset' => 'foo') | $entity->foo = 0;
data | An array with a name, then value. | True if the named variable is defined and equal. | array('&', 'data' => array('foo', false)) | $entity->foo = 0;
strict | An array with a name, then value. | True if the named variable is defined and identical. | array('&', 'strict' => array('foo', 0)) | $entity->foo = 0;
array | An array with a name, then value. | True if the named variable is an array containing the value. Uses `inArray`. | array('&', 'array' => array('foo', 'bar')) | $entity->foo = array('bar', 'baz');
match | An array with a name, then regular expression. | True if the named variable matches. Uses `preg_match`. | array('&', 'match' => array('foo', '/bar/')) | $entity->foo = 'foobarbaz';
gt | An array with a name, then value. | True if the named variable is greater than the value. | array('&', 'gt' => array('foo', 5)) | $entity->foo = 6;
gte | An array with a name, then value. | True if the named variable is greater than or equal to the value. | array('&', 'gte' => array('foo', 6)) | $entity->foo = 6;
lt | An array with a name, then value. | True if the named variable is less than the value. | array('&', 'lt' => array('foo', 7)) | $entity->foo = 6;
lte | An array with a name, then value. | True if the named variable is less than or equal to the value. | array('&', 'lte' => array('foo', 6)) | $entity->foo = 6;
ref | An array with a name, then either a entity, or a GUID. | True if the named variable is the entity or an array containing the entity. | array('&', 'ref' => array('foo', 12)) | $entity->foo = Entity::factory(12);

So putting it all together, you can specify any of the options, and any number of selectors to find the exact entities you want.

<div dir="rtl">Getting Entities by Querying</div>
```php
// Get all entities using the entity class.
$entities = $nymph->getEntities();

// Get only the first entity.
$entity = $nymph->getEntity();

// Get the last entity.
$entity = $nymph->getEntity(array('reverse' => true));

// Get all baz entities, using the FoobarBaz class.
$entities = $nymph->getEntities(
    array('class' => FoobarBaz),
    array('&',
      'tag' => array('foobar', 'baz')
    )
  );

// Get the five newest baz entities.
$entities = $nymph->getEntities(
    array('class' => FoobarBaz, 'reverse' => true, 'limit' => 5),
    array('&',
      'tag' => array('foobar', 'baz')
    )
  );

// Get baz entities with names.
$entities = $nymph->getEntities(
    array('class' => FoobarBaz),
    array('&',
      'tag' => array('foobar', 'baz'),
      'isset' => 'name'
    )
  );

// Get baz entities without names.
$entities = $nymph->getEntities(
    array('class' => FoobarBaz),
    array('&',
      'tag' => array('foobar', 'baz'),
      '!isset' => 'name'
    )
  );

// Get baz entities with either first names or last names.
$entities = $nymph->getEntities(
    array('class' => FoobarBaz),
    array('&',
      'tag' => array('foobar', 'baz')
    ),
    array('|',
      'isset' => array('first_name', 'last_name')
    )
  );

// Get baz entities created since yesterday.
$entities = $nymph->getEntities(
    array('class' => FoobarBaz),
    array('&',
      'tag' => array('foobar', 'baz'),
      'gt' => array('cdate', strtotime('-1 day'))
    )
  );

// Get baz entities with names, who either make not greater than 8 dollars pay or are under 22.
$entities = $nymph->getEntities(
    array('class' => FoobarBaz),
    array('&',
      'tag' => array('foobar', 'baz'),
      'isset' => 'name'
    ),
    array('!|', // at least one must be false
      'gte' => array('age', 22),
      'gt' => array('pay', 8)
    )
  );

// Get baz entities named Clark, James, Chris, Christopher, Jake, or Jacob.
$entities = $nymph->getEntities(
    array('class' => FoobarBaz),
    array('&',
      'tag' => array('foobar', 'baz')
    ),
    array('|',
      'strict' => array(
        array('name', 'Clark'),
        array('name', 'James')
      ),
      'match' => array(
        array('name', '/Chris(topher)?/'),
        array('name', '/Ja(ke|cob)/')
      )
    )
  );
// Get all entities using the entity class.
var entitiesPromise = Nymph.getEntities();

// Get only the first entity.
var entityPromise = Nymph.getEntity();

// Get the last entity.
var entityPromise = Nymph.getEntity({'reverse': true});

// Get all baz entities, using the FoobarBaz class.
var entitiesPromise = Nymph.getEntities(
    {'class': 'FoobarBaz'},
    {'type': '&',
      'tag': ['foobar', 'baz']
    }
  );

// Get the five newest baz entities.
var entitiesPromise = Nymph.getEntities(
    {'class': 'FoobarBaz', 'reverse': true, 'limit': 5},
    {'type': '&',
      'tag': ['foobar', 'baz']
    }
  );

// Get baz entities with names.
var entitiesPromise = Nymph.getEntities(
    {'class': 'FoobarBaz'},
    {'type': '&',
      'tag': ['foobar', 'baz'],
      'isset': 'name'
    }
  );

// Get baz entities without names.
var entitiesPromise = Nymph.getEntities(
    {'class': 'FoobarBaz'},
    {'type': '&',
      'tag': ['foobar', 'baz'],
      '!isset': 'name'
    }
  );

// Get baz entities with either first names or last names.
var entitiesPromise = Nymph.getEntities(
    {'class': 'FoobarBaz'},
    {'type': '&',
      'tag': ['foobar', 'baz']
    },
    {'type': '|',
      'isset': ['first_name', 'last_name']
    }
  );

// Get baz entities created since yesterday.
var entitiesPromise = Nymph.getEntities(
    {'class': 'FoobarBaz'},
    {'type': '&',
      'tag': ['foobar', 'baz'],
      'gt': ['cdate', Math.round((new Date()).getTime() / 1000) - 86400]
    }
  );

// Get baz entities with names, who either make not greater than 8 dollars pay or are under 22.
var entitiesPromise = Nymph.getEntities(
    {'class': 'FoobarBaz'},
    {'type': '&',
      'tag': ['foobar', 'baz'],
      'isset': 'name'
    },
    {'type': '!|', // at least one must be false
      'gte': ['age', 22],
      'gt': ['pay', 8]
    }
  );

// Get baz entities named Clark, James, Chris, Christopher, Jake, or Jacob.
var entitiesPromise = Nymph.getEntities(
    {'class': 'FoobarBaz'},
    {'type': '&',
      'tag': ['foobar', 'baz']
    },
    {'type': '|',
      'strict': [
        ['name', 'Clark'],
        ['name', 'James']
      ],
      'match': [
        ['name', '/Chris(topher)?/'],
        ['name', '/Ja(ke|cob)/']
      ]
    }
  );

Clone this wiki locally