Index

RepositoryController

MMO\core\controllers · 1 symbol · generated 30 Sep 2026

class

RepositoryController

RepositoryController.php:46

Controller used to handle entities through the repositories

class MMO\core\controllers\RepositoryController extends MMO\core\classes\aController implements MMO\core\interfaces\iRoutable
Namespace
MMO\core\controllers
Extends
aController
Implements
iRoutable
WARNING: all date MUST be sent as ISO 8601 (javascript function date.toISOString()): YYYY-MM-DDTHH:mm:ss.ccc(+|-)HH:mm ## Route `data` Collections can be accessed through the url `data/{repository}/{collection}.{format}` - {repository} the repository's name - {collection} the collection's name in the repository - {format} is the output format of the answer (supported: json|csv) - GET: list the entities - POST: insert/update entities - PUT: update entities by id - DELETE: delete entities ### Supported query - pagination : ?page[offset]=0&page[limit]=10 - sorting : ?sort=-created,title - fields : ?fields=articles.title,-articles.body,people.name - filters : ?filters[age][$>]=20&filters[age][$<]=50&filters[author.status]=active - list only id : ?onlydIds - search : ?search[type]=$text&search[text]=test: will do a search of type `$text` using the value text = 'test' ## Route `schemas` GET|data/schemas.json This route return all the schemas for every available entity class served by the repositories: {class: Schema}

Index

API_PARAMETERS_INFO
query
repositories
xlsxTplFilename
CollectionUrl($collection, $repository, $extension, $query) static
ConnectRoutes($routes, $config) staticCalled once when routes are registered: adds the actual list of configured repository/collection names as an enum constraint onto every route's repository/collection API parameter info (so ge…
getCollection($name, $repository)
getQuery()
getRepositories()
getRepository($name)
getRepositoryName($repo)
hasCollection($collection, $repository)
isListed($entity)Tell if a query of $entity's collection, dispatched as a listing's (routeGet), keeps it: its listeners decide (mmo.oauth's AccessController, an application's filter by client)
onRoute($route)
routeDelete($route)Delete entities by id -- archives an active entity (iEntity::archive), or permanently removes an already-archived one.
routeEntity($route)Fetch a single entity by its global uid (fetch), regardless of which repository/collection it's in.
routeGet($route)List entities from one collection: pagination, sort, field selection, filters, and text/property search (the class docblock's "Supported query" section), plus first/prev/next/last pagination l…
routePatch($route)Partially update entities by id -- either sets a new cStatus (via a 'status' key), or pushes one or more values onto array properties (any other key, optionally a `path/to/n…
routePost($route)Insert or update entity with similar data (using groups or id)
routeSchemas($route)
routeUpdate($route)Update entity only by id
SchemaUrl($entity) static
setRepositories($repositories)Replace every registered repository (Serialize -- this is the injection target for the repositories config key, e.g.

Constants1

API_PARAMETERS_INFO

const API_PARAMETERS_INFO = ['parameters' => […10 items]]

Properties3

query

protected ?MMO\core\entities\Query $query = null
Type
null | Query

repositories

#[MMO\core\attributes\Serialize(unserialize: 'setRepositories')] protected array $repositories = []
Type
array

xlsxTplFilename

?string $xlsxTplFilename = null
Type
null | string

Methods19

CollectionUrl($collection, $repository, $extension, $query)

staticRepositoryController.php:139
static function CollectionUrl( string $collection, string $repository = 'main', string $extension = 'json', MMO\core\helpers\FilterGroup|array|string $query = '' ): string
$collectionstring
$repository = 'main'string
$extension = 'json'string
$query = ''FilterGroup | array | stringa query string, or filters to encode into one (apiQuery).
returnsstringthe URL for routeGet on this collection.

ConnectRoutes($routes, $config)

staticRepositoryController.php:78

Called once when routes are registered: adds the actual list of configured repository/collection names as an enum constraint onto every route's repository/collection API parameter info (so generated API docs/validation know the real allowed values, instead of just 'string').

static function ConnectRoutes(array &$routes, array $config): void
$routesarray
$configarrayunused directly -- get is used instead to read this controller's own configured repositories.
returnsvoid

getCollection($name, $repository)

RepositoryController.php:193
function getCollection(string $name, ?string $repository = null): MMO\core\interfaces\iCollection
$namestring
$repository = nullnull | stringif given, only look in that repository; if null, search every registered one.
returnsiCollection
throwsif no matching collection is found.

hasCollection($collection, $repository)

RepositoryController.php:206
function hasCollection( MMO\core\interfaces\iCollection|string $collection, ?string $repository = null ): bool
$collectioniCollection | string
$repository = nullnull | stringif given, only check that repository; if null, check every registered one.
returnsbool

isListed($entity)

RepositoryController.php:240

Tell if a query of $entity's collection, dispatched as a listing's (routeGet), keeps it: its listeners decide (mmo.oauth's AccessController, an application's filter by client)

protected function isListed(mixed $entity): bool
$entitymixed
returnsboolfalse for a value that is not an entity of a collection
$this->isListed(\MMO\fetch($this, 'file://users.json#1')); // false if a listing of users would leave it out

onRoute($route)

RepositoryController.php:162
function onRoute(MMO\core\server\Route $route): bool
See
iRoutable::onRoute -- prepares the response for this route's extension before the route's own handler runs: JSON (default), CSV, or Xlsx (optionally from a template, $xlsxTplFilename), each with a Content-Disposition: attachment filename derived from today's date and the {repository}/{collection} URL.
$routeRoute
returnsbool

routeDelete($route)

RepositoryController.php:526

Delete entities by id -- archives an active entity (iEntity::archive), or permanently removes an already-archived one.

#[MMO\core\attributes\APIRoute('DELETE|data/{repository}/{collection}.{extension}', ['parameters' => […10 items]], mediaTypes: ['json', 'csv'])] function routeDelete(MMO\core\server\Route $route): array
$routeRoutethe request body: a single {id: ...} object, or a list of them.
returnsarrayevery entity actually archived/removed (a missing 'id' or unknown id is skipped and logged, not thrown).
throwsif repository/collection doesn't resolve.
throwsif the collection is readonly.

routeEntity($route)

RepositoryController.php:261

Fetch a single entity by its global uid (fetch), regardless of which repository/collection it's in.

#[MMO\core\attributes\APIRoute('GET|data.json?uid={uid}', ['parameters' => […10 items]], mediaTypes: ['json'])] function routeEntity(MMO\core\server\Route $route): arrayWhat a listing would not show is refused ([`isListed`](https://mmoframework.fr/documentation/mmo.core/php/controllers/RepositoryController.md#repositorycontroller-islisted)): the entity the uid names, and one of another collection that its path leads to (`...#12/author`; an embedded one, `...#12/address/0`, is its entity's). NOTE: until 2026-09 nothing was, \MMO\fetch() dispatching no query: `data.json?uid=file://users.json#1` gave any client the user that `data/main/users.json` refused it.
$routeRoute
returnsarray[the entity].
throwsif no entity matches, or a listing would leave it out.
GET data.json?uid=file://users.json#1 // [the user], if a listing of users would show it

routeGet($route)

RepositoryController.php:290

List entities from one collection: pagination, sort, field selection, filters, and text/property search (the class docblock's "Supported query" section), plus first/prev/next/last pagination links (NOTE: see the caveat on 'data.total'/'page.total'/'last' below -- task_03489439).

#[MMO\core\attributes\APIRoute('GET|data/{repository}/{collection}.{extension}', ['parameters' => […10 items]], mediaTypes: ['json', 'csv', 'xlsx'])] function routeGet(MMO\core\server\Route $route): array
$routeRoute
returnsarraythe matching entities for this page.
throwsif repository or collection doesn't resolve.

routePatch($route)

RepositoryController.php:566

Partially update entities by id -- either sets a new cStatus (via a 'status' key), or pushes one or more values onto array properties (any other key, optionally a path/to/nested/prop for a nested entity, via iArrayProperties::setArrayPropertyOffset).

#[MMO\core\attributes\APIRoute('PATCH|data/{repository}/{collection}.{extension}', ['parameters' => […3 items]], ['id' => 'string'], mediaTypes: ['json', 'csv'])] function routePatch(MMO\core\server\Route $route): array
$routeRoutethe request body: a single {id, ...} object, or a list of them.
returnsarrayevery entity actually changed (a missing/unknown id, unknown status, or an archived/final/unreachable-path target is skipped and logged, not thrown).
throwsif repository/collection doesn't resolve.
throwsif the collection is readonly.

routePost($route)

RepositoryController.php:469

Insert or update entity with similar data (using groups or id)

#[MMO\core\attributes\APIRoute('POST|data/{repository}/{collection}.{extension}', ['parameters' => […10 items]], mediaTypes: ['json', 'csv'])] function routePost(MMO\core\server\Route $route): array
$routeRoutethe request body: a single entity object, or a list of them. Per entity: an 'id' key with a value updates that entity; an 'id' key present but explicitly null forces creation of a new entity; no 'id' key at all looks for (or creates) an entity with matching content (Collection::getOrCreateEntity).
returnsarrayevery entity actually created or changed (an unknown id, or an archived/final entity being updated, is skipped and logged, not thrown; an unchanged existing entity is silently omitted).
throwsif repository/collection doesn't resolve.
throwsif the collection is readonly.
throwsif nothing ended up being inserted/updated.

routeSchemas($route)

RepositoryController.php:221
#[MMO\core\attributes\APIRoute('GET|data/schemas.json', 'Get schemas for all the entities in the application', mediaTypes: ['json'])] function routeSchemas(MMO\core\server\Route $route): array
$routeRoute
returnsarraya JSON Schema document ($id/$defs) covering every entity class served by every registered repository/collection.

routeUpdate($route)

RepositoryController.php:415

Update entity only by id

#[MMO\core\attributes\APIRoute('PUT|data/{repository}/{collection}.{extension}', ['parameters' => […10 items]], mediaTypes: ['json', 'csv'])] function routeUpdate(MMO\core\server\Route $route): array
$routeRoutethe request body: a single entity object, or a list of them; each MUST have an 'id'.
returnsarraythe entities that were actually changed (an entity with no 'id', an unknown id, an archived/final entity, or no actual changes is skipped and logged, not thrown).
throwsif repository/collection doesn't resolve.
throwsif the collection is readonly.

SchemaUrl($entity)

staticRepositoryController.php:151
static function SchemaUrl( MMO\core\interfaces\iEntity|MMO\core\interfaces\iCollection|null $entity = null ): string
$entity = nulliEntity | iCollection | nullif given, the URL points at that specific entity's/collection's $defs entry; if null, at the root schemas document (routeSchemas).
returnsstring

setRepositories($repositories)

RepositoryController.php:120

Replace every registered repository (Serialize -- this is the injection target for the repositories config key, e.g. RepositoryController::class => ['repositories' => ['main' => ...]]).

function setRepositories(array $repositories): void
$repositoriesarrayname => iRepository.
returnsvoid
throwsif any value isn't an iRepository.
Inherited members (55)
ConstantsDeclared byDescription
ALERTiLogLevelAlert: Action must be taken immediately.
ALLiLogLevelMask for all
ALL_PLUSiLogLeveldebug everything
BACKTRACEiLogLevel
CRITICALiLogLevelCritical: Critical conditions.
DEBUGiLogLevelDebug: Detailed debug information.
DEEPiLogLeveldebug everything with arguments
EMERGENCYiLogLevelEmergency: System is unusable.
ERRORiLogLevelError: Runtime errors that do not require immediate action but should typically be logged and monitored.
ERROR_PLUSiLogLevelMask for all error
FATALiLogLevelMask for all fatal error
INFOiLogLevelInfo: Interesting events.
INFO_PLUSiLogLevelMask for all errors/warning/notices/info
MEMORYiLogLevelinclude backtrace object
NOTICEiLogLevelNotice: Normal but significant events.
NOTICE_PLUSiLogLevelMask for all errors/warning/notices/info
TRACEiLogLevelinclude backtrace as origins
WARNINGiLogLevelWarning: Exceptional occurrences that are not errors.
WARNING_PLUSiLogLevelMask for all errors and warnings
PropertiesDeclared byDescription
verbosityaModule
MethodsDeclared byDescription
alert($message, $context)aModuleAction must be taken immediately.
backtraces($message, $context)aModuleForce-log a message at INFO level together with a full stack trace/memory snapshot (iLogLevel::BACKTRACE), bypassing the verbosity mask entirely (any non-zero verbosity is enough to trigger it).
Configure($config)aModuleMerge $config into this module's configuration in the shared Configuration.
critical($message, $context)aModuleCritical conditions. No-op if CRITICAL is currently filtered out by the verbosity mask.
debug($message, $context)aModuleDetailed debug information.
debugName()aModuleHuman-readable identifier used as the default {origin} in this instance's log messages.
DefaultConfig()aModuleThe config a module starts from before anything loaded via Configuration is merged in.
emergency($message, $context)aModuleSystem is unusable. No-op if EMERGENCY is currently filtered out by the verbosity mask.
error($message, $context)aModuleRuntime errors that do not require immediate action but should typically be logged and monitored.
ExtractRoutes($config)aControllerExtract all the APIRoute from this class, regardless of the fact they are registered in the application
getVerbosity()aModule
HasRoutes()aControllerTells if any APIRoute are registered in the application
info($message, $context)aModuleInteresting events. No-op if INFO is currently filtered out by the verbosity mask.
Instantiate($config)aModule(Re)create the shared instance immediately, configured with $config merged into the class's existing config.
IsShared()aModule
Link($method, $data)aControllerBuild a Link (URL + label/icon/description/title, taken from the route's APIRoute metadata) for a registered route.
log($level, $message, $context)aModuleLogs with an arbitrary level.
notice($message, $context)aModuleNormal but significant events.
offsetExists($key)aModule\ArrayAccess::offsetExists -- tells whether $key is a declared property at all, regardless of whether it is currently readable/writable through array access.
offsetGet($key)aModule\ArrayAccess::offsetGet -- reads a property directly, unless it has a #[Serialize(serialize: 'methodName')] attribute, in which case that zero-argument method is called instead (e.g.
offsetSet($key, $value)aModule\ArrayAccess::offsetSet -- sets a property directly, unless it has a #[Serialize(unserialize: 'methodName')] attribute, in which case that method is called with $value instead (e.g.
offsetUnset($key)aModule\ArrayAccess::offsetUnset -- equivalent to $module[$key] = null.
Route($method)aControllerGet a registered APIRoute WARNING: if this class was not registered in the application, it will return null.
Routes()aControllerGet a list of registered APIRoutes (from this class) in the application WARNING: if this class was not registered in the application, it will return an empty array.
serialize($path, $serializer)aModule\MMO\core\interfaces\iSerializable::serialize -- exports every property (via
setVerbosity($verb)aModuleSet the current verbosity mask, replacing whatever it was before.
Shared()aModuleGet the shared instance, creating (and configuring) it on first call.
testVerbosity($level)aModuleTest whether a given level (or set of levels) is currently enabled by this instance's verbosity mask.
traitUnshare($serialize)aModuleRemove the shared instance, so the next Shared() call creates a fresh one.
unserialize($data, $path, $instances)aModule\MMO\core\interfaces\iSerializable::unserialize -- merges $data onto DefaultConfig, runs it through the (possibly overridden) constructor, then applies each resulting value to its property (via
Unshare($serialize)aModuleLike tSingleton::Unshare, but also disconnects this module's instance from every event it was listening to (via Event::DisconnectListeners) before dropping it.
Url($method, $data)aControllerBuild the URL for a registered route, filling in any {placeholder} from $data.
warning($message, $context)aModuleExceptional occurrences that are not errors.
__construct($config)aModuleprotected constructor, so it is not possible to do new Module(...) called by the serialization process just before being injected with data.
__wakeup()aControllerCalled automatically right after the controller's shared instance is built (aModule::unserialize): registers onRoute as a Route listener with a low priority (-10), so it…