How To

A look at various different ways you can customize BitFrame

Customize

Using Middleware:

You can use any existing PSR-7 / PSR-15 compatible middleware available on the Packagist, or create your own.

Configure Application:

One of the easiest ways to customize the application components is to configure the application by passing a configuration array to \BitFrame\Application at the time of instantiation. Using this method, you can customize the following components:

  1. \BitFrame\Dispatcher\DispatcherInterface
  2. \Psr\Http\Message\ServerRequestInterface
  3. \Psr\Http\Message\ResponseInterface
  4. \BitFrame\Router\RouteCollectionInterface

Using Factories:

BitFrame has two main factory classes:

  1. \BitFrame\Factory\ApplicationFactory
  2. \BitFrame\Factory\HttpMessageFactory

You can use these factory classes to customize BitFrame. The following components can be customized via factories:

Example:
use \BitFrame\Factory\ApplicationFactory;
use \BitFrame\Factory\HttpMessageFactory;

// create default http response
$response = HttpMessageFactory::createResponse();

// create default middleware dispatcher
$dispatcher = ApplicationFactory::createDispatcher($response);

// create default http request
$request = HttpMessageFactory::createServerRequestFromArray($_SERVER);

$dispatcher->addMiddleware([
    \BitFrame\Message\DiactorosResponseEmitter::class,
    function($request, $response, $next) {
        $response->getBody()->write('Hello World!');

        return $response;
    }
]);

$dispatcher->handle($request);
Example:
use \BitFrame\Factory\ApplicationFactory;

// create default event manager
$eventManager = ApplicationFactory::createEventManager();

// create a new event
$event = new Event('name', 'target', ['test' => 'hello world']);

/** attach event  */
$eventManager->attach('name', function($event) {
    echo $event->getParam('test'); // outputs: 'hello world'
});

$eventManager->trigger($event);
Example:
use \BitFrame\Factory\HttpMessageFactory;

// create default http response
$response = HttpMessageFactory::createResponse(200);

$body = $response->getBody();

$body->write('Hello World!');

// emit response body
if ($body->isSeekable()) {
    $body->rewind();
}

// no readable data in stream?
if (! $body->isReadable()) {
    echo $body;
} else {
    // read data till end of stream is reached...
    while (! $body->eof()) {
        // read 8mb (max buffer length) of binary data at a time and output it
        echo $body->read(1024 * 8);
    }
}
Example:
use \BitFrame\Factory\ApplicationFactory;

// create default route collection
$routeCollection = ApplicationFactory::createRouteCollection();

$routeCollection->get('/', function($request, $response, $next) {
    // do something
});

echo '<pre>' . print_r($routeCollection, true) . '</pre>';
Example:
use \BitFrame\Factory\HttpMessageFactory;

// create http request from server variables
$request = HttpMessageFactory::createServerRequestFromArray($_SERVER);

// create http request from method + url
$request = HttpMessageFactory::createServerRequest(
    'GET', 'http://www.example.com'
);
Example:
use \BitFrame\Factory\HttpMessageFactory;

// stream with content
$stream = HttpMessageFactory::createStream('Hello World!');

// stream from file
$stream = HttpMessageFactory::createStreamFromFile('/path/to/file', 'r');

// stream from resource
$stream = HttpMessageFactory::createStreamFromResource(
    // read/write stream for temporary data storage 
    // in a temporary file
    fopen('php://temp', 'r+')
);
Example:
use \BitFrame\Factory\HttpMessageFactory;

// create default uri
$uri = HttpMessageFactory::createUri('http://www.example.com');

echo (string)$uri;
Using Your Own Factory Classes:

Calling the listed static methods on the following two main factories you can replace various components of BitFrame:

  1. \BitFrame\Factory\ApplicationFactory:
  2. \BitFrame\Factory\HttpMessageFactory:
Examples:
use \BitFrame\Factory\ApplicationFactory;
use \BitFrame\Factory\HttpMessageFactory;

// set event manager factory
ApplicationFactory::setEventManagerFactory(  );

// set http response factory
HttpMessageFactory::setResponseFactory(  );

// instantiate application
$app = new \BitFrame\Application;

You must set the factory classes before instantiating \BitFrame\Application. Note, however, that all subsequent instances of the classes you provide custom factories for, will use that factory class. If you wish to revert back, or change this, you will have to set the factory back to default or to another factory class of your choosing.

Remember to see the method api to see the factory interface you must implement in your custom factory classes in order to replace the default ones.

Custom Components:

You can create your own components using the interfaces and traits available in BitFrame.

Interfaces You Can Implement:

You can implement the following interfaces to create custom components in BitFrame:

  1. \BitFrame\Dispatcher\DispatcherInterface:

    Representation of a middleware dispatcher.

  2. \BitFrame\EventManager\EventInterface:

    Representation of an event.

  3. \BitFrame\EventManager\EventManagerInterface:

    Representation of an event manager.

  4. \BitFrame\Factory\DispatcherFactoryInterface:

    Representation of an dispatcher factory.

  5. \BitFrame\Factory\EventManagerFactoryInterface:

    Representation of an event manager factory.

  6. \BitFrame\Factory\RouteCollectionFactoryInterface:

    Representation of route collection factory.

  7. \BitFrame\Renderer\TemplateInterface:

    Interface defining required template capabilities.

  8. \BitFrame\Router\RouteCollectionInterface:

    Representation of a route collection.

  9. \BitFrame\Router\RouterInterface:

    Interface defining required router capabilities.

  10. \Psr\Http\Message\ServerRequestInterface:

    Representation of an incoming, server-side HTTP request.

  11. \Psr\Http\Message\ResponseInterface:

    Representation of an outgoing, server-side response.

Traits You Can Use:

You could use the following traits in your own components to extend their functionality:

  1. \BitFrame\Data\ApplicationDataTrait:

    Common implementation of the \ArrayAccess interface methods.

  2. \BitFrame\Delegate\CallableMiddlewareTrait:

    Decorate PSR-7 style callable delegates as PSR-15 compatible, processable http requests.

  3. \BitFrame\Dispatcher\DispatcherAwareTrait:

    Exposes the Dispatcher to any 'aware' class.

  4. \BitFrame\EventManager\EventManagerAwareTrait:

    Exposes the EventManager to any 'aware' class.

  5. \BitFrame\EventManager\EventManagerTrait:

    Common implementation of an event manager.

  6. \BitFrame\Message\RequestTrait:

    Provides extended, proprietary, functionality for the PSR-7 Http Request interface.

  7. \BitFrame\Message\ResponseTrait:

    Provides extended, proprietary, functionality for the PSR-7 Http Response interface.

  8. \BitFrame\Router\RouteCollectionMapTrait:

    Common implementation of the http router methods.

  9. \BitFrame\Router\RouteConditionTrait:

    Provides common router-related methods.

  10. \BitFrame\Router\RouterTrait:

    Common methods that all routers can implement.

  11. \BitFrame\Locale\GeoLocationTrait:

    Common wrapper for the Geocoder plugin (requires the designcise/bitframe-geolocation package).

  12. \BitFrame\Locale\RemoteAddressTrait:

    Get user ip (requires the designcise/bitframe-geolocation package).

Comments

Let us know if you have something to say or add