Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rad Laravel Package

21torr/rad

RAD Bundle is a Symfony package for rapid application development, bundling commonly used features and 21TORR's opinionated conventions so teams can scaffold and ship applications faster.

View on GitHub
Deep Wiki
Context7

Getting Started

21torr/rad is a Symfony bundle, not a Laravel package. If you're a Laravel developer, the day-one decision is whether you're working in a Symfony codebase at all — there is no service provider, no Eloquent integration, and no Laravel facade. If you are in Symfony, it installs as a normal bundle:

composer require 21torr/rad

Register it in config/bundles.php (the bundle ships a RadBundle class), then confirm the runtime constraints before you plan around it:

  • PHP 8.4+ and Symfony 7 are required as of the 3.4.x line (3.0.1 bumped to PHP 8.3/Symfony 7; 3.4.0 moved to PHP 8.4). Older stacks need older tags.
  • Doctrine ORM is the persistence assumption (v3 is tested).

Where to look first:

  1. The official docs at 21torr-docs.pages.dev/docs/php/symfony/rad — the README is a pointer, not a manual.
  2. The src/ tree by feature area: controllers (BaseController), API (ApiResponse, ApiResponseNormalizer), entities (EntityModel, field traits), request handling (ArgumentBag, ImportData), security (AbilitiesVoter), and helpers (EnumValue, TranslationHelper, InMemoryCache).
  3. The CHANGELOG/releases — with only a handful of stars, release notes are effectively your upgrade guide.

First use case: stand up a JSON endpoint. Extend BaseController, pull a typed service via getService(), load an entity through EntityModel, and return an ApiResponse built with ApiResponseNormalizer::createResponse(). That single vertical slice touches the bundle's most-used pieces and tells you quickly whether its opinions fit your app.

Implementation Patterns

Thin controllers with typed service access. BaseController::getService() exists so PhpStorm and PHPStan know the concrete service type instead of the container's object. Use it rather than reaching into $this->container directly.

final class OrderController extends BaseController
{
    public function show(int $id): ApiResponse
    {
        $model = $this->getService(OrderModel::class);

        return $this->getService(ApiResponseNormalizer::class)
            ->createResponse($model->get($id));
    }
}

Entity models instead of repository sprawl. EntityModel wraps Doctrine persistence behind persist() (a unified add/edit), update(), and refresh(). The pattern is: one model per aggregate, controllers call the model, the model owns EntityManager calls. update() has an option to skip marking the entity as modified — useful when you're hydrating/refreshing and don't want a flush to fire.

Field traits for boilerplate columns. EntityFieldsTrait (id + created timestamp) and ModifiableEntityFieldsTrait (adds modified timestamp) replace the old IdTrait/TimestampsTrait split from v2. IDs are unsigned integers in the database, and timestamps go through the clock rather than new \DateTime() — so tests that freeze time behave.

API responses as a builder, with explicit status codes. ApiResponse is a builder type; the constructor now requires an explicit status code (passing a bool was deprecated in 3.1.0). Use the user-readable error message added in 3.3.0 for client-facing failures, and EnumValue to serialize backed enums without ad-hoc ->value noise in every resource.

return ApiResponse::create(Status::NotFound)
    ->withErrorMessage('Order not found');

Request parsing with ArgumentBag and ImportData. ArgumentBag is an array-like argument holder (with ArrayAccess since 3.2.2) for consolidating controller/command inputs. ImportData is the helper for imported payloads: it normalizes empty strings to null and detects rewritable paths more robustly as of 3.4.6. For JSON bodies, malformed input is logged with the raw JSON — check your logs rather than guessing at decode failures.

Abilities with CAN_ attributes. AbilitiesVoter votes on attributes prefixed CAN_, so authorization reads naturally in controllers and templates: $this->isGranted('CAN_EDIT_ORDER', $order). Register your ability→callback mapping as the extension point; don't hand-roll a second voter.

Cross-cutting helpers. TranslationHelper (3.5.0) plus TranslatableInterface support means helpers accept any translatable, not just TranslatableMessage. InMemoryCache is a per-request memoization cache — good for repeated lookups inside one request, wrong for anything that must survive the request.

Links on entities. Implement LinkableInterface (the v2 Routable successor) so entities can generate their own URLs instead of controllers/templates hardcoding route names.

Gotchas and Tips

  • It is not Laravel, and it is not trying to be. No Eloquent, no facades, no queued jobs, no artisan. Doctrine EntityManager, Symfony voters, and Symfony's container are assumed. Porting patterns across frameworks means rewriting, not importing.
  • Pin your version and read the CHANGELOG before upgrading. v3.0.0 removed sortable handlers, the simple entity search handler, Model, and Routable; it also renamed the field traits and moved EntityInterface. Minor bumps still change signatures (e.g. ApiResponse constructor). With ~0 dependents, you're on your own for upgrade guides.
  • DoctrineChangeChecker is deprecated (3.4.5) and its internals changed repeatedly around UnitOfWork handling. Don't build new audit logging on it — assume it disappears in the next major.
  • Budget for the PHP 8.4 requirement. It's the most common reason an otherwise suitable Symfony app can't use current releases; check composer why-not before evaluating features.
  • Empty-string → null normalization in ImportData will surprise you if downstream code distinguishes "" from null (unique constraints, NOT NULL columns with defaults). Decide explicitly whether that's what you want.
  • Unsigned integer IDs (3.2.1) can bite on existing schemas: foreign keys, signed INT columns, and legacy migrations need review before adopting the traits.
  • BaseController public methods are effectively @protected. Custom public methods were flagged as a BC-break deprecation in 2.4.1. Don't call them from outside the controller, and don't add your own public helpers — use services from getService().
  • The CAN_ prefix is load-bearing. AbilitiesVoter only votes on attributes with that prefix; a typo in the attribute string silently falls through to a deny (or to another voter's abstain). Verify with a functional test, not by eyeballing.
  • InMemoryCache doesn't cache across requests. If you're chasing performance, don't mistake it for a PSR-6 pool.
  • Small ecosystem, opinionated conventions. Two stars and a single-maintainer release cadence mean the bundle mirrors 21TORR's internal project shape. Treat the docs site as the source of truth, expect limited community answers, and keep the bundle boundary thin — wrap ApiResponse/EntityModel usage in your own base classes so you can swap it out if maintenance stalls.
  • Watch for deprecation notices at runtime rather than in docs; the project uses trigger_deprecation and PHPDoc @deprecated together. Running the test suite with deprecations escalated to errors is the cheapest early warning you'll get.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support