It is my fervent wish that this file guide every AI coding agent working with code in this repository.
Any distilled, agent-facing documentation for this package - how it works
internally and the rationale behind key design decisions - lives in docs/.
Consult it before non-trivial changes; it is the source of truth from which the
public manual is distilled.
Five small files, but a genuinely tricky core (tree + monitoring + lookup +
cloning). Almost all the value is in the monitor walks (Component::attachMonitors
/ detachMonitors) and the cloning handshake - read docs/internals.md before
touching them.
docs/upgrading.md records, per released version, every change visible to
users of the package (renames, removals, deprecations, signatures, behavior,
configuration), each with its commit hash; internal changes are not in it. It
is the place to look up the history of a public symbol. Do not write to it; it
is extended at release time from the git history.
nette/component-model is the foundational component architecture for the Nette Framework: a hierarchical system where components nest inside containers, are monitored for attach/detach events, and are addressed through a path-based lookup. Consumed by Forms and Application, not usually used directly.
- PHP Version: 8.3 - 8.6
- Package:
nette/component-model
# Run all tests
composer tester # or: vendor/bin/tester tests -s
# Run a single test file
php tests/ComponentModel/Container.getComponentTree.phpt
# Static analysis (PHPStan level 8)
composer phpstan- Every file starts with
declare(strict_types=1);; the coding style is checked by DressCode (dresscode.neon). - Tests are Nette Tester
.phptfiles; they usually define minimal component classes inline.
- Monitoring is a single-pass, live-mutation-safe walk with a precise order:
attachedfires top-down (ancestor→descendant),detachedfires bottom-up, and detach is depth-gated. The handler registry ($monitors), the depth each type was notified about ($attachedDepths, updated before the handlers run) and the lookup cache ($lookups, dropped for the whole subtree on every parent change) are kept apart. A throwing listener vetoes the change. This is the sharp edge - seedocs/internals.mdand the ADR it references before changing it. - Cloning re-homes children via a cross-instance handshake (the private
Component::$cloning, written byContainer::__clone), not a parameter. Standalone-cloning a child detaches it. - A component name cannot contain
-(#^[a-zA-Z0-9_]+$#) because-is the path separator;getComponent('a-b-c')descends into sub-containers. - Components cannot be serialized (
__serializethrows by design). getComponent()return-type inference lives innette/phpstan-rules(GetComponentReturnTypeExtension), not in phpDoc here - look there for types.