PHPackages                             survos/atlas-bundle - 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. survos/atlas-bundle

ActiveSymfony-bundle[Utility &amp; Helpers](/categories/utility)

survos/atlas-bundle
===================

Compile-time discovery of controllers, routes, and entities — the atlas the rest of survos draws maps from.

2.7.2(4w ago)0171↑108.3%1MITPHPPHP ^8.4

Since May 3Pushed 2d agoCompare

[ Source](https://github.com/survos/atlas-bundle)[ Packagist](https://packagist.org/packages/survos/atlas-bundle)[ GitHub Sponsors](https://github.com/kbond)[ RSS](/packages/survos-atlas-bundle/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (27)Versions (31)Used By (1)

Atlas Bundle
============

[](#atlas-bundle)

Compile-time discovery of controllers, routes, and entities — the atlas the rest of survos draws maps from.

```
composer require survos/atlas-bundle
```

What it does
------------

[](#what-it-does)

At compile time, it walks:

1. **Controllers** — every service tagged `container.service_subscriber` (the Symfony default for `AbstractController` subclasses), recording one `RouteEntry` per `#[Route]` method along with every other attribute on the method and class.
2. **Entities** — directories from `doctrine.orm.mappings` plus `src/Entity` plus each registered bundle's `Entity/` subdir, recording one `EntityEntry` per concrete class with its class-level attributes.

The result is exposed as a runtime `Atlas` service. Atlas does not interpret attributes — it records them. Bundles like [`survos/field-bundle`](#see-also) layer domain meaning (`#[EntityMeta]`, `#[RouteMeta]`, …) on top.

How attributes are stored — the `{class, args}` shape
-----------------------------------------------------

[](#how-attributes-are-stored--the-class-args-shape)

Attribute payloads are kept as plain arrays, not instantiated objects:

```
[
    'class' => 'App\Attribute\PublicApi',
    'args'  => ['version' => 2, 'description' => 'Public list endpoint'],
]
```

`args` is exactly what `ReflectionAttribute::getArguments()` returned: positional values keyed by integer, named values keyed by string name.

This shape has three properties worth keeping in mind:

- **Trivially serializable.** `atlas:export` is a one-line `json_encode` because there are no objects to coerce.
- **Resilient.** A renamed or removed attribute class will not break the Atlas; only consumers that explicitly look for that FQCN are affected.
- **Composable.** Multiple bundles can read the same `RouteEntry` and each pull out the attributes they care about, without any of them needing to instantiate the others' classes.

To turn a stored entry back into a real attribute object, unpack the args:

```
foreach ($route->attributesOf(\App\Attribute\PublicApi::class) as $hit) {
    $attr = new \App\Attribute\PublicApi(...$hit['args']);
}
```

PHP's named-argument unpacking handles mixed positional/named args correctly, so this works whether the attribute was written as `#[PublicApi(2)]` or `#[PublicApi(version: 2)]`.

Using the Atlas at runtime
--------------------------

[](#using-the-atlas-at-runtime)

```
use Survos\AtlasBundle\Service\Atlas;

final class MyService
{
    public function __construct(private readonly Atlas $atlas) {}

    public function example(): void
    {
        foreach ($this->atlas->routes() as $route) {
            // $route->name, $route->path, $route->methodAttributes, ...
        }

        $hits = $this->atlas->routesWithAttribute(\App\Attribute\PublicApi::class);
    }
}
```

Using the builders inside your own compiler pass
------------------------------------------------

[](#using-the-builders-inside-your-own-compiler-pass)

```
use Survos\AtlasBundle\Compiler\ControllerAtlasBuilder;
use Survos\AtlasBundle\Compiler\EntityAtlasBuilder;

final class MyBundlePass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container): void
    {
        foreach (ControllerAtlasBuilder::build($container) as $route) {
            foreach ($route->attributesOf(\App\Attribute\Foo::class) as $hit) {
                // $hit['args'] holds the original attribute arguments
            }
        }

        foreach (EntityAtlasBuilder::build($container, extraDirs: ['/path/to/extra']) as $entity) {
            // ...
        }
    }
}
```

The builders are pure helpers — no service registration, no runtime cost when called from a compile pass.

Console
-------

[](#console)

```
bin/console atlas:export                    # JSON to stdout
bin/console atlas:export --pretty           # pretty JSON
bin/console atlas:export -f yaml            # YAML
bin/console atlas:export -o atlas.json      # write to file
```

The output is the natural shape to paste into an LLM conversation when you want to ask design questions about your application's surface area.

Conventions
-----------

[](#conventions)

- A `#[Route]` without an explicit `name:` is skipped. Atlas needs a stable identifier and won't guess.
- Multiple `#[Route]` attributes on the same method each produce their own `RouteEntry`.
- Entity discovery skips abstract classes, interfaces, and traits.

Which attributes get recorded
-----------------------------

[](#which-attributes-get-recorded)

Atlas is opinionated. Only attributes whose class FQCN starts with one of these prefixes are captured:

- `Survos\` — every survos attribute (RouteMeta, EntityMeta, RouteIdentity, Field, MeiliIndex, Facet, …)
- `Symfony\Component\Routing\Attribute\` — `#[Route]`
- `Symfony\Component\Security\Http\Attribute\` — `#[IsGranted]`
- `Symfony\Bridge\Twig\Attribute\` — `#[Template]`
- `App\Attribute\` — your own attributes

Anything else — most importantly **ApiPlatform's `#[ApiResource]` and friends** — is silently filtered out. ApiPlatform's attribute universe is huge and deeply nested; analyzing it belongs in `survos/inspection-bundle`, not here. Atlas's scope is "metadata that drives survos features," not "every attribute on every method."

If you genuinely need wider coverage, pass extra prefixes to `AttributeFilter::accepts($fqcn, $extraNamespaces)` from your own builder call — but reconsider the layering first.

See also
--------

[](#see-also)

Atlas is intentionally low-level — it records what's there. If you want **opinionated metadata attributes** with semantic helpers on top, install [`survos/field-bundle`](https://packagist.org/packages/survos/field-bundle):

```
composer require survos/field-bundle
```

field-bundle defines:

- `#[EntityMeta]` — class-level metadata for admin UI, dashboards, menu auto-registration (icon, group, label, …)
- `#[RouteMeta]` *(in progress)* — method-level metadata for sitemap inclusion, AI introspection, breadcrumb construction, …

Both are discovered through Atlas, and field-bundle ships richer registries (`EntityMetaRegistry`, `RouteMetaRegistry`) plus an enriched `meta:export` command that joins entities and routes into a single graph. Use Atlas directly when you have your own attribute vocabulary; reach for field-bundle when its vocabulary is what you'd be inventing.

###  Health Score

49

—

FairBetter than 94% of packages

Maintenance98

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity62

Established project with proven stability

 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

Every ~0 days

Total

30

Last Release

28d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/21b39551f92ed4143772c622f9e571589c5a72c96ab3c53fe67489ce0d83e806?d=identicon)[tacman1123](/maintainers/tacman1123)

---

Top Contributors

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

---

Tags

symfonyroutesdiscoveryattributesatlasentitiesregistrycompile-time

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/survos-atlas-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/survos-atlas-bundle/health.svg)](https://phpackages.com/packages/survos-atlas-bundle)
```

###  Alternatives

[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M195](/packages/sulu-sulu)[open-dxp/opendxp

Content &amp; Product Management Framework (CMS/PIM)

9017.2k55](/packages/open-dxp-opendxp)

PHPackages © 2026

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