PHPackages                             conceptsandtraining/ente - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. conceptsandtraining/ente

ActiveLibrary[Framework](/categories/framework)

conceptsandtraining/ente
========================

An entity component framework for ILIAS.

4.0.0(7y ago)311.4k4[1 PRs](https://github.com/conceptsandtraining/lib-ente/pulls)GPL-3.0-or-laterPHPCI failing

Since Oct 4Pushed 6y ago5 watchersCompare

[ Source](https://github.com/conceptsandtraining/lib-ente)[ Packagist](https://packagist.org/packages/conceptsandtraining/ente)[ RSS](/packages/conceptsandtraining-ente/feed)WikiDiscussions master Synced 2w ago

READMEChangelogDependencies (1)Versions (20)Used By (0)

[![Build Status](https://camo.githubusercontent.com/ce28c92a1029368c31f45e266ffdddda8cf28ec0b520737bb7eef02d368a726e/68747470733a2f2f7472617669732d63692e636f6d2f636f6e6365707473616e64747261696e696e672f6c69622d656e74652e7376673f746f6b656e3d3473687772543934695051667061455831475759266272616e63683d6d6173746572)](https://travis-ci.com/conceptsandtraining/lib-ente)

ente.php
========

[](#entephp)

*An entity component framework for ILIAS.*

**Contact:** [Richard Klees](https://github.com/klees)

Model
-----

[](#model)

[Entity component model or system is an architectural pattern](https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system)developed for and mostly used in games. Still, the problems solved with that pattern are discovered in other situations, i.e. the development of interconnected functionality in [ILIAS](https://github.com/ILIAS-eLearning/ILIAS).

The general problem that is solved could be described as such: One has a system with some (or often a lot of) entities in it. An entity can be understood as an object that has an identity and exhibits some continuity over time and space. Within the system, there are a lot of subsystems that act upon these entities.

> **Example:**In a real time strategy game, entities would be units of the armies in the game as well as objects in the landscape and maybe other things. Systems acting upon these objects would be e.g. a physics system, a path finding system, a sound system, ...

> **Example:**In ILIAS an entity could basically be identified with all descendants of `ilObject`although there are possibly more things that could be called entities, e.g. questions in the test. Systems acting upon these entities would then e.g. be the RBAC system, the Learning Progress System, the Tree/Repository, ...

Implementing that kind of system with inheritance could lead to some problems that could also be observed in ILIAS:

- The classes that are used to build entities aqcuire a lot of code to be able to serve all systems that are interested in them.
- It is difficult to share functionality between the different classes of entities.
- It is cumbersome to define classes of entities where the objects might or might not take part in that system, depending on whatever.
- For languages that are not memory managed (e.g. C) that strategy for implementation might also be bad for caching in CPU caches.

Entity component model solves these problems by employing the principle to "favour composition over inheritance". The entities on their own are understood to just supply the required identity and continuity, i.e. each entity is basically an id. Components that serve the needs of different subsystems can then be attached to the entity to make them take part in that system.

> **Example:**A entity in the RTS game could be extended with a "physics" component that knows a location and other physical metrics of the entity to make it appear on the playground.

> **Example:**The implementation of the learning progress in ILIAS actually follows that model. Instead of providing some interface that all `ilObjects` with learning progress need to implement, one needs to build a separate object that takes care of the learning progress of the original `ilObject`.

This pattern for solving the described problem has some virtues over the naive inheritance based approach:

- Instead of one huge class that contains code for all kind of subsystems the entity is split up into distinct classes that each serve only some subset of all systems.
- There is an obvious way to share functionality between entities: just use the same components or implementation for the component.
- If an entity should not be processed by a subsystem just don't add the according component to the entity. This could easily be changed at runtime and requires no code change.
- C-programmes and the like could take care about memory locality more easily. A similar benefit regarding the database could apply in the PHP scenario.

There are definetly also disadvantages in using the entity component model. For the sake of the argument they are not written down here. Finding them is left as an exercise to the reader.

Implementation
--------------

[](#implementation)

This implementation is meant to work in the context of ILIAS, where Plugins should be able to define components for `ilObjects`. This library therefore knows four kinds of objects, where the according interfaces could be found in the base directory of the lib:

- `Entity` provides the basic means to identify an object. That is, an entity needs to be able to provide some comparable id, where objects with the same id are indeed the very same object. This is the thingy known from the pattern.
- A `Component` is the thingy from the pattern that provides information and implementations for a certain subsystem. Since the library doesn't know about these subsystems, the basic interface just provides a method to get to know the entity the component belongs to. This will be one main extension point for this library.
- This library should be able to work in the context of `ilObjects`, plugins and the ILIAS tree. The plugins this framework will be used for are mainly there to enhance the ILIAS Course with different functionality. Plugins then need to be able to extend the course in different directions, thus a notion of sources for components of an entity is required. A `Provider` thus can provide different types of components for a fixed entity.
- All this stuff needs to be tied together, that is what the `Repository` does. It is the source to query for `Providers` and `Components`.

A simple implementation (without ILIAS) can be found in `src/Simple`. It defines two Components `AttachInt` and `AttachString` that both have one `*Memory`implementation.

An ILIAS based implementation can be found in `src/ILIAS`. It contains two more noteworthy objects, that act as a plumbing between the simple model presented above and the factual ILIAS world.

- The `UnboundProvider` accounts for the fact, that ILIAS repository objects can actually have different locations in the tree. An object providing components could thus provide for different branches of the tree. To still allow for some common machinery to store and load providers, repository objects need a way to talk about their possibilities to provide components without actually knowing which entity they are bound to.
- The `ProviderDB` is that common machinery to store and load providers. Objects providing components must create `UnboundProviders` via that object. The ILIAS implementation of the model then uses the tree to turn the `UnboundProviders`to real providers for the objects in the tree.

The usage of both facilities is showcased in two examples.

Example
-------

[](#example)

The `example` folder contains two plugins, one that provides a component, one that uses handles the provided component. Note that both plugins do not know each other. Their common denominator is this library and the `AttachString` component they both use. Both plugins try to showcase this framework only and are no good showcases for general plugin development!

The `AttachString` component is a very dumb component that allows to attach a string to an entity. We most probably won't use such a simple component in a real world problem.

To check out what the plugins are doing, copy both of them to the directory for RepositoryPlugins in an ilias installation, `composer install` them and activate them within ILIAS. You should be provided with two new types of repo objects: `Component Handler Example` and `Component Provider Example`. Create a course and an object for each plugin within the course.

First open the Provider-object. You should get a simple form where you can add multiple strings the object will provide via the `AttachString` component. Do that now (and don't forget to save the form). Then open the Handler-object. You should see a simple listing of all strings you added to the provider. You can also add some more providers to the course. The handler will collect the strings from all providers. You could of course also add some more handlers, but they won't differ from your first one.

Now have a look at how the provider object is implemented. One thing the plugin needs to implement is an instance of `UnboundProvider`. This can be found in `example/ComponentProviderExample/classes/UnboundProvider.php`. This class needs to tell which components it intents to provide via `componentTypes` and needs to present a way how instance of these components can be created via `buildComponentsOf`.

The `UnboundProvider` has an `owner`-ilObject, which is used to get the provided strings from the ILIAS-database. The component interface `AttachString` is used for the declaration in `componentTypes`, but `buildComponentOf` uses the in-memory implementation `AttachStringMemory` to create the actual components.

The provider object needs to define when an `UnboundProvider` is actually created and the object starts to provide components for some other object. This is done on creation of the object in `example/ComponentProviderExample/classes/class.ilObjComponentProviderExample.php`. The trait `ilProviderObjectHelper` helps to easily implement that creation. The object needs to provide a DIC via `getDIC` and then may `createUnboundProvider`whenever it needs to. To do that, it needs to tell for which objects on its path it wants to provide components for (`crs` in the example), what the name of the `UnboundProvider` is and where the according implementation can be found. The object also needs to take care that the UnboundProviders it created gets destroyed afterwards, which is done via `deleteUnboundProviders` on object deletion.

The handler object is even simple. In `example/ComponentHandlerExample/classes/class.ilObjComponentHandlerExample.php`you can see the according implementation for the handler. It uses the `ilHandlerObjectHelper`trait and also needs to provide a DIC via `getDIC`. It also needs to provide the `ref_id` of an object it intends to handle components for. We just use the parent in the example. It then can use `getComponentsOfType` to get all components provided for its object and do further processing on them.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity25

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 87.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~18 days

Recently: every ~1 days

Total

19

Last Release

2867d ago

Major Versions

1.0.2 → 2.0.02017-10-17

2.1.2 → 3.0.02018-01-15

3.3.4 → 4.0.02018-08-23

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/10611082?v=4)[Richard Klees](/maintainers/klees)[@klees](https://github.com/klees)

![](https://avatars.githubusercontent.com/u/3328364?v=4)[Nils Haagen](/maintainers/nhaagen)[@nhaagen](https://github.com/nhaagen)

![](https://avatars.githubusercontent.com/u/12557020?v=4)[Stefan Hecken](/maintainers/shecken)[@shecken](https://github.com/shecken)

![](https://avatars.githubusercontent.com/u/22291200?v=4)[Daniel Weise](/maintainers/daniwe4)[@daniwe4](https://github.com/daniwe4)

---

Top Contributors

[![klees](https://avatars.githubusercontent.com/u/10611082?v=4)](https://github.com/klees "klees (191 commits)")[![nhaagen](https://avatars.githubusercontent.com/u/3328364?v=4)](https://github.com/nhaagen "nhaagen (16 commits)")[![daniwe4](https://avatars.githubusercontent.com/u/22291200?v=4)](https://github.com/daniwe4 "daniwe4 (6 commits)")[![shecken](https://avatars.githubusercontent.com/u/12557020?v=4)](https://github.com/shecken "shecken (5 commits)")

---

Tags

entity-componentlib

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/conceptsandtraining-ente/health.svg)

```
[![Health](https://phpackages.com/badges/conceptsandtraining-ente/health.svg)](https://phpackages.com/packages/conceptsandtraining-ente)
```

###  Alternatives

[laravel/socialite

Laravel wrapper around OAuth 1 &amp; OAuth 2 libraries.

5.7k104.3M836](/packages/laravel-socialite)[laravel/dusk

Laravel Dusk provides simple end-to-end testing and browser automation.

1.9k38.6M289](/packages/laravel-dusk)[nineinchnick/edatatables

Grid widget for the Yii Framework, wrapper for the DataTables jQuery plugin

173.2k](/packages/nineinchnick-edatatables)[link-cloud/fast-hyperf

LinkCloud Fast Hyperf

241.2k1](/packages/link-cloud-fast-hyperf)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
