Embryo is a simple PHP framework for building web applications.

3.2.1 2021-06-25 09:58 UTC

This package is auto-updated.

Last update: 2024-04-05 17:37:55 UTC


README

You can use this skeleton application to start working on a new Embryo Framework 3 application.

Getting Started

Requirements

  • PHP >= 7.2
  • URL Rewriting

Installation

Using Composer:

$ composer create-project davidecesarano/embryo [my-app-name]

Configuration

Embryo utilizes the DotEnv PHP library. In a fresh Embryo installation, the root directory of your application will contain a .env.example file. When you install Embryo via Composer, this file will automatically be renamed to .env.

Directory Structure

Directory Description
app Contains the core code of your application. This directory contains a variety of additional directories such as Controllers, Exceptions, Helpers, Middleware, Models and Services.
bootstrap Contains the files which bootstraps your application such as app instantiation, middleware, services and settings.
public Contains the entry point for all request (index.php file) and the assets directory.
routes Contains all of the route definitions for your application. By default, several route files are included with Embryo: app.php and api.php.
storage Contains your logs (logs), compiled templates file (views), file based sessions (sessions), caches files (cache).
translations Contains your language files.
views Contains the views files.

Concepts

Life Cycle

  • The app is instantiated in bootstrap/app.php with Embryo\Application class. During instantiation, Embryo registers services for the dependencies (bootstrap/services.php), middlewares (bootstrap/middleware.php) and routes files (in routes directory). The application constructor accepts an optional settings array that configures the application’s behavior (bootstrap/settings.php).
  • In routes direcotry define routes using the application instance’s routing methods. These instance methods register a route with the application’s Router object. Each routing method returns the Route instance so you can immediately invoke the Route instance’s methods to add middleware or assign a name.
  • In public/index.php invoke the application instance's run() method. This method starts the following process:
    • enter in middleware stack;
    • run application (dispatches the current HTTP request to the appropriate application route object);
    • exit middleware stack;
    • send HTTP response.

PSR-7

Embryo supports PSR-7 interfaces for its Request and Response objects.

Middleware

You can run code before and after your Embryo application to manipulate the Request and Response objects as you see fit. This is called middleware. A middleware implements the PSR-15 Middleware Interface.

Dependency Container

Embryo uses an dependency container to prepare, manage, and inject application dependencies. Embryo supports containers that implement PSR-11.

Application

Routing

You can define application routes using the application instance’s routing methods. Every method accepts two arguments:

  • The route pattern (with optional placeholders)
  • The route callback (a closure, a class@method string or a ['class', 'method'] array)
use Embryo\Http\Message\{Response, ServerRequest};

// GET Route
$app->get('/blog/{id}', function(ServerRequest $request, Response $response, int $id) {
    return $response->write('This is post with id '.$id);
}

Embryo Routing supports GET, POST, PUT, PATCH, DELETE and OPTIONS request methods. Every request method corresponds to a method of the Router object: get(), post(), put(), patch(), delete() and options(). You can use all() and map() methods for supporting all methods or specific route methods.

See full documentation: Embryo Routing.

Register route files

All Embryo routes are defined in your route files, which are located in the routes directory. These files are automatically loaded by your application in boostrap/app.php file. If you want create new ruote file, add it in routes directory and register it in import() method of the application instance in boostrap/app.php file:

$app->import([
    root_path('bootstrap/services.php'),
    root_path('bootstrap/middleware.php'),
    root_path('routes/api.php'),
    root_path('routes/app.php'),
    root_path('routes/my_route_file.php')
]);

Middleware

In Embryo you may create a PSR-15 middleware in app\Middleware directory. You may add middleware to application, to specific route or to route group.

Application middleware

If you want register middleware for every HTTP request, add application middleware in bootstrap\middleware.php. The addMiddleware() method accepts a string, an array or an instance of Psr\Http\Server\MiddlewareInterface.

$app->addMiddleware(App\Middleware\MyCustomMiddleware::class);

Route middleware

You can use the middleware() method to assign one or more middleware at the route. The middleware() method accepts a string, an array or an instance of Psr\Http\Server\MiddlewareInterface.

$app->get('/users', function(ServerRequest $request, Response $response) {
    //...
})->middleware('App\MiddlewareTestMiddleware1::class', 'App\MiddlewareTestMiddleware2::class');

Route group middleware

In addition to the routes, you can assign one or more middleware to a group and to individual routes within the group. The middleware() method accepts a string, an array or an instance of Psr\Http\Server\MiddlewareInterface.

$app->prefix('/api')->middleware(App\Middleware\GroupMiddlewareTest::class)->group(function($app) {
    $app->get('/user/{id}', function(ServerRequest $request, Response $response, int $id) {
        //...
    })->middleware(App\Middleware\RouteMiddlewareTest::class);
});

Controllers

Instead of defining all of your request handling logic as closures in your route files, you may wish to organize this behavior using "controller" classes. Let's take a look at an example of a basic controller. Note that the controller extends the base controller class included with Embryo:

namespace App\Controllers;

use Embryo\Controller;
use Embryo\Http\Message\Response;

class UserController extends Controller
{
    /**
     * @param int $id
     * @return Response
     */
    public function show(int $id): Response
    {
        return $this->response()->write($id);
    }
}

You can define a route to this controller method like so:

use App\Controllers\UserController;

$app->get('/user/{id}', [UserController::class, 'show']);

Controllers are required to extend a base class. However, you will not have access to features such as the get(), request() and response() methods.

Dependency Injection & Controllers

You are able to type-hint any dependencies your controller may need in its constructor. The declared dependencies will automatically be resolved and injected into the controller instance:

namespace App\Controllers;

use Embryo\Controller;
use Path\To\Service;

class UserController extends Controller
{
    /**
     * @var Service $service
     */
    private $service;

    /**
     * @param Service $service
     */
    public function __construct(Service $service)
    {
        $this->service = $service;
    }
}

In addition to constructor injection, you may also type-hint dependencies on your controller's methods:

namespace App\Controllers;

use Embryo\Controller;
use Embryo\Http\Message\ServerRequest;

class UserController extends Controller
{
    /**
     * @param ServerRequest $request
     */
    public function store(ServerRequest $request)
    {
        //...
    }
}

In addition, you may also to use the get() method of the base controller class:

namespace App\Controllers;

use Embryo\Controller;
use Path\To\Service;

class UserController extends Controller
{
    public function show()
    {
       $service = $this->get(Service::class);
       //...
    }
}

Base controller class also has access to PSR-7 request() and response() methods:

namespace App\Controllers;

use Embryo\Controller;
use Embryo\Http\Message\Response;

class UserController extends Controller
{
    /**
     * @return Response
     */
    public function store(): Response
    {
       $params = $this->request()->getParsedBody();
       //...
       return $this->response()->write('Hello!');
    }
}

Alternatively, you may to access to request() and response() helpers:

namespace App\Controllers;

use Embryo\Controller;
use Embryo\Http\Message\Response;

class UserController extends Controller
{
    /**
     * @return Response
     */
    public function store(): Response
    {
       $params = request()->getParsedBody();
       return response()->write('Hello!');
    }
}

Service Providers

Service providers are the central place of all Embryo application bootstrapping. Your own application, as well as all of Embryo's core services, are bootstrapped via service providers.

Writing a service

The service providers era located in app/Services directory. All service providers extend the Embryo\Container\ServiceProvider class and contains a register method. Within the register method, you should only bind things into the service container.

namespace App\Services;

use Embryo\Container\ServiceProvider;

class TestService extends ServiceProvider
{
    /**
     * Registers service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->container->set('test', function($container){
            return 'Hello from my test service';
        });
    }
}

Registering a service

Models

Views

Packages

Validation