Minion - Silex framework wrapper
Powerful wrapper extending Silex, merging simplicity of Silex and usability of Symfony 2., (*1)
Table of Contents
- Main features
- Installation
-
Usage
- API Documentation
Main features
- Silex basic features (see more)
- Propel 2.x integration
- Twig 2.x integration
- More flexible services
- Controller classes with handy helpers
- Command line support
Installation
NOTE: Minion require PHP version 5.6.x or greater., (*2)
Using Composer
Type in console composer require dszczer/minion
., (*3)
Usage
Project directory tree
Legend:
- * required
- [name] directory
. (root directory)
+-- [app]*
| +-- config.yml*
| +-- parameters.yml*
| +-- routing.yml*
|
+-- [bin] (autogenerated by Composer)
|
+-- [src]* (project source code)
| +-- [Controller]*
| +-- [Resources] (required if using Twig)
| +-- [views]*
|
+-- [var]*
| +-- [cache] (must have write permission)
| +-- [log] (must have write permission)
|
+-- [vendor]* (Composer dependencies)
|
+-- [web]* (public access directory - server document root)
+-- assets (any directory structure)
+-- index.php (entry point)
Custom project directory structure
If you want to use other directory structure or you have no choice (e.g. shared hosting), you can define custom paths as third __construct
Application's method:
- string rootDir
- project root directory
- string packageDir
- Minion vendor's directory root
- string configPath
- configuration files path, default is /app/
- string propelConfigPath
- Propel sensitive-data and project-specific propel.php
configuration file path; ignored if option minion.usePropel
is false
, (*4)
Bootstrap
All you need to bootstrap Minion is include Composer autoloader, provide application namespace (not required, but recommended), instantiate Minion\Application
and call run()
method on it., (*5)
// web/index.php
require_once __DIR__ . '/../vendor/autoload.php';
// it is recommended to provide ./src/ namespace, but Minion will try to guess this value
$namespace = 'Project\\';
$app = new Minion\Application($namespace, ['debug' => false, 'environment' => 'prod']);
$app->run();
You will need to configure your server to point ./web
directory as the only one with public access, and index.php
as directory index. Look here for more information., (*6)
Application environments
Avaliable environments:
- prod
production - production environment which should be used in production server
- test
testing - testing environment which disable handling error exceptions, (*7)
Initial configuration
You can pass several options into second __construct()
argument Application's method:
- bool debug
- debugging mode, true to enable, false to disable
- string environment
['prod'|'test']
- working application's environment
- bool minion.usePropel
- true to use Propel ORM, false to don't
- bool minion.useTwig
- true to use Twig templating, false to don't, (*8)
Routing
Routing map
Routing map file is based on Symfony 2 routing files component., (*9)
# app/routing.yml
homepage:
path: /
defaults: { _controller: "DefaultController::indexAction" }
# ...
Controllers
Minion provides helpful controller basic class. To extend this class and use actions, write your controller like this:, (*10)
// src/Controller/DefaultController.php
namespace Project\Controller;
use Minion\Controller;
use Minion\Application;
use Symfony\HttpFoundation\Request;
// ...
class DefaultController extends Controller
{
public function indexAction(Request $request, Application $app)
{
// ...
// if you're using Twig, path is relative to src/Resources/views/
return $this->render('index.html.twig');
// if you're not using Twig, path is relative to src/
return $this->render('template_index.html.php');
}
}
IMPORTANT: action shall always return an Symfony\HttpFoundation\Response
object (exactly like in Symfony 2).
For more information about avaliable methods, look into API documentation., (*11)
Services
Services in Minion are something between Silex and Symfony 2. They are expandable, flexible and easy in use., (*12)
Writing own service
First, you must write a new Service class:, (*13)
// src/Service/MyService.php
namespace Project\Service;
class MyService
{
public function foo()
{
return 'bar';
}
}
Then, you should write provider class:, (*14)
// src/Service/CustomServiceProvider.php
namespace Project\Service;
use \Minion\Service\ServiceProvider;
use \Silex\Application as SilexApp;
class CustomServiceProvider extends ServiceProvider
{
public function register(SilexApp $app)
{
$config = $this->getServiceConfig();
$app[ $config->getId() ] = $app->share(function(SilexApp $app) {
return new MyService();
});
}
public function boot(SilexApp $app) {}
}
CustomServiceProvider
shall extend Minion\Service\ServiceProvider
basic class or implement Minion\Service\ServiceProviderInterface
interface.
Of course, instead of sharing a new service, you are fully able to extend an exisitng one. Example below is extending Twig with Twig_Extension
class:, (*15)
// src/Service/CustomServiceProvider.php
namespace Project\Service;
use \Minion\Service\ServiceProvider;
use \Silex\Application as SilexApp;
class CustomServiceProvider extends ServiceProvider
{
public function register(SilexApp $app)
{
$app['twig'] = $app->share($app->extend('twig', function (\Twig_Environment $twig, SilexApp $app) {
$class = $this->getServiceConfig()->getOption('twig.extension.class'); // is \Project\Util\MyTwigExtension
$twig->addExtension(new $class);
return $twig;
}));
}
public function boot(SilexApp $app) {}
}
Finally, you can define your custom service in app/config.yml
file:, (*16)
# app/config.yml
services:
my_custom_service_id: # unique service id
class: "Project\\Service\\CustomServiceProvider" # service provider's fully qualified class name
options: # options accesible inside service provider
twig.extension.class: "\\Project\\Util\\MyTwigExtension"
And Voile'a! You have registered your new service. You can use it for e.g. inside controller's action:, (*17)
// ...
class DefaultController extends Controller
{
public function defaultAction(Request $request, Application $app) {
$myServiceName = $app['my_custom_service']->foo(); // should return 'bar'
}
}
HINT: Minion has it's own Twig extension service provider expander, so you don't have to write your own one. Read more below., (*18)
Service configuration
Inside service provider's register
method you have full access to service configuration, thanks to Minion\Service\ServiceConfigInterface
:, (*19)
// ...
class CustomServiceProvider extends ServiceProvider
{
public function register(SilexApp $app)
{
$serviceConfiguration = $this->getServiceConfig();
}
// ...
}
Service tags are marks for Minion to use build-in service provider and are special case use. Avaliable tags:
- twig.extension
, (*20)
Tag twig.extension
is defined in app/config.yml
like below:, (*21)
# app/config.yml
services:
my_custom_twig_extension_id:
class: "\\Project\\Twig\\MyCustomTwigExtension"
#options: # optional
tags:
- twig.extension
Build-in Twig extensions, ready to use
List of build-in twig extensions:
- AssetExtension
- assets for web use, helps to define web side or server side related paths
- MiscExtension
- some miscellaneous functions thay may be useful
- UrlExtension
- generating links in templates with this is easy
For more information about avaliable methods, see API documentation., (*22)
Error pages
Minion allows you to customize error pages for 403
, 404
and 500
HTTP status codes. Inside your template scope only thrown exception would be avaliable under (Twig) exception
or (PHP) $exception
variable name.
Template file can be standalone or extending other template file., (*23)
Twig template
Place Twig template under src/Resources/views/Static/<code>.html.twig
name, where <code>
is a status code generated by Application., (*24)
PHP template
If you are not using Twig, place your PHP template under src/Static/<code>.html.php
name, where <code>
is a status code generated by Application., (*25)
Console
Minion provides easy in use CLI mode. All project specific commands should be stored in src/Command
directory and should extend Knp\Command\Command
class.
More about Knp Command avaliable here., (*26)
Naming conventions
Command file must have name with suffix Command.php
. Class name also must contain Command
suffix. Files that do not fulfill those conditions are ignored.
Example command:, (*27)
// src/Command/ProjectCommand.php
namespace Project\Command;
use Knp\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class ProjectCommand extends Command
{
// Configure command
protected function configure() {
$this
->setName('project')
->setDescription('project command')
;
}
// Execute command
public function execute(InputInterface $input, OutputInterface $output) {
$output->write('project command in practice');
}
}
Bootstrap
Minion already has bootstrap file for CLI mode, so it should be accessible in your bin
directory, after installing dependencies with Composer., (*28)
Usage
To run Minion in CLI mode, go to your project directory (bash, windows command, etc.) and type bin/console command:name
., (*29)
Minion provides autoloader for Propel commands. If you want to use propel commands, type in project root directory bin/console propel:namespace:command
, for e.g. bin/console propel:model:build
, or just use aliases bin/console build
., (*30)
Registering
Minion has command autoloader, so you just need to place Command
class in the right directory src/Command
. That's all! Of course, you can load commands from anywhere, just call $app->loadCommands($path, $prefix)
before $app->run()
.
Required $path
argument is an absolute path to directory containing command files. Optional $prefix
argument is a namespace for them. So, if you enter prefix, your command for e.g. command:exec
will be avaliable under prefix:command:exec
., (*31)
API Documentation
Click here to see detailed API documentation., (*32)