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

Core Laravel Package

apiato/core

APIato Core is the foundational package for APIato, an API-first Laravel framework built on the Porto architecture. It provides modular containers, authentication, authorization, routing, shared utilities, and code generation tools for scalable, maintainable backend applications.

Deep Wiki
Context7

Getting Started

apiato/core is the foundational package of the Apiato framework — a Laravel-based API starter kit built around the Porto architectural pattern (Containers → Sections → Actions/Tasks/Repositories/Transformers). You almost never install apiato/core in isolation; you get it transitively via:

composer create-project apiato/apiato my-api

After scaffolding:

  1. Read app/Ship/ first. Ship is where cross-cutting concerns live (exception handler, global config, base migrations, OAuth/Passport setup). It explains how the framework wires itself.
  2. Read one complete App container (usually app/Containers/AppSection/User) end-to-end: Router → Controller → Request → Action → Task → Repository → Model → Transformer. That single container teaches you 90% of the framework.
  3. Check the generators — php artisan list apiato — because scaffolding is how you actually work day to day.

Your first real use case is typically: add a new endpoint under an existing container (e.g. GET /v1/users/{id}), which means writing a Controller + Request + Transformer and re-using the existing Action.

Implementation Patterns

The container is the unit of work

Every feature lives inside a container (app/Containers/{Section}/{Container}). Create one with:

php artisan apiato:container

Then generate the pieces inside it:

php artisan apiato:action --container=AppSection@User
php artisan apiato:task --container=AppSection@User
php artisan apiato:request --container=AppSection@User
php artisan apiato:transformer --container=AppSection@User

The generator scaffolds the correct namespace, base class and boilerplate — do not hand-roll classes if a generator exists for it.

Action orchestrates, Task does the work

The canonical layering:

  • Action — one public run() method, orchestrates Tasks, owns transaction boundaries.
  • Task — single, testable unit of work (CreateUserTask, SendWelcomeEmailTask).
  • SubAction — reusable action invoked from other actions.
  • Repository — persistence concerns only.
  • Transformer — serialization, driven by ?include= query parameters.
class RegisterUserAction extends Action
{
    public function __construct(
        private CreateUserTask $createUserTask,
        private SendWelcomeMailTask $sendWelcomeMailTask,
    ) {}

    public function run(RegisterUserRequest $request): User
    {
        $user = $this->createUserTask->run($request->validated());

        $this->sendWelcomeMailTask->run($user);

        return $user;
    }
}

Inject Tasks/Actions via the constructor — the container auto-resolves them because they are bound by the framework.

Repositories and ?include=

Repositories extend Apiato\Core\Abstracts\Repositories\Repository and expose search(), find(), create(), update(), etc. They support the RequestCriteria out of the box, so a transformer with availableIncludes = ['roles', 'orders'] automatically honors GET /users/1?include=roles.

Requests combine validation + authorization

Extend the framework Request — do not use Laravel's default FormRequest. authorize() and rules() both live on the same class, and the controller signature (RegisterUserRequest $request, ...) auto-validates before the action runs.

Routes are per-container

Each container has UI/API/Routes/*.php. Register routes in the container's ServiceProvider via $this->router helpers ($this->routePublic(), $this->routePrivate(), $this->routeProtected(), $this->routeAdmin()). The middleware stack applied differs per helper, so use them rather than Route::middleware() by hand.

Testing pattern

Tests live inside each container (Containers/AppSection/User/Tests). The framework testcase (ApiTestCase) includes helpers like $this->makeCall(), $this->getTestingUser(), and $this->assertResponseStatus() — always test at the endpoint level (functional), not just unit-test the Task.

Gotchas and Tips

  • Config caching bites hard. Apiato reads config from Ship/Configs and generates classes at bootstrap. After changing config, run php artisan config:clear and (if the container registry seems stale) php artisan apiato:generate or its equivalent in your version. Many "my new container isn't discovered" bugs are cached bootstrap manifests.
  • Naming is load-bearing. Container, Route, Request, and Transformer names follow strict conventions; the framework resolves them by convention, not explicit registration. Renaming a container means also renaming its folder, provider, and routes file.
  • HashIDs on by default. Responses mask numeric IDs as short strings (OZ9bGg). find($id) in repositories transparently decodes them — but if you call Model::find($id) directly, you'll get a miss. Always go through the repository for ID lookups.
  • Transformers default to safe-serialization. If a field is not in the transformer transform(), it will not appear. Adding a column to the DB is not enough — add it to the transformer and update its tests.
  • OAuth2 / Passport wiring is in Ship. Auth endpoints and Proxy helpers for password grants live under Ship/ and the Authentication container. Overriding token TTL, scopes or client config happens there, not in .env alone.
  • Exception handler is custom. Apiato overrides rendering to return consistent JSON error envelopes. If you throw a domain exception, either extend the framework exception class or register a handler in Ship/Exceptions/Handler. Plain \Exception throws may produce non-standard responses.
  • Middleware order matters for auth helpers. $this->routeProtected() vs $this->routePrivate() differ in auth guard; picking the wrong helper is a common source of "why is this public" bugs.
  • Use SubAction for reuse, not inheritance. It's tempting to build deep action hierarchies; instead compose small SubActions — this keeps each Task/Action independently testable, which is the whole point of the layering.
  • Ship vs App container. Put anything reusable across sections (utilities, base repo traits, HTTP helpers) into Ship; keep feature code in its App container. Mixing the two erodes the architecture quickly.
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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource