Download the PHP package j0hnys/trident without Composer
On this page you can find all versions of the php package j0hnys/trident. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download j0hnys/trident
More information about j0hnys/trident
Files in j0hnys/trident
Package trident
Short Description A laravel package for developing applications following Domain Driven Design (DDD) and Test Driven Design (TDD) principles
License MIT
Informations about the package trident
trident
The purpose of this package is to assist developers in building laravel applications using Domain Driven Design (DDD) and Test Driven Development (TDD) principles. The way it is achieved is by creating an application structure through CLI commands that create scaffolding code. Internally the package uses nikic/PHP-Parser in order to understand and edit code.
The main rationale behind this is that the code generated takes care of all the wiring and architecture enforcing that way DDD and TDD principles. This leaves developers more time to focus on implementing business logic.
video introduction at: https://www.youtube.com/watch?v=nMjZEMkYkNM and https://www.youtube.com/watch?v=DxAgaBFP6Rc
Installation instructions
to add to a laravel project as a package
composer require j0hnys/trident
to install in laravel
after executing php artisan trident:install
add
to config/app
Application architecture
Folder structure
The package on install creates among others the following folder structure
Where |* app
is the app directory of a laravel application.
The goal of this structure is to isolate the Domain Logic from application/infrastructure (as seen on DDD) and at the same time, reuse as many build-in laravel functionality and follow the general philosophy of doing things. This has lead to deviations from a purely DDD approach that simplify some of the structures and flow.
The first deviation is in definitions. There are Workflows
and Business
. The Workflows basically implement the workflow of a functionality (e.x. 1. get db list, 2. process, 3. return). The Business implements domain processes (e.x. VAT evaluation, exports to different formats), the concept is to have this functionality isolated and reusable.
The main differences between a pure DDD and the structure above are the following
- Building blocks
- the "Mappers", "Value Objects", "Factories" are implemented by
StrictTypes
(described below) and eloquent-resources - "Entities" are implemented by laravel models and migrations
- "Services" are implemented by "Workflows" -> "Logic"
- "Repositories" are implemented as an abstraction above laravel models
- "Domain Events" are implemented by laravel events
- the "Mappers", "Value Objects", "Factories" are implemented by
- Layers
- "Application Layer" is implemented by
app/Http
,app/Policies
folders basically - "Infrastructure Layer" is implemented by laravel
- "Domain Model Layer" by
app/Trident
folder
- "Application Layer" is implemented by
For more information about DDD you can reference this, this and google
Everything inside the app/Trident
folder is Dependency Injected with Interfaces, the "bind" to laravel happens through dedicated providers in the app/Providers
folder
The app/Trident/Business
folder is for implementing domain processes as pure php classes.
The app/Trident/Workflow/Processes
are for implementing the steps of one workflow process.
All the complexity is handled by the package. Using the CLI commands all the necessary objects are created and binded together and to the framework. The developer implementes the functionality needed to the designated places, Policies
is for authorization, Events
are for events, Repositories
are for repositories e.t.c.
Strict Types
Trident uses j0hnys/trident-typed which is a fork of spatie/typed that is tailored for the purpose of Trident.
The main usage is to define strict data structures that are passed through different layers of the architecture.
For example this struct data structure:
will define an assosiative array that the keys and values have very specific properties. Here the $developer
can have only "name","age","second_name" as properties and each property have specific type only (string, int, ?string accordingly).
The code $developer['name'] = 123;
or $developer['nameee'] = 'John';
will through an exception.
Basic usage
php artisan make:migration create_demo_process
- fill in the appropriate data in the migration file
php artisan migrate
php artisan trident:generate:workflow_restful_crud DemoProcess
In the end of this process the following will be created:
- a new controller with restful CRUD functions will and placed in
app/Http/Controllers/Trident
- a new resource in
routes/trident.php
behind the native authentication middleware - a new model in
app/Models
, a new policy for this process and placed inapp/Policies/Trident
- a new exception class in
app/Trident/Workflows/Exceptions
- a new set of validation (FormRequests) and placed in
app/Trident/Workflows/Validations
- a new set of strict types and placed in
app/Trident/Workflows/Schemas/Logic/<trident entity name>/Typed
- a new set of resources and placed in
app/Trident/Workflows/Schemas/Logic/<trident entity name>/Resources
- a new repository in
app/Trident/Workflows/Repositories
- a new logic for this process in
app/Trident/Workflows/Logic
- finally a new business logic in
app/Trident/Business/Logic
If we want to add a new function in the process, let's say a new feature we execute:
php artisan trident:generate:workflow_logic_function DemoProcess [function_name]
which will create automatically the appropriate functions and wiring in the controller, router, workflow logic, business logic, policy, validation. as seen below
Controller:
Workflow:
Business:
So in this example the TestEntityController
calls TestEntity
from workflow which calls TestEntity
from logic. Authentication, authorization and validation are being done in the controller before we reach the workflow, the workflow interacts with the database (our only external source in this example) and the business only does logic. Workflows should only contain dependency injected functions, "if" statements and "throws" of new Exception as this is all that is needed in order to describe a workflow. By this paradigm all concerns are seperated and isolated using native laravel functionallity (IoC DI, Exceptions, Policies, Validations, authentication) and we have a good base structure for unit, integration, functional tests.
Available artisan commands
Command | Description | Parameters |
---|---|---|
trident:build:migrations | Create all migrations from current database connection | {--output-path=} |
trident:build:model_exports | Create all model exports from current models | {--output-path=} |
trident:build:models | Create all models from current database connection | {--output-path=} |
trident:export:model | export a models schema | {entity_name} {--output-path=} |
trident:generate:business_logic_function | Create a business logic function | {entity_name} {function_name} |
trident:generate:controller_function | Create a controller function | {entity_name} {function_name} |
trident:generate:events | Create an event | {td_entity_type} {event_type} {td_entity_name} |
trident:generate:exception | Create an exception | {td_entity_type} {td_entity_name} |
trident:generate:factories | Create database factories for all models | {--force} |
trident:generate:factory | Create a factory for a model | {model} {--force} |
trident:generate:policy_function | Create a policy function | {entity_name} {function_name} |
trident:generate:process | Create a process | {td_entity_name} {process_name} {schema_path} |
trident:generate:resources | Create resources for restful entity | {entity_name} {--collection} {--workflow} {--schema_path=} {--force} |
trident:generate:resource | Create a resource | {entity_name} {function_name} {--collection} {--workflow} {--schema_path=} {--force} |
trident:generate:restful_crud | Create a RESTFUL CRUD | {name} {--model_db_name=} {--schema_path=} |
trident:generate:strict_type | Create a strict type | {strict_type_name} {function_name} {entity_name} {--workflow} {--schema_path=} {--force} |
trident:generate:validation | Create a validation | {entity_name} {function_name} {--schema_path=} {--force} |
trident:generate:workflow | Create a workflow | {name} |
trident:generate:workflow_function_process | Create a workflow function process from existing workflow function | {entity_name} {type} {function_name} {schema_path} |
trident:generate:workflow_logic_function | Create a workflow logic function | {entity_name} {function_name} |
trident:generate:workflow_restful_crud | Create a workflow with the accompanied restful crud | {name} {--functionality_schema_path=} {--resource_schema_path=} {--validation_schema_path=} {--strict_type_schema_path=} |
trident:generate:workflow_restful_crud_tests | Create workflow restful crud tests | {name} {--functionality_schema_path=} {--request_schema_path=} {--response_schema_path=} |
trident:generate:workflow_restful_function_test | Create a restful function test | {entity_name} {function_name} {--functionality_schema_path=} {--request_schema_path=} {--response_schema_path=} |
trident:generate:workflow_test_logic_function | Create workflow test logic function | {entity_name} {function_name} |
trident:generate:workflow_tests | Create workflow tests | {name} |
trident:install | Trident installer | - |
trident:refresh:class_interface | Refreshes the interface that a class implements according to class functions | {name} {relative_input_path} {relative_output_path} |
trident:refresh:class_interfaces | Refreshes all the interfaces from the classes of a specific type/folder | {td_entity_type} |
trident:refresh:di_binds | Refreshes DI containers binds | - |
trident:refresh:factories | Refreshes all database factories | - |
trident:refresh:workflow_logic_function | Refresh a workflow logic function | {entity_name} {function_name} {--functionality_schema_path=} {--resource_schema_path=} {--validation_schema_path=} {--strict_type_schema_path=} |
trident:refresh:workflow_restful_crud | Refresh a workflow with the accompanied restful crud | {name} {--functionality_schema_path=} {--resource_schema_path=} {--validation_schema_path=} {--strict_type_schema_path=} |
trident:refresh:workflow_restful_crud_tests | Refresh workflow restful crud tests | {name} {--functionality_schema_path=} {--request_schema_path=} {--response_schema_path=} |
trident:refresh:workflow_restful_function_test | Refresh a restful function test | {entity_name} {function_name} {--functionality_schema_path=} {--request_schema_path=} {--response_schema_path=} |
trident:remove:entity | Removes trident entity completely or a part. | {td_entity_name} |
trident:remove:entity_function | Removes trident entity's function with the structures connected to it. | {entity_name} {function_name} |
trident:setup:tests | Trident test setup | - |
All versions of trident with dependencies
doctrine/dbal Version ^2.10
symfony/class-loader Version ^3.0
kitloong/laravel-migrations-generator Version ^4.0
krlove/eloquent-model-generator Version ^1.0
nikic/php-parser Version ^4.0
j0hnys/trident-workflow Version 0.1.0.1
j0hnys/trident-typed Version 0.1.0.0
j0hnys/definitions Version 0.1.0.0