PHPackages                             blackcube/magic-compose - 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. blackcube/magic-compose

ActiveLibrary

blackcube/magic-compose
=======================

Simple solution for magic methods and method composition using attributes

1.0.0(1mo ago)026↓100%1BSD-3-ClausePHPPHP ^8.0

Since Mar 21Pushed 1mo agoCompare

[ Source](https://github.com/blackcubeio/magic-compose)[ Packagist](https://packagist.org/packages/blackcube/magic-compose)[ Docs](https://github.com/blackcubeio/magic-compose)[ RSS](/packages/blackcube-magic-compose/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (13)Versions (3)Used By (1)

Blackcube Magic Compose
=======================

[](#blackcube-magic-compose)

> **⚠️ Blackcube Warning**
>
> PHP says one `__get` per class. Blackcube says no.
>
> Multiple traits, each with their own magic handlers, dispatched by priority via attributes. It's not a hack — it's composition where PHP forgot to provide it.

Simple solution for magic methods and method composition using attributes.

[![License](https://camo.githubusercontent.com/6cb285b57819f8de0acfb34923298f4f569f962544e8fe35331da2d163f4e485/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4253442d2d332d2d436c617573652d626c75652e737667)](LICENSE.md)[![Packagist Version](https://camo.githubusercontent.com/9a1097702a2dd7af39afa1b08184cc2204badcf1d042ffe7e31d5f83d5c8b3db/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f626c61636b637562652f6d616769632d636f6d706f73652e737667)](https://packagist.org/packages/blackcube/magic-compose)[![Warning](https://camo.githubusercontent.com/f6bc4777f4b5c33df3e4f07b00623d3231016d0291e5ce1bf40b0dc084c71145/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f426c61636b637562652d5761726e696e672d6f72616e6765)](BLACKCUBE_WARNING.md)

Installation
------------

[](#installation)

```
composer require blackcube/magic-compose
```

Problem
-------

[](#problem)

PHP traits can't compose magic methods. When multiple traits define `__get`, only one wins:

```
class MyClass {
    use TraitA, TraitB; // TraitB::__get shadows TraitA::__get
}
```

Solution
--------

[](#solution)

Mark handlers with attributes, let `MagicComposeTrait` dispatch:

```
class MyClass {
    use MagicComposeTrait, TraitA, TraitB;
}

trait TraitA {
    #[MagicGetter]
    protected function getFromA(string $name): mixed {
        if ($name === 'foo') return 'from A';
        throw new MagicNotHandledException();
    }
}

trait TraitB {
    #[MagicGetter(priority: Priority::HIGH)]
    protected function getFromB(string $name): mixed {
        if ($name === 'bar') return 'from B';
        throw new MagicNotHandledException();
    }
}

$obj = new MyClass();
$obj->foo; // 'from A'
$obj->bar; // 'from B'
```

Attributes
----------

[](#attributes)

AttributeMagic methodHandler signature`#[MagicGetter]``__get``(string $name): mixed``#[MagicSetter]``__set``(string $name, mixed $value): void``#[MagicIsset]``__isset``(string $name): bool``#[MagicUnset]``__unset``(string $name): void``#[MagicCall]``__call``(string $name, array $arguments): mixed`Priority
--------

[](#priority)

Handlers are sorted by priority (highest first):

```
use Blackcube\MagicCompose\Attributes\Priority;

#[MagicGetter(priority: Priority::HIGH)]  // 90 - runs first
#[MagicGetter(priority: Priority::NORMAL)] // 50 - default
#[MagicGetter(priority: Priority::LOW)]    // 10 - runs last
```

Constants: `CRITICAL` (100), `HIGH` (90), `NORMAL` (50), `LOW` (10).

MagicExtend
-----------

[](#magicextend)

Intercept parent class methods with chainable `$this->next()`:

```
trait AuditTrait {
    use MagicComposeMethodsBaseTrait;

    #[MagicExtend(method: 'save')]
    protected function auditSave(): bool {
        $this->log('before save');
        $result = $this->next(); // call parent::save() or next handler
        $this->log('after save');
        return $result;
    }
}
```

ActiveRecord Integration
------------------------

[](#activerecord-integration)

For Yii ActiveRecord, use `MagicComposeActiveRecordTrait`:

```
use Yiisoft\ActiveRecord\ActiveRecord;
use Blackcube\MagicCompose\MagicComposeActiveRecordTrait;

class User extends ActiveRecord {
    use MagicComposeActiveRecordTrait;
    use SomeCustomTrait;
}
```

Pre-wired methods: `propertyValuesInternal`, `refreshInternal`, `populateProperty`, `deleteInternal`, `populateRecord`.

Handler Flow
------------

[](#handler-flow)

1. Handlers discovered via reflection (cached)
2. Sorted by priority DESC
3. First handler that doesn't throw `MagicNotHandledException` wins
4. If all throw → fallback to parent or PHP error

License
-------

[](#license)

BSD-3-Clause. See [LICENSE.md](LICENSE.md).

Author
------

[](#author)

Philippe Gaultier

###  Health Score

40

—

FairBetter than 87% of packages

Maintenance97

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

48d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/545714?v=4)[pgaultier](/maintainers/pgaultier)[@pgaultier](https://github.com/pgaultier)

---

Top Contributors

[![pgaultier](https://avatars.githubusercontent.com/u/545714?v=4)](https://github.com/pgaultier "pgaultier (2 commits)")

---

Tags

eventstraitscompositionphp-attributesmagic methodsgetter settermagic-propertiesmethod-composition

###  Code Quality

TestsCodeception

### Embed Badge

![Health badge](/badges/blackcube-magic-compose/health.svg)

```
[![Health](https://phpackages.com/badges/blackcube-magic-compose/health.svg)](https://phpackages.com/packages/blackcube-magic-compose)
```

###  Alternatives

[doctrine/event-manager

The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.

6.1k501.1M114](/packages/doctrine-event-manager)[psr/event-dispatcher

Standard interfaces for event handling.

2.3k618.8M862](/packages/psr-event-dispatcher)[pusher/pusher-php-server

Library for interacting with the Pusher REST API

1.5k94.8M290](/packages/pusher-pusher-php-server)[laminas/laminas-eventmanager

Trigger and listen to events within a PHP application

1.0k69.8M225](/packages/laminas-laminas-eventmanager)[simshaun/recurr

PHP library for working with recurrence rules

1.6k15.7M40](/packages/simshaun-recurr)[league/pipeline

A plug and play pipeline implementation.

1.0k16.0M74](/packages/league-pipeline)

PHPackages © 2026

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