PHPackages                             locomotivemtl/charcoal-object - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. locomotivemtl/charcoal-object

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

locomotivemtl/charcoal-object
=============================

Object (Content and UserData) definition and object behaviors and tools.

0.8.1(2y ago)015.2k7MITPHPPHP ^7.3 || ^8.0CI failing

Since Jan 19Pushed 2y ago11 watchersCompare

[ Source](https://github.com/locomotivemtl/charcoal-object)[ Packagist](https://packagist.org/packages/locomotivemtl/charcoal-object)[ RSS](/packages/locomotivemtl-charcoal-object/feed)WikiDiscussions master Synced today

READMEChangelog (10)Dependencies (11)Versions (44)Used By (7)

Charcoal Object
===============

[](#charcoal-object)

Object definition (Content and UserData), behaviors and tools.

Table of content
================

[](#table-of-content)

- [How to install](#how-to-install)
    - [Dependencies](#dependencies)
- [The Charcoal Object](#the-charcoal-object)
    - [Basic classes](#basic-classes)
        - [Content](#content)
        - [UserData](#userdata)
    - [Object behaviors](#object-behaviors)
        - [Archivable](#archivable)
        - [Categorizable](#categorizable)
        - [Category](#category)
        - [Hierarchical](#hierarchical)
        - [Publishable](#publishable)
        - [Revisionable](#revisionable)
        - [Routable](#routable)
    - [Helpers](#helpers)
        - [ObjectDraft](#objectdraft)
        - [ObjectRevision](#objectrevision)
        - [ObjectSchedule](#objectschedule)
- [Development](#development)
    - [Development dependencies](#development-dependencies)
    - [Continuous Integration](#continuous-integration)
    - [Coding Style](#coding-style)
    - [Authors](#authors)
    - [Changelog](#changelog)

How to install
==============

[](#how-to-install)

The preferred (and only supported) way of installing *charcoal-object* is with **composer**:

```
★ composer require locomotivemtl/charcoal-object
```

Dependencies
------------

[](#dependencies)

- PHP 5.6+
    - This is the last supported version of PHP.
    - `PHP 7` is also supported (meaning *green on travis*…).

The Charcoal Object
===================

[](#the-charcoal-object)

The `\Charcoal\Object` namespace provides a bunch of basic classes, helpers as well as object behaviors (interfaces + traits).

Basic classes
-------------

[](#basic-classes)

All charcoal project object classes should extend one of the 2 base classes, [`\Charcoal\Object\Content`](#content), for data created and managed by administrators or [`\Charcoal\Object\UserData`](#userdata), for data created from clients / users.

### Content

[](#content)

The **Content** base class should be used for all objects which can be "managed". Typically by an administrator, via the `charcoal-admin` module. It adds the "active" flag to objects as well as creation and modification informations.

**API**

- ` setActive($active)`
- `active()`
- `setPosition($position)`
- `position()`
- `setCreated($created)`
- `created()`
- `setCreatedBy($createdBy)`
- `createdBy()`
- `setLastModified($lastModified)`
- `lastModified()`
- `setLastModifiedBy($lastModifiedBy)`
- `lastModifiedBy()`

> The `Content` class extends `\Charcoal\Model\AbstractModel` from the `charcoal-core` module, which means that it also inherits its API as well as the `DescribableInterface` (`metadata()`, `setMetadata()` and `loadMetadata()`, amongst others) and the `StorableInterface` (`id()`, `key()`, `save()`, `update()`, `delete()`, `load()`, `loadFrom()`, `loadFromQuery()`, `source()` and `setSource()`, amongst others).
>
> The `AbstractModel` class extends `\Charcoal\Config\AbstractEntity` which also defines basic data-access methods (`setData()`, `data()`, `keys()`, `has()`, `get()`, `set()`, plus the `ArrayAccess`, `JsonSerializable` and `Serializable` interfaces).

**Properties (metadata)**

PropertyTypeDefaultDescription**active**`boolean``true`…**position**`number``null`…**created**`date-time``null` \[1\]…**created\_by**`string``''` \[1\]…**last\_modified**`date-time``null` \[2\]…**last\_modified\_by**`string``''` \[2\]…\[1\] Auto-generated upon `save()`
\[2\] Auto-generated upon `update()`

> Default metadata is defined in `metadata/charcoal/object/content.json`

### UserData

[](#userdata)

The **UserData** class should be used for all objects that are expected to be entered from the project's "client" or "end user".

**API**

- `setIp($ip)`
- `ip()`
- `setTs($ts)`
- `ts()`
- `setLang($lang)`
- `lang()`

> The `Content` class extends `\Charcoal\Model\AbstractModel` from the `charcoal-core` module, which means that it also inherits its API as well as the `DescribableInterface` (`metadata()`, `setMetadata()` and `loadMetadata()`, amongst others) and the `StorableInterface` (`id()`, `key()`, `save()`, `update()`, `delete()`, `load()`, `loadFrom()`, `loadFromQuery()`, `source()` and `setSource()`, amongst others).
>
> The `AbstractModel` class extends `\Charcoal\Config\AbstractEntity` which also defines basic data-access methods (`setData()`, `data()`, `keys()`, `has()`, `get()`, `set()`, plus the `ArrayAccess`, `JsonSerializable` and `Serializable` interfaces).

**Properties (metadata)**

PropertyTypeDefaultDescription**ip**`ip``null` \[1\]…**ts**`date-time``null` \[1\]…**lang**`lang``null` \[1\]…\[1\] Auto-generated upon `save()` and `update()`

> Default metadata is defined in `metadata/charcoal/object/user-data.json`

Object behaviors
----------------

[](#object-behaviors)

- [Archivable](#archivable)
- [Categorizable](#categorizable)
- [Category](#category)
- [Hierarchical](#hierarchical)
- [Publishable](#publishable)
- [Revisionable](#revisionable)
- [Routable](#routable)

### Archivable

[](#archivable)

*The archivable behavior is not yet documented. It is still under heavy development.*

### Categorizable

[](#categorizable)

**API**

- `setCategory($category)`
- `category()`
- `setCategoryType($type)`
- `categoryType()`

**Properties (metadata)**

PropertyTypeDefaultDescription**category**`object``null`The object's category.\[1\]\[1\] The category `obj_type` must be explicitely set in implementation's metadata.

> Default metadata is defined in `metadata/charcoal/object/catgorizable-interface.json`

### Category

[](#category)

**API**

- `setCategoryItemType($type)`
- `categoryItemType()`
- `numCategoryItems()`
- `hasCategoryItems()`
- `categoryItems()`

**Properties (metadata)**

PropertyTypeDefaultDescription**category\_item**`string``null`…> Default metadata is defined in `metadata/charcoal/object/catgory-interface.json`

### Hierarchical

[](#hierarchical)

**API**

- `hasMaster()`
- `isTopLevel()`
- `isLastLevel()`
- `hierarchyLevel()`
- `master()`
- `toplevelMaster()`
- `hierarchy()`
- `invertedHierarchy()`
- `isMasterOf($child)`
- `recursiveIsMasterOf($child)`
- `hasChildren()`
- `numChildren()`
- `recursiveNumChildren()`
- `children()`
- `isChildOf($master)`
- `recursiveIsChildOf($master)`
- `hasSiblings()`
- `numSiblings()`
- `siblings()`
- `isSiblingOf($sibling)`

**Properties (metadata)**

PropertyTypeDefaultDescription**master**`object``null`The master object (parent in hierarchy).> Default metadata is defined in `metadata/charcoal/object/hierarchical-interface.json`.

### Publishable

[](#publishable)

- `setPublishDate($publishDate)`
- `publishDate()`
- `setExpiryDate($expiryDate)`
- `expiryDate()`
- `setPublishStatus($status)`
- `publishStatus()`
- `isPublished()`

**Properties (metadata)**

PropertyTypeDefaultDescription**publishDate**`date-time``null`…**expiryDate**`date-time``null`…**publishStatus**`string` \[1\]`'draft'`…> Default metadata is defined in `metadata/charcoal/object/publishable-interface.json`.

### Revisionable

[](#revisionable)

Revisionable objects implement `\Charcoal\Object\Revision\RevisionableInterface`, which can be easily implemented by using `\Charcoal\Object\Revision\RevisionableTrait`.

Revisionable objects create *revisions* which logs the changes between an object's versions, as *diffs*.

**API**

- `setRevisionEnabled(bool$enabled)`
- `revisionEnabled()`
- `revisionObject()`
- `generateRevision()`
- `latestRevision()`
- `revisionNum(integer $revNum)`
- `allRevisions(callable $callback = null)`
- `revertToRevision(integer $revNum)`

**Properties (metadata)**

*The revisionable behavior does not implement any properties as all logic &amp; data is self-contained in the revisions.*

### Routable

[](#routable)

*The routable behavior is not yet documented. It is still under heavy development.*

Helpers
-------

[](#helpers)

### ObjectDraft

[](#objectdraft)

…

### ObjectRevision

[](#objectrevision)

Upon every `update` in *storage*, a revisionable object creates a new *revision* (a `\Charcoal\Object\ObjectRevision` instance) which holds logs the changes (*diff*) between versions of an object:

**Revision properties**

PropertyTypeDefaultDescription**target\_type**`string``null`The object type of the target object.**target\_id**`string``null`The object idenfiier of the target object.**rev\_num**`integer``null`Revision number, (auto-generated).**ref\_ts**`date-time`**rev\_user**`string``null`**data\_prev**`structure`**data\_obj**`structure`**data\_diff**`structure`**Revision methods**

- `createFromObject(RevisionableInterface $obj)`
- `createDiff(array $dataPrev, array $dataObj)`
- `lastObjectRevision(RevisionableInterface $obj)`
- `objectRevisionNum(RevisionableInterface $obj, integer $revNum)`

### ObjetSchedule

[](#objetschedule)

It is possible, (typically from the charcoal admin backend), to create *schedule* (a `\Charcaol\Object\ObjectSchedule` instance) which associate a set of changes to be applied automatically to an object:

**Schedule properties**

PropertyTypeDefaultDescription**target\_type**`string``null`The object type of the target object.**target\_id**`string``null`The object idenfiier of the target object.**scheduled\_date**`date-time``null`**data\_diff**`structure``[]`**processed**`boolean``false`**processed\_date****Schedule methods (API)**

- `process([callable $callback, callable $successCallback,callable $failureCallback])`

> Scheduled actions should be run with a timely cron job. The [charcoal-admin](https://github.com/locomotivemtl/charcoal-admin) module contains a script to run schedules automatically:
>
> ```
> ★ ./vendor/bin/charcoal admin/object/process-schedules`
> ```

Development
===========

[](#development)

To install the development environment:

```
★ composer install --prefer-source
```

To run the scripts (phplint, phpcs and phpunit):

```
★ composer test
```

API documentation
-----------------

[](#api-documentation)

- The auto-generated `phpDocumentor` API documentation is available at
- The auto-generated `apigen` API documentation is available at [https://codedoc.pub/locomotivemtl/charcoal-object/master/](https://codedoc.pub/locomotivemtl/charcoal-object/master/index.html)

Development dependencies
------------------------

[](#development-dependencies)

- `phpunit/phpunit`
- `squizlabs/php_codesniffer`
- `satooshi/php-coveralls`

Continuous Integration
----------------------

[](#continuous-integration)

ServiceBadgeDescription[Travis](https://travis-ci.org/locomotivemtl/charcoal-object)[![Build Status](https://camo.githubusercontent.com/afaf89e3d49543d24ffb913a8049c66df8e9df528c5968551ea06588b0924f61/68747470733a2f2f7472617669732d63692e6f72672f6c6f636f6d6f746976656d746c2f63686172636f616c2d6f626a6563742e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/locomotivemtl/charcoal-object)Runs code sniff check and unit tests. Auto-generates API documentation.[Scrutinizer](https://scrutinizer-ci.com/g/locomotivemtl/charcoal-object/)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/2ce794a41f3f28c465b8d4467ce27f84b7eabd0a25f30e4815333cdf78e0a10f/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6c6f636f6d6f746976656d746c2f63686172636f616c2d6f626a6563742f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/locomotivemtl/charcoal-object/?branch=master)Code quality checker. Also validates API documentation quality.[Coveralls](https://coveralls.io/github/locomotivemtl/charcoal-object)[![Coverage Status](https://camo.githubusercontent.com/ee94afc380ae84ee7220d4a6c85b8f8129492ed5855a8f68cd750af31c7e792f/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6c6f636f6d6f746976656d746c2f63686172636f616c2d6f626a6563742f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/locomotivemtl/charcoal-object?branch=master)Unit Tests code coverage.[Sensiolabs](https://insight.sensiolabs.com/projects/5ef771c49-8c05-448b-a112-069737b380dc)[![SensioLabsInsight](https://camo.githubusercontent.com/db2599008839e02de5b4c05ddeabe6e44bbbe66ae4d0565472a7a6aa0ca84e8f/68747470733a2f2f696e73696768742e73656e73696f6c6162732e636f6d2f70726f6a656374732f65663737316334392d386330352d343438622d613131322d3036393733376233383064632f6d696e692e706e67)](https://insight.sensiolabs.com/projects/ef771c49-8c05-448b-a112-069737b380dc)Another code quality checker, focused on PHP.Coding Style
------------

[](#coding-style)

The charcoal-object module follows the Charcoal coding-style:

- [*PSR-1*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md)
- [*PSR-2*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
- [*PSR-4*](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md), autoloading is therefore provided by *Composer*.
- [*phpDocumentor*](http://phpdoc.org/) comments.
- Read the [phpcs.xml](phpcs.xml) file for all the details on code style.

> Coding style validation / enforcement can be performed with `composer phpcs`. An auto-fixer is also available with `composer phpcbf`.

Authors
=======

[](#authors)

- Mathieu Ducharme,
- Chauncey McAskill
- Locomotive Inc.

License
=======

[](#license)

Charcoal is licensed under the MIT license. See [LICENSE](LICENSE) for details.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity23

Limited adoption so far

Community24

Small or concentrated contributor base

Maturity71

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~65 days

Recently: every ~358 days

Total

40

Last Release

885d ago

PHP version history (3 changes)0.1PHP &gt;=5.6.0

0.5.1PHP &gt;=5.6.0 || &gt;=7.0

0.8.0PHP ^7.3 || ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/cfb071c0ff7ce9500c528a003a2c53124248debc3e5bf367c17f89f5e6136125?d=identicon)[mducharme](/maintainers/mducharme)

---

Top Contributors

[![mcaskill](https://avatars.githubusercontent.com/u/29353?v=4)](https://github.com/mcaskill "mcaskill (44 commits)")[![mducharme](https://avatars.githubusercontent.com/u/12157?v=4)](https://github.com/mducharme "mducharme (41 commits)")[![JoelAlphonso](https://avatars.githubusercontent.com/u/10762266?v=4)](https://github.com/JoelAlphonso "JoelAlphonso (19 commits)")[![dominiclord](https://avatars.githubusercontent.com/u/1775204?v=4)](https://github.com/dominiclord "dominiclord (8 commits)")[![veve40](https://avatars.githubusercontent.com/u/7537381?v=4)](https://github.com/veve40 "veve40 (5 commits)")[![BeneRoch](https://avatars.githubusercontent.com/u/3017380?v=4)](https://github.com/BeneRoch "BeneRoch (4 commits)")[![losted](https://avatars.githubusercontent.com/u/165665?v=4)](https://github.com/losted "losted (2 commits)")

---

Tags

charcoalcontentmodelobjectphprevisionrouteuserdata

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/locomotivemtl-charcoal-object/health.svg)

```
[![Health](https://phpackages.com/badges/locomotivemtl-charcoal-object/health.svg)](https://phpackages.com/packages/locomotivemtl-charcoal-object)
```

###  Alternatives

[symfony/lock

Creates and manages locks, a mechanism to provide exclusive access to a shared resource

514139.2M690](/packages/symfony-lock)[matomo/matomo

Matomo is the leading Free/Libre open analytics platform

21.7k38.9k](/packages/matomo-matomo)[ecotone/ecotone

Enterprise architecture layer for Laravel and Symfony — CQRS, Event Sourcing, Durable Workflows (Sagas, Orchestrators), Projections, and Outbox messaging via PHP attributes.

564576.7k52](/packages/ecotone-ecotone)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

751291.4k43](/packages/civicrm-civicrm-core)[illuminate/broadcasting

The Illuminate Broadcasting package.

7127.2M208](/packages/illuminate-broadcasting)[logiscape/mcp-sdk-php

Model Context Protocol SDK for PHP

368116.8k12](/packages/logiscape-mcp-sdk-php)

PHPackages © 2026

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