Download the PHP package alvarez/concrete-php without Composer
On this page you can find all versions of the php package alvarez/concrete-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download alvarez/concrete-php
More information about alvarez/concrete-php
Files in alvarez/concrete-php
Package concrete-php
Short Description Generator of DTOs and Services for Laravel using stubs
License MIT
Informations about the package concrete-php
ConcretePHP — Service Layer & DTO Abstractions
A lightweight, pragmatic set of abstractions to organize business logic in Laravel:
a minimal Service Layer (AbstractModelService) and a compact
DTO system (AbstractDTO).
Table of Contents
- Overview
- Features
- Requirements
- Installation
- Quick Start (Examples)
-
Deep Dive — API Reference
AbstractDTOAbstractModelServiceIsDTOcontract
- Behavior & Implementation Notes (the "magic")
- Extending & Customization
- Testing (outside Laravel)
- Best Practices
- Packagist / Composer Publishing Tips
- Contributing
- Changelog
- License
1. Overview
ConcretePHP focuses on two complementary building blocks:
- DTOs (Data Transfer Objects) —
AbstractDTOgives you a small, serializable object model for carrying validated data between layers. - Service Layer —
AbstractModelServicewraps an Eloquent model instance and centralizes create/find/update operations while accepting DTOs or arrays.
This combination reduces coupling between HTTP layer and persistence, makes unit-testing trivial, and keeps your controllers focused on request/response logic.
2. Features
- Accept DTOs or arrays uniformly when creating/updating records.
- Fluent interface for updating / setting records.
- Built-in helpers for DTO serialization (
toArray,toJson,fromArray,fromJson), filtering (except) and immutability-like cloning (cloneWith). - Sensible convention:
UserService→App\Models\User(pluggable by overridinggetModelPath). - Lightweight — no repository abstractions, no heavy DI required.
3. Requirements
- PHP 8.0 or later (union types and
staticreturn types are used) - Laravel 8+ (for typical usage), or
illuminate/databaseif you want to use Eloquent standalone.
4. Installation
If you plan to run tests or use the package outside Laravel, install Eloquent components:
5. Quick Start (Examples)
DTO Definition
Service Definition
Create a User (DTO or array)
Find, Update, and Access Model
6. Deep Dive — API Reference
Alvarez\ConcretePhp\Contracts\IsDTO
This contract ensures DTOs can be converted to/from arrays and JSON. Services rely on toArray() to persist DTO data.
Alvarez\ConcretePhp\Data\AbstractDTO
Public methods provided:
public static function fromArray(array $data): static— Creates a DTO instance from an array usingnew static(...$data).public function toArray(): array— Returns an associative array of the DTO’s public properties usingget_object_vars($this).public function except(array $keys): array— Returns DTO properties, excluding the provided keys.public function cloneWith(array $values): static— Returns a new DTO instance with merged values (original remains unchanged).public static function fromJson(string $json): static— Create DTO from JSON string.public function toJson(): string— Convert DTO to JSON string.
Notes & caveats
fromArrayuses the argument unpacking operator (...$data) to pass array values to the DTO constructor. This means the order of values matters — the array must provide values in the same order as the constructor parameters. If you prefer keyed mapping, build DTO instances manually or implement a small factory.toArray()returns public properties only. If you use protected/private fields in a derived DTO, they won't be part of the serialized form.
Alvarez\ConcretePhp\Services\AbstractModelService
Public methods provided:
public static function create(array|IsDTO $data): static— Create a new model record and return a Service instance that wraps it. Accepts either a DTO (callstoArray()), or a plain array.public static function find(string|int $id): static— UsesfindOrFailon the resolved model path and returns a Service wrapping the model.public function update(array|IsDTO $data): static— Update the internal model with data from an array or DTO, and return$thisfor chaining.public function getRecord(): Model— Get the underlying Eloquent model instance.public function setRecord(Model $record): static— Replace the stored model instance — returns$this.public static function getModelPath(): string— Resolve the Model FQN by convention. Defaults toApp\Models\{ModelName}derived from service class name.
Behavior details
- When
create()is called with a DTO,create($data->toArray())will be executed on the resolved Eloquent model class. For arrays,create($data)is executed directly. find()usesfindOrFail()to surfaceModelNotFoundExceptionwhen the record is absent (this maps to a 404 in HTTP contexts when using Laravel's exception handler).update()delegates to Eloquent'supdate()method on the stored model instance.
7. Behavior & Implementation Notes (the "magic")
These are the small, opinionated choices that make ConcretePHP feel magical and at the same time predictable — and why they matter:
-
Constructor-wrapped Model:
AbstractModelServicestores a single Eloquent model instance. This makes services lightweight stateful wrappers — ideal for per-request domain operations. -
DTO-first flow: Services accept DTOs and arrays interchangeably. Passing DTOs clarifies intent and ensures you work with validated, explicit contracts before touching persistence.
-
Convention-based model resolution:
getModelPath()extracts the service class basename and removes theServicesuffix.UserService→App\Models\User. Override it if your models live elsewhere or use a different naming scheme. -
Fluent API &
staticreturn types: Methods returnstaticso child service classes preserve fluent chaining and typing. -
Immutability-friendly DTOs:
cloneWith()returns a new instance — original DTOs remain unchanged, which helps reasoning about state when composing domain operations. - Testing-friendly: The service layer is pure PHP and touches Eloquent only through the Model instance — which means you can inject mocked or in-memory models for unit tests.
8. Extending & Customization
Overriding model path
If your models live outside App\Models, or you want to point to a mock in tests, just override getModelPath():
Add domain methods
A service should contain domain-specific operations, not just CRUD helpers:
Validation & Form Requests
Keep validation responsibility in Form Requests (or a validation layer) and pass a DTO into the service. This keeps the service focused on business logic and persistence.
9. Testing (outside Laravel)
The repository includes example tests which demonstrate how to bootstrap Eloquent in-memory via Illuminate\Database\Capsule\Manager (useful for package tests or library CI):
- Boot Eloquent with an in-memory SQLite DB.
- Create test schema using
Capsule::schema()->create(...). - Define a small mock model (with
$fillable) and a concrete Service class that overridesgetModelPath()to return the mock model class.
Example (conceptual):
This pattern is included in the test-suite so Continuous Integration can verify package behavior without a full Laravel app.
10. Best Practices
- Prefer DTOs over raw arrays when passing input to services.
- Keep services focused: orchestrate domain logic and talk to models — do not implement HTTP concerns.
- Use Form Requests (or a Validator) to return validated data before creating DTOs.
- Override
getModelPath()in tests for deterministic behavior. - When using
AbstractDTO::fromArray, ensure the input array values follow the constructor parameter order.
11. Packagist / Composer Publishing Tips
Suggested composer.json excerpt for the package root:
- Tag releases semantically (v1.0.0, v1.1.0).
- Add a
CHANGELOG.mdand keep it updated.
12. Contributing
Contributions are welcome!
- Open issues for bugs or feature requests.
- Send PRs against
main. - Keep changes small and focused, and include tests for new behavior.
Suggested CI checks:
- PHPUnit tests
- Static analysis (Psalm/Phan)
- PHPStan level 7+
13. Changelog
See CHANGELOG.md for details. Keep the first release note brief:
v1.0.0— Initial release:AbstractDTO,AbstractModelService, contract and basic tests.
14. License
MIT — see LICENSE for full text.
If you want, I can:
- Produce a shorter
README.mdsuitable for Packagist’s limited preview. - Generate a
composer.jsoncomplete file ready for publishing. - Add ready-to-copy badges and GitHub templates (issue template, PR template).
- Create
CHANGELOG.mdorCONTRIBUTING.mdfiles.
Tell me which of the above you want next and I’ll add them directly to the repository content.
All versions of concrete-php with dependencies
illuminate/console Version ^10.0|^11.0|^12.0
illuminate/support Version ^10.0|^11.0|^12.0