Aura.Web_Project
This package provides a minimal framework for web projects., (*1)
By "minimal" we mean very minimal. The package provides only a dependency
injection container, a configuration system, a router, a dispatcher, a pair of
request and response objects, and a logging instance., (*2)
This minimal implementation should not be taken as "restrictive". The DI
container, with its two-stage configuration system, allows a wide range of
programmatic service definitions. The router and dispatcher are built with
iterative refactoring in mind, so you can start with micro-framework-like
closure controllers, and work your way into more complex controller objects of
your own design., (*3)
Foreword
Requirements
This project requires PHP 5.4 or later; we recommend using the latest available version of PHP as a matter of principle., (*4)
Unlike Aura library packages, this project package has userland dependencies, which themselves may have other dependencies:, (*5)
Installation
Install this project via Composer to a {$PROJECT_PATH}
of your choosing:, (*6)
composer create-project aura/web-project {$PROJECT_PATH}
This will create the project skeleton and install all of the necessary packages., (*7)
Tests
, (*8)
To run the unit tests at the command line, issue ./phpunit.sh
at the package root. This requires PHPUnit to be available as phpunit
., (*9)
Alternatively, after you have installed the project, start the built-in PHP server with the web/
directory as the document root:, (*10)
cd {$PROJECT_PATH}
php -S localhost:8000 -t web/
When you browse to http://localhost:8000 you should see "Hello World!" as the output. Terminate the built-in server process thereafter. (Be sure to use the built-in PHP server only for testing, never for production.), (*11)
PSR Compliance
This projects attempts to comply with PSR-1, PSR-2, and PSR-4. If you notice compliance oversights, please send a patch via pull request., (*12)
To ask questions, provide feedback, or otherwise communicate with the Aura community, please join our Google Group, follow @auraphp on Twitter, or chat with us on #auraphp on Freenode., (*13)
Services
This package uses services defined by:, (*14)
This project resets the following services:, (*15)
-
aura/project-kernel:logger
: an instance of Monolog\Logger
Getting Started
Component Packages
This project combines a collection of independent Aura packages into a cohesive whole. The operation of each package is documented separately., (*16)
The dependency injection Container is absolutely central to the operation of an Aura project. Please be familiar with the Aura.Di docs before continuing., (*17)
You should also familiarize yourself with Aura.Router, Aura.Dispatcher, and the Aura.Web Request and Response objects., (*18)
Project Configuration
Every Aura project is configured the same way. Please see the shared configuration docs for more information., (*19)
Logging
The project automatically logs to {$PROJECT_PATH}/tmp/log/{$mode}.log
. If
you want to change the logging behaviors for a particular config mode,
edit the related config file (e.g., config/Dev.php
) file to modify the
aura/project-kernel:logger
service., (*20)
Routing and Dispatching
We configure routing and dispatching via the project-level config/
class files. If a route needs to be available in every config mode,
edit the project-level config/Common.php
class file. If it only needs
to be available in a specific mode, e.g. dev
, then edit the config file for
that mode., (*21)
Here are three different styles of routing and dispatching., (*22)
Micro-Framework Style
Aura is the first framework which follows the
Action Domain Responder pattern.
The following is an example of a micro-framework style route, where the
action logic is embedded in the route params. In the modifyWebRouter()
config method, we retrieve the shared aura/web-kernel:request
and
aura/web-kernel:response
services, along with the aura/web-kernel:router
service. We then add a route names blog.read
and embed the action code as a
closure., (*23)
get('aura/web-kernel:request');
$response = $di->get('aura/web-kernel:response');
$router = $di->get('aura/web-kernel:router');
$router
->add('blog.read', '/blog/read/{id}')
->addValues(array(
'action' => function ($id) use ($request, $response) {
$content = "Reading blog post $id";
$response->content->set(htmlspecialchars(
$content, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8'
));
}
));
}
// ...
}
?>
You can now start up the built-in PHP server to get the application running ..., (*24)
cd {$PROJECT_PATH}
php -S localhost:8000 -t web/
... and browse to http://localhost:8000/blog/read/88 to see the application output., (*25)
Modified Micro-Framework Style
We can modify the above example to put the controller logic in the
dispatcher instead of the route itself., (*26)
Extract the action closure to the dispatcher under the name
blog.read
. Then, in the route, use a action
value that
matches the name in the dispatcher., (*27)
get('aura/web-kernel:router');
$router
->add('blog.read', '/blog/read/{id}')
->addValues(array(
'action' => 'blog.read',
));
}
public function modifyWebDispatcher(Container $di)
{
$request = $di->get('aura/web-kernel:request');
$response = $di->get('aura/web-kernel:response');
$dispatcher = $di->get('aura/web-kernel:dispatcher');
$dispatcher->setObject(
'blog.read',
function ($id) use ($request, $response) {
$content = "Reading blog post $id";
$response->content->set(htmlspecialchars(
$content, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8'
));
}
);
}
// ...
}
?>
You can now start up the built-in PHP server to get the application running ..., (*28)
cd {$PROJECT_PATH}
php -S localhost:8000 -t web/
... and browse to http://localhost:8000/blog/read/88 to see the application
output., (*29)
Full-Stack Style
You can migrate from a micro style to a full-stack style (or start
with full-stack style in the first place)., (*30)
First, define an action class and place it in the project src/
directory., (*31)
request = $request;
$this->response = $response;
}
public function __invoke($id)
{
$content = "Reading blog post $id";
$this->response->content->set(htmlspecialchars(
$content, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8'
));
}
}
?>
Next, tell the project how to build the BlogReadAction through the DI
Container. Edit the project config/Common.php
file to configure the
Container to pass the aura/web-kernel:request
and aura/web-kernel:response
service objects to
the BlogReadAction constructor., (*32)
set('aura/project-kernel:logger', $di->lazyNew('Monolog\Logger'));
$di->params['App\Actions\BlogReadAction'] = array(
'request' => $di->lazyGet('aura/web-kernel:request'),
'response' => $di->lazyGet('aura/web-kernel:response'),
);
}
// ...
}
?>
After that, put the App\Actions\BlogReadAction object in the dispatcher
under the name blog.read
as a lazy-loaded instantiation ..., (*33)
get('aura/web-kernel:dispatcher');
$dispatcher->setObject(
'blog.read',
$di->lazyNew('App\Actions\BlogReadAction')
);
}
// ...
}
?>
... and finally, point the router to the blog.read
action object:, (*34)
get('aura/web-kernel:router');
$router->add('blog.read', '/blog/read/{id}');
}
// ...
}
?>
You can now start up the built-in PHP server to get the application
running ..., (*35)
cd {$PROJECT_PATH}
php -S localhost:8000 -t web/
... then browse to http://localhost:8000/blog/read/88 to see the application
output., (*36)
Other Variations
These are only some common variations of router and dispatcher interactions;
there are many other combinations., (*37)