Search by

pekral / arch-app-services

pekral

Laravel package providing architectural abstractions for services, repositories and model managers

Package info

github.com/pekral/arch-app-services

Documentation

Language:Shell

pkg:composer/pekral/arch-app-services

Statistics

Installs: 94 446

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 1

0.5.2 2026-11-11 07:13 UTC

README

Arch App Services — an arch connecting separate application layers

Arch App Services

Latest Version on Packagist MIT Licensed Checkers Total Downloads

Arch App Services gives Laravel applications single-purpose Actions, Repositories for reads, and Model Managers for writes. Model Services combine the read and write layers; Artisan generators and custom PHPStan rules help keep that structure consistent.

Note

The package is under active development and its API may change between releases. Review the changelog before upgrading.

Requirements

  • PHP ^8.4 with the SimpleXML extension.
  • Laravel 12 or 13 (illuminate/* constraints: ^12.0 || ^13.0).

Installation

composer require pekral/arch-app-services

Laravel discovers ArchServiceProvider automatically.

DynamoDB support is optional. Applications using the DynamoDB Repositories and Model Managers must also install the driver:

composer require "baopham/dynamodb:^7.1"

SQL-only applications do not need this dependency. See DynamoDB setup for models and configuration.

Configuration

No configuration is required: defaults for pagination, repository caching and transaction attempts load from config/arch.php. Publish the file to change them:

php artisan vendor:publish --tag="arch-config"

Publish the generator templates to customize generated classes:

php artisan vendor:publish --tag="arch-stubs"

Quick start

In a Laravel application with an existing App\Models\User model and migrated users table, generate its service stack:

php artisan make:arch-service "App\Models\User"

This creates UserModelService, UserRepository and UserModelManager in app/Services/User. The model must allow mass assignment of the fields you pass to create(); the example uses name, email and password.

Resolve the generated service through Laravel's container to write and read a user:

use App\Services\User\UserModelService;
use Illuminate\Support\Facades\Hash;

$users = app(UserModelService::class);

$user = $users->create([
    'name' => 'Alex',
    'email' => 'alex@example.com',
    'password' => Hash::make('example-password'),
]);

$found = $users->getOneByParams(['email' => 'alex@example.com']);
// $found->id === $user->id

create() delegates to the Model Manager; getOneByParams() delegates to the Repository and throws ModelNotFoundException when no record matches. Use findOneByParams() for a nullable result.

Put an operation in an Action

Save this as app/Actions/User/UpdateUserName.php. It follows the package's final readonly Action convention and injects the generated service:

<?php

namespace App\Actions\User;

use App\Models\User;
use App\Services\User\UserModelService;
use Pekral\Arch\Action\ArchAction;

final readonly class UpdateUserName implements ArchAction
{
    public function __construct(private UserModelService $users)
    {
    }

    public function __invoke(string $name, User $user): void
    {
        $this->users->updateModel($user, ['name' => $name]);
    }
}

Call the Action from a controller or another application entry point after validating and authorizing the request:

use App\Actions\User\UpdateUserName;

$updateUserName = app(UpdateUserName::class);
($updateUserName)('Alex Morgan', $user);

This Action takes its inputs as __invoke() arguments. The optional ActionInvokeArgumentsRule PHPStan rule reports that style; see the rule summary before enabling it.

What it does

Component Responsibility
Actions & Model Services Actions orchestrate an operation through __invoke(); Model Services combine reads and writes
Repositories & Model Managers Query and paginate records; create, update, delete and process records in bulk, with SQL and DynamoDB implementations
Repository caching Opt in to cached reads through CacheableRepository::cache(), with configurable TTL and explicit invalidation
Data objects & validation Build DTOs on Spatie Laravel Data, validate input and transform data through pipelines
Transactions & Results Wrap SQL writes with Transactional, #[InTransaction] helpers or nested savepoints; return explicit success/failure outcomes with Result
Architecture rules & generators Generate Actions, service stacks, DTOs and validation rules; check layer boundaries, immutable dependencies and raw SQL bindings with PHPStan

The #[InTransaction] attribute requires the TransactionAwareAction trait and an explicit call to executeWithTransactionAttribute() inside the Action. The attribute alone does not wrap execution. See the transaction example.

The package ships 24 PHPStan rules in the Pekral\Arch\PHPStan\Rules namespace. Installation alone does not enable them; register the rules you want in your PHPStan configuration. The rule summary lists each rule with a reported example.

Documentation

Topic Guide
Scaffolding Artisan commands, options and custom stubs
Data access Model Managers and bulk writes · Query Builder methods · Soft deletes
Cached reads Caching, keys and invalidation
Input and transformation DTOs and validation · Data Builder pipelines
DynamoDB Models and setup
Architecture checks PHPStan rule summary · Registration
Transactions Atomic writes · Attribute helper · Nested savepoints
Expected failures Result-based Action · Result API

More working patterns are in examples/.

Testing

Repository development uses PHP 8.5, matching CI. The test suite uses SQLite and DynamoDB Local; composer test:coverage starts the local Docker Compose service through the bundled script. Coverage requires PCOV.

composer install
composer test:coverage
Command Checks
composer analyse PHPStan static analysis
composer security-audit Dependencies against known security advisories
composer check Composer normalization, PHPCS, Pint, Rector dry run, PHPStan, dependency audit and tests with a 100% coverage threshold

Checkers runs on pushes and pull requests to master/main, and weekly.

Changelog

See CHANGELOG.md for release history and breaking changes.

Contributing

See CONTRIBUTING.md. Report bugs and request features through GitHub issues.

Report security vulnerabilities privately as described in the security policy. Everyone taking part is expected to follow the Code of Conduct.

License

MIT. See LICENSE.