PHPackages                             amcgowanca/discoverable\_entity\_bundle\_classes - 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. amcgowanca/discoverable\_entity\_bundle\_classes

ActiveDrupal-module

amcgowanca/discoverable\_entity\_bundle\_classes
================================================

An experimental approach for implementing entity classes for specific bundles.

1.0.3(7y ago)15106.8k↓37.5%7[5 PRs](https://github.com/amcgowanca/discoverable_entity_bundle_classes/pulls)GPL-2.0+PHP

Since Sep 4Pushed 4y ago1 watchersCompare

[ Source](https://github.com/amcgowanca/discoverable_entity_bundle_classes)[ Packagist](https://packagist.org/packages/amcgowanca/discoverable_entity_bundle_classes)[ RSS](/packages/amcgowanca-discoverable-entity-bundle-classes/feed)WikiDiscussions 9.x-2.x Synced 1mo ago

READMEChangelog (6)Dependencies (1)Versions (12)Used By (0)

Discoverable Entity Bundle Classes
----------------------------------

[](#discoverable-entity-bundle-classes)

Currently in Drupal 8, there is *no* mechanism for deriving a base entity type's class implementation with a unique class type on a per-bundle basis. As a result, if overriding the entity type class, that class type will be used for all instances in which that entity is instantiated as.

This module is also referred to as "DEBC", short for "Discoverable Entity Bundle Classes".

### Installation &amp; usage

[](#installation--usage)

##### Installation via Composer

[](#installation-via-composer)

This module should be installed through use of Composer.

```
$ composer require amcgowanca/discoverable_entity_bundle_classes:^1.0

```

##### Usage

[](#usage)

Discoverable Entity Bundle Classes module does not provide any "out of the box" ready setup or configuration and is focused on enhancing the developer experience of building elegant solutions. As a result, the following is required:

1. Ensure that the entity storage class for the entity type which you would like entity bundle classes made available for implements the trait `Drupal\discoverable_entity_bundle_classes\Storage\SqlContentEntityStorageTrait`. This trait's implementation is focused on ensuring that the needed `SqlContentEntityStorage` class methods from Drupal core are effectively overridden to allow for discoverable bundle classes and their instantiation.

    Note that this module provides the required Storage class representations for Drupal core's Node, Comment and Taxonomy term entities but does not activate them. *This* is purposefully left for the technical architect of the implementing project to decide. See #2 below.
2. If the entity type (e.g. Node) is being provided via a Drupal core or contributed module package, ensure that a storage class exists or is made available that implements the required `SqlContentEntityStorageTrait` trait. Override the entity type's storage class through use of `hook_entity_type_alter(&$entity_types)`.

    ```
    /**
     * Implements hook_entity_type_alter(&$entity_types)
     */
    function my_module_entity_type_alter(&$entity_types) {
      /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
      if (isset($entity_types['node'])) {
        $entity_types['node']->setStorageClass('\Drupal\discoverable_entity_bundle_classes\Storage\Node\NodeStorage');
      }
    }
    ```
3. Define custom entity bundle classes (e.g. Article) which extends the previously defined base entity class. For example, if Article is a type of Node, then it should be defined as:

    ```
    namespace Drupal\my_module\Entity;

    use Drupal\node\Entity\Node;

    class Article extends Node implements ArticleInterface {

      ...

    }
    ```
4. Any bundle specific class **must** also implement the interface, `ContentEntityBundleInterface`.

    ```
    namespace Drupal\my_module\Entity;

    use Drupal\node\Entity\Node;
    use Drupal\discoverable_entity_bundle_classes\ContentEntityBundleInterface;

    class Article extends Node implements ArticleInterface, ContentEntityBundleInterface {

      ...

    }
    ```
5. The bundle specific class **must** also be annotated with `@ContentEntityBundleClass` which defines the following properties:

    - `label`: Human-readable representation of the entity bundle class (e.g. `@Translation("Article")`)
    - `entity_type`: The base entity type (e.g. `node`).
    - `bundle`: The entity bundle that this class should be applied to.

    ```
    namespace Drupal\my_module\Entity;

    use Drupal\node\Entity\Node;
    use Drupal\discoverable_entity_bundle_classes\ContentEntityBundleInterface;

    /**
     * Defines an Article node class.
     *
     * @ContentEntityBundleClass(
     *   label = @Translation("Article"),
     *   entity_type = "node",
     *   bundle = "article"
     * );
     */
    class Article extends Node implements ArticleInterface, ContentEntityBundleInterface {

      ...

    }
    ```
6. *Finally*, clear cache (`drush @site.alias cache-rebuild`) and begin creating awesome Drupal solutions.

### History of this project

[](#history-of-this-project)

##### The beginning

[](#the-beginning)

***This*** module and architectural approach was originally conceived for a global brand. The intent was to allow for a simple proof of concept that enables the ability to derive entity classes (e.g. `\Drupal\node\Entity\Node`) for specialized implementations. The goal was to allow for a layer of abstraction and decoupling of common Drupal-isms to implement a services and other data managers to act purely on defined interfaces *instead of* Drupal's data representation.

##### Fast-forward +1 year

[](#fast-forward-1-year)

***This*** module has been utilized on regular basis for small non-profit organizations through to Fortune 100s by enabling delivery teams to build elegant software that is removed from the tightly coupled behaviors of common Drupal implementations.

##### On Drupal.org

[](#on-drupalorg)

Below are links to Drupal.org issues which reference this particular project *and/or* that this project addresses as part of its architecture.

-

### Real-life example(s)

[](#real-life-examples)

Its is not uncommon, in fact, it is **very** common to have projects be overwhelmed with Drupal-isms that appear easy-to-manage early on within a project's development cycle but become very unmanageable as time goes on - let alone after its first production release.

#### Making multiple data-points "Locationable"

[](#making-multiple-data-points-locationable)

**The scenario:** A single project has multiple data types - a Node type *and* Vocabulary, that represented a singular "Location". Due to the duplicative nature, the Vocabulary's implementation existed from the original delivery team and was simply used for the purpose of categorization content. The Node type "Location" was an after thought and therefore was implemented for the purpose of:

- representing a location "page" used for content creation purposes,
- (future needs) categorization of *new* content types and *eventually* historical implementations, for building relational content models.

**The problem:** How do I sustain the large codebase without introducing large levels of effort to introduce or eventually remove the data types while persisting functional business logic.

**The answer:** Through a well abstraction between data types (e.g. a Node *or* Vocabulary) and services or other class implementations that make use of strongly-typed parameters.

**The observed changes:** With minimal refactoring of core business logic and class implementations, this particular project was able to reduce the number of *Drupal-isms* by leveraging DEBC and well-defined interfaces that were implemented by entity bundle classes.

An example of code reduction and type-hinted values, allowed for:

*Before*:

[![Example of the 'before' for a location class that had its Drupal-isms reduced](./docs/assets/example-1--location-before.png)](./docs/assets/example-1--location-before.png)

*After*:

[![Example of the 'after' for a location class that had its Drupal-isms reduced](./docs/assets/example-1--location-after.png)](./docs/assets/example-1--location-after.png)

### License

[](#license)

This Drupal module is licensed under the [GNU General Public License](./LICENSE.md) version 2.

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity39

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity70

Established project with proven stability

 Bus Factor1

Top contributor holds 87.5% 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 ~180 days

Total

4

Last Release

2638d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/611e78e95ac720d290f97d7df2c279c0c3a703f22caae1114b7885d503844b36?d=identicon)[amcgowanca](/maintainers/amcgowanca)

---

Top Contributors

[![amcgowanca](https://avatars.githubusercontent.com/u/316512?v=4)](https://github.com/amcgowanca "amcgowanca (21 commits)")[![timodwhit](https://avatars.githubusercontent.com/u/2761203?v=4)](https://github.com/timodwhit "timodwhit (2 commits)")[![douggreen](https://avatars.githubusercontent.com/u/1244341?v=4)](https://github.com/douggreen "douggreen (1 commits)")

### Embed Badge

![Health badge](/badges/amcgowanca-discoverable-entity-bundle-classes/health.svg)

```
[![Health](https://phpackages.com/badges/amcgowanca-discoverable-entity-bundle-classes/health.svg)](https://phpackages.com/packages/amcgowanca-discoverable-entity-bundle-classes)
```

PHPackages © 2026

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