mirror of
https://github.com/marcostoll/FF.git
synced 2025-03-22 07:59:57 +01:00
173 lines
5.7 KiB
Markdown
173 lines
5.7 KiB
Markdown
|
Fast Forward
|
||
|
========================================================================================================================
|
||
|
|
||
|
by Marco Stoll
|
||
|
|
||
|
- <marco.stoll@rocketmail.com>
|
||
|
- <http://marcostoll.de>
|
||
|
- <https://github.com/marcostoll>
|
||
|
- <https://github.com/marcostoll/FF>
|
||
|
------------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
# Introduction - What is Fast Forward?
|
||
|
|
||
|
**Fast Forward** (in short **FF**) is a generic application template for building web and/or command line applications
|
||
|
fast and easy. It addresses the common tasks and provides configurable and/or extendable default implementations for you
|
||
|
to use.
|
||
|
|
||
|
Currently **FF** is composed of the following features:
|
||
|
1. Services and a Service Factory
|
||
|
|
||
|
More features will follow (see the Road Map section below).
|
||
|
|
||
|
# A Warning before you start
|
||
|
|
||
|
**FF** is highly opinionated and depends on a bunch of conventions! So be sure to consult the documentation
|
||
|
before deciding to develop your application based on **FF**.
|
||
|
But if you do **FF** ensures a minimal amount of setup, letting you concentrate your efforts on your business logic
|
||
|
instead of soe framework configuration.
|
||
|
|
||
|
# Dependencies
|
||
|
|
||
|
- FF Family
|
||
|
|
||
|
**FF** makes heavy usage of the **Fast Forward Family** components, a collection of independent components providing
|
||
|
generic implementations (like data structures of design patterns) used by many of **FF**'s features.
|
||
|
|
||
|
# Installation
|
||
|
|
||
|
## via Composer
|
||
|
|
||
|
## manual Installation
|
||
|
|
||
|
# Bootstrapping
|
||
|
|
||
|
## Bootstrap a web application
|
||
|
|
||
|
## Bootstrap a command line application
|
||
|
|
||
|
# Services and the Service Factory
|
||
|
|
||
|
## Services - a definition
|
||
|
|
||
|
From the **FF** perspective a service is a singular component (mostly class) that provide needed functionality as part
|
||
|
of certain domain. Common attributes of services should be
|
||
|
- Make minimal assumptions of the surrounding runtime environment.
|
||
|
- Be stateless.
|
||
|
- Be unit testable.
|
||
|
|
||
|
## Writing services
|
||
|
|
||
|
[**CONVENTION**] Service classes extend `FF\Services\AbstractService`.
|
||
|
[**CONVENTION**] Services should be located in your project's `MyProject\Services` namespace (or any sub namespace
|
||
|
thereof) to be found by the `ServicesFactory`.
|
||
|
|
||
|
***Example: Basic service implementation***
|
||
|
|
||
|
namespace MyProject\Services;
|
||
|
|
||
|
use FF\Services\AbstractService;
|
||
|
|
||
|
class MyService extends AbstractService
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
**FF** services can be configured if needed. The `ServicesFactory` will initialize a service's instance with available
|
||
|
config options. But it will be your responsibility to validate that any given options will meet your service's
|
||
|
requirements.
|
||
|
|
||
|
***Example: Configurable service implementation***
|
||
|
|
||
|
namespace MyProject\Services;
|
||
|
|
||
|
use FF\Services\AbstractService;
|
||
|
|
||
|
class MyConfigurableService extends AbstractService
|
||
|
{
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*/
|
||
|
protected function validateOptions(array $options, array &$errors): bool
|
||
|
{
|
||
|
// place you option validation logic here
|
||
|
// example
|
||
|
if (!isset($options['some-option'])) {
|
||
|
$errors[] = 'missing options [some-options]';
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
## Using the Service Factory
|
||
|
|
||
|
**FF**'s service factory is based on the `AbstractSingletonFactory` of the **FF-Factories** component. Be sure to
|
||
|
consult component's [documentation](https://github.com/marcostoll/FF-Factories) for further information about using
|
||
|
**FF** factories.
|
||
|
|
||
|
To retrieve a service from the factory you have to know thw service's **class identifier**. These class identifiers are
|
||
|
composed of the service's class name prefixed by any sub namespace relative to `FF\Services` (for built-in services) or
|
||
|
`MyProject\Services` (for you custom services).
|
||
|
|
||
|
For convenience reasons there is a shorthand class `SF` that lets you retrieve one or more services with minimal effort.
|
||
|
|
||
|
***Example: Getting a single service***
|
||
|
|
||
|
use FF\Services\SF;
|
||
|
use MyProject\Services\MyService;
|
||
|
|
||
|
/** @var MyService $myService */
|
||
|
$myService = SF::i()->get('MyService'); // finds MyProject\Services\MyService
|
||
|
|
||
|
***Example: Getting multiple services at once***
|
||
|
|
||
|
use FF\Services\Events\EventBroker;
|
||
|
use FF\Services\SF;
|
||
|
use MyProject\Services\MyService;
|
||
|
|
||
|
/** @var EventBroker $eventBroker */
|
||
|
/** @var MyService $myService */
|
||
|
list ($eventBroker, $myService) = SF::i()->get('Events\EventBroker', MyService');
|
||
|
|
||
|
|
||
|
## Extending built-in FF Services
|
||
|
|
||
|
The `ServicesFactory` uses a `FF\Factories\NamespaceClassLocator` locator to find services definitions bases on a class
|
||
|
identifier. To archive this, it searches the list of registered base namespace for any suitable service class **in the
|
||
|
given order**.
|
||
|
|
||
|
This feature lets you sub class and replace **FF**'s built-in service implementations easily by just following the
|
||
|
naming conventions and registering the `ServiceFactory` as shown in the **Bootstrapping** section of this document.
|
||
|
|
||
|
***Example: Extend/Replace a built-in service***
|
||
|
|
||
|
namespace MyProject\Services\Runtime;
|
||
|
|
||
|
use FF\Services\Runtime\ExceptionHandler as FFExceptionHandler;
|
||
|
|
||
|
class ExceptionHandler extends FFExceptionHandler
|
||
|
{
|
||
|
// place your custom logic here
|
||
|
}
|
||
|
|
||
|
###############
|
||
|
|
||
|
// when ever some component refers to the 'Runtime\ExceptionHandler' service via the ServicesFactory
|
||
|
// an instance of your service extension will be used instead of the built-in service
|
||
|
|
||
|
/** @var MyProject\Services\Runtime\ExceptionHandler $exceptionHandler */
|
||
|
$exceptionHandler = SF::get('Runtime\ExceptionHandler');
|
||
|
|
||
|
|
||
|
# Road map
|
||
|
|
||
|
- Events
|
||
|
- Runtime
|
||
|
- Controllers
|
||
|
- Sessions
|
||
|
- Security
|
||
|
- CLI
|
||
|
- ORM
|
||
|
- Bootstrapping
|