├── .gitignore ├── .travis.yml ├── CHANGES.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── composer.json ├── config ├── Common.php ├── Dev.php ├── Prod.php ├── Test.php └── _env.php ├── phpunit.php ├── phpunit.sh ├── phpunit.xml.dist ├── src └── .placeholder ├── tests └── WebProjectTest.php ├── tmp ├── .placeholder ├── cache │ └── .placeholder └── log │ └── .placeholder └── web ├── .htaccess └── index.php /.gitignore: -------------------------------------------------------------------------------- 1 | /composer.lock 2 | /tmp/* 3 | !/tmp/.placeholder 4 | /vendor 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.4 4 | - 5.5 5 | - 5.6 6 | - 7 7 | before_script: 8 | - composer self-update 9 | - composer install 10 | script: 11 | - ./phpunit.sh 12 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | This release fixes a typo in the .gitignore file. 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We are happy to review any contributions you want to make. When contributing, please follow the rules outlined at . 4 | 5 | The time between submitting a contribution and its review one may be extensive; do not be discouraged if there is not immediate feedback. 6 | 7 | Thanks! 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2015, Aura for PHP 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | - Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Aura.Web_Project 2 | 3 | This package provides a minimal framework for web projects. 4 | 5 | By "minimal" we mean *very* minimal. The package provides only a dependency 6 | injection container, a configuration system, a router, a dispatcher, a pair of 7 | request and response objects, and a logging instance. 8 | 9 | This minimal implementation should not be taken as "restrictive". The DI 10 | container, with its two-stage configuration system, allows a wide range of 11 | programmatic service definitions. The router and dispatcher are built with 12 | iterative refactoring in mind, so you can start with micro-framework-like 13 | closure controllers, and work your way into more complex controller objects of 14 | your own design. 15 | 16 | ## Foreword 17 | 18 | ### Requirements 19 | 20 | This project requires PHP 5.4 or later; we recommend using the latest available version of PHP as a matter of principle. 21 | 22 | Unlike Aura library packages, this project package has userland dependencies, which themselves may have other dependencies: 23 | 24 | - [aura/web-kernel](https://packagist.org/packages/aura/web-kernel) 25 | - [monolog/monolog](https://packagist.org/packages/monolog/monolog) 26 | 27 | ### Installation 28 | 29 | Install this project via Composer to a `{$PROJECT_PATH}` of your choosing: 30 | 31 | composer create-project aura/web-project {$PROJECT_PATH} 32 | 33 | This will create the project skeleton and install all of the necessary packages. 34 | 35 | ### Tests 36 | 37 | [![Build Status](https://travis-ci.org/auraphp/Aura.Web_Project.png)](https://travis-ci.org/auraphp/Aura.Web_Project) 38 | 39 | To run the unit tests at the command line, issue `./phpunit.sh` at the package root. This requires [PHPUnit](http://phpunit.de/) to be available as `phpunit`. 40 | 41 | Alternatively, after you have installed the project, start the built-in PHP server with the `web/` directory as the document root: 42 | 43 | cd {$PROJECT_PATH} 44 | php -S localhost:8000 -t web/ 45 | 46 | When you browse to 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.) 47 | 48 | ### PSR Compliance 49 | 50 | 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. 51 | 52 | [PSR-1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md 53 | [PSR-2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md 54 | [PSR-4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md 55 | 56 | ### Community 57 | 58 | To ask questions, provide feedback, or otherwise communicate with the Aura community, please join our [Google Group](http://groups.google.com/group/auraphp), follow [@auraphp on Twitter](http://twitter.com/auraphp), or chat with us on #auraphp on Freenode. 59 | 60 | ### Services 61 | 62 | This package uses services defined by: 63 | 64 | - [Aura.Project_Kernel](https://github.com/auraphp/Aura.Project_Kernel#services) 65 | - [Aura.Web_Kernel](https://github.com/auraphp/Aura.Web_Kernel#services) 66 | 67 | This project resets the following services: 68 | 69 | - `aura/project-kernel:logger`: an instance of `Monolog\Logger` 70 | 71 | ## Getting Started 72 | 73 | ### Component Packages 74 | 75 | This project combines a collection of independent Aura packages into a cohesive whole. The operation of each package is documented separately. 76 | 77 | The dependency injection _Container_ is absolutely central to the operation of an Aura project. Please be familiar with [the Aura.Di docs](https://github.com/auraphp/Aura.Di) before continuing. 78 | 79 | You should also familiarize yourself with [Aura.Router](https://github.com/auraphp/Aura.Router), [Aura.Dispatcher](https://github.com/auraphp/Aura.Dispatcher), and the [Aura.Web](https://github.com/auraphp/Aura.Web) _Request_ and _Response_ objects. 80 | 81 | ### Project Configuration 82 | 83 | Every Aura project is configured the same way. Please see the [shared configuration docs](https://github.com/auraphp/Aura.Project_Kernel#configuration) for more information. 84 | 85 | ### Logging 86 | 87 | The project automatically logs to `{$PROJECT_PATH}/tmp/log/{$mode}.log`. If 88 | you want to change the logging behaviors for a particular config mode, 89 | edit the related config file (e.g., `config/Dev.php`) file to modify the 90 | `aura/project-kernel:logger` service. 91 | 92 | ### Routing and Dispatching 93 | 94 | We configure routing and dispatching via the project-level `config/` 95 | class files. If a route needs to be available in every config mode, 96 | edit the project-level `config/Common.php` class file. If it only needs 97 | to be available in a specific mode, e.g. `dev`, then edit the config file for 98 | that mode. 99 | 100 | Here are three different styles of routing and dispatching. 101 | 102 | #### Micro-Framework Style 103 | 104 | Aura is the first framework which follows the 105 | [Action Domain Responder](https://github.com/pmjones/mvc-refinement) pattern. 106 | The following is an example of a micro-framework style route, where the 107 | action logic is embedded in the route params. In the `modifyWebRouter()` 108 | config method, we retrieve the shared `aura/web-kernel:request` and 109 | `aura/web-kernel:response` services, along with the `aura/web-kernel:router` 110 | service. We then add a route names `blog.read` and embed the action code as a 111 | closure. 112 | 113 | ```php 114 | get('aura/web-kernel:request'); 127 | $response = $di->get('aura/web-kernel:response'); 128 | 129 | $router = $di->get('aura/web-kernel:router'); 130 | $router 131 | ->add('blog.read', '/blog/read/{id}') 132 | ->addValues(array( 133 | 'action' => function ($id) use ($request, $response) { 134 | $content = "Reading blog post $id"; 135 | $response->content->set(htmlspecialchars( 136 | $content, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8' 137 | )); 138 | } 139 | )); 140 | } 141 | 142 | // ... 143 | } 144 | ?> 145 | ``` 146 | 147 | You can now start up the built-in PHP server to get the application running ... 148 | 149 | cd {$PROJECT_PATH} 150 | php -S localhost:8000 -t web/ 151 | 152 | ... and browse to to see the application output. 153 | 154 | #### Modified Micro-Framework Style 155 | 156 | We can modify the above example to put the controller logic in the 157 | dispatcher instead of the route itself. 158 | 159 | Extract the action closure to the dispatcher under the name 160 | `blog.read`. Then, in the route, use a `action` value that 161 | matches the name in the dispatcher. 162 | 163 | ```php 164 | get('aura/web-kernel:router'); 178 | $router 179 | ->add('blog.read', '/blog/read/{id}') 180 | ->addValues(array( 181 | 'action' => 'blog.read', 182 | )); 183 | } 184 | 185 | public function modifyWebDispatcher(Container $di) 186 | { 187 | $request = $di->get('aura/web-kernel:request'); 188 | $response = $di->get('aura/web-kernel:response'); 189 | 190 | $dispatcher = $di->get('aura/web-kernel:dispatcher'); 191 | $dispatcher->setObject( 192 | 'blog.read', 193 | function ($id) use ($request, $response) { 194 | $content = "Reading blog post $id"; 195 | $response->content->set(htmlspecialchars( 196 | $content, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8' 197 | )); 198 | } 199 | ); 200 | 201 | } 202 | 203 | // ... 204 | } 205 | ?> 206 | ``` 207 | 208 | You can now start up the built-in PHP server to get the application running ... 209 | 210 | cd {$PROJECT_PATH} 211 | php -S localhost:8000 -t web/ 212 | 213 | ... and browse to to see the application 214 | output. 215 | 216 | #### Full-Stack Style 217 | 218 | You can migrate from a micro style to a full-stack style (or start 219 | with full-stack style in the first place). 220 | 221 | First, define an action class and place it in the project `src/` directory. 222 | 223 | ```php 224 | request = $request; 238 | $this->response = $response; 239 | } 240 | 241 | public function __invoke($id) 242 | { 243 | $content = "Reading blog post $id"; 244 | $this->response->content->set(htmlspecialchars( 245 | $content, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8' 246 | )); 247 | } 248 | } 249 | ?> 250 | ``` 251 | 252 | Next, tell the project how to build the _BlogReadAction_ through the DI 253 | _Container_. Edit the project `config/Common.php` file to configure the 254 | _Container_ to pass the `aura/web-kernel:request` and `aura/web-kernel:response` service objects to 255 | the _BlogReadAction_ constructor. 256 | 257 | ```php 258 | set('aura/project-kernel:logger', $di->lazyNew('Monolog\Logger')); 269 | 270 | $di->params['App\Actions\BlogReadAction'] = array( 271 | 'request' => $di->lazyGet('aura/web-kernel:request'), 272 | 'response' => $di->lazyGet('aura/web-kernel:response'), 273 | ); 274 | } 275 | 276 | // ... 277 | } 278 | ?> 279 | ``` 280 | 281 | After that, put the _App\Actions\BlogReadAction_ object in the dispatcher 282 | under the name `blog.read` as a lazy-loaded instantiation ... 283 | 284 | ```php 285 | get('aura/web-kernel:dispatcher'); 298 | $dispatcher->setObject( 299 | 'blog.read', 300 | $di->lazyNew('App\Actions\BlogReadAction') 301 | ); 302 | } 303 | 304 | // ... 305 | } 306 | ?> 307 | ``` 308 | 309 | ... and finally, point the router to the `blog.read` action object: 310 | 311 | ```php 312 | get('aura/web-kernel:router'); 325 | $router->add('blog.read', '/blog/read/{id}'); 326 | } 327 | 328 | // ... 329 | } 330 | ?> 331 | ``` 332 | 333 | You can now start up the built-in PHP server to get the application 334 | running ... 335 | 336 | cd {$PROJECT_PATH} 337 | php -S localhost:8000 -t web/ 338 | 339 | ... then browse to to see the application 340 | output. 341 | 342 | #### Other Variations 343 | 344 | These are only some common variations of router and dispatcher interactions; 345 | [there are many other combinations](https://github.com/auraphp/Aura.Dispatcher/tree/develop-2#refactoring-to-architecture-changes). 346 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aura/web-project", 3 | "type": "project", 4 | "description": "A minimal web framework built from Aura v2 packages", 5 | "keywords": [ 6 | "web", 7 | "framework" 8 | ], 9 | "license": "BSD-2-Clause", 10 | "authors": [ 11 | { 12 | "name": "Aura.Web_Project Contributors", 13 | "homepage": "https://github.com/auraphp/Aura.Web_Project/contributors" 14 | } 15 | ], 16 | "require": { 17 | "aura/web-kernel": "~2.0", 18 | "monolog/monolog": "~1.0" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "": "src/", 23 | "Aura\\Web_Project\\_Config\\": "config/" 24 | } 25 | }, 26 | "extra": { 27 | "aura": { 28 | "type": "project", 29 | "config": { 30 | "common": "Aura\\Web_Project\\_Config\\Common", 31 | "dev": "Aura\\Web_Project\\_Config\\Dev", 32 | "test": "Aura\\Web_Project\\_Config\\Test", 33 | "prod": "Aura\\Web_Project\\_Config\\Prod" 34 | } 35 | } 36 | }, 37 | "autoload-dev": { 38 | "psr-4": { 39 | "Aura\\Web_Project\\": "tests/" 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /config/Common.php: -------------------------------------------------------------------------------- 1 | set('aura/project-kernel:logger', $di->lazyNew('Monolog\Logger')); 12 | } 13 | 14 | public function modify(Container $di) 15 | { 16 | $this->modifyLogger($di); 17 | $this->modifyWebRouter($di); 18 | $this->modifyWebDispatcher($di); 19 | } 20 | 21 | public function modifyLogger(Container $di) 22 | { 23 | $project = $di->get('project'); 24 | $mode = $project->getMode(); 25 | $file = $project->getPath("tmp/log/{$mode}.log"); 26 | 27 | $logger = $di->get('aura/project-kernel:logger'); 28 | $logger->pushHandler($di->newInstance( 29 | 'Monolog\Handler\StreamHandler', 30 | array( 31 | 'stream' => $file, 32 | ) 33 | )); 34 | } 35 | 36 | public function modifyWebRouter(Container $di) 37 | { 38 | $router = $di->get('aura/web-kernel:router'); 39 | 40 | $router->add('hello', '/') 41 | ->setValues(array('action' => 'hello')); 42 | } 43 | 44 | public function modifyWebDispatcher($di) 45 | { 46 | $dispatcher = $di->get('aura/web-kernel:dispatcher'); 47 | 48 | $dispatcher->setObject('hello', function () use ($di) { 49 | $response = $di->get('aura/web-kernel:response'); 50 | $response->content->set('Hello World!'); 51 | }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /config/Dev.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ./tests 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auraphp/Aura.Web_Project/8869c99979fc1f920bca1a779869192ec1b813d1/src/.placeholder -------------------------------------------------------------------------------- /tests/WebProjectTest.php: -------------------------------------------------------------------------------- 1 | assertSame($expect, $actual); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tmp/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auraphp/Aura.Web_Project/8869c99979fc1f920bca1a779869192ec1b813d1/tmp/.placeholder -------------------------------------------------------------------------------- /tmp/cache/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auraphp/Aura.Web_Project/8869c99979fc1f920bca1a779869192ec1b813d1/tmp/cache/.placeholder -------------------------------------------------------------------------------- /tmp/log/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/auraphp/Aura.Web_Project/8869c99979fc1f920bca1a779869192ec1b813d1/tmp/log/.placeholder -------------------------------------------------------------------------------- /web/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | # turn on rewriting 3 | RewriteEngine On 4 | 5 | # turn empty requests into requests for "index.php", 6 | # keeping the query string intact 7 | RewriteRule ^$ index.php [QSA] 8 | 9 | # look for cached versions of files in ./web/cache/ 10 | RewriteCond %{DOCUMENT_ROOT}/cache%{REQUEST_URI} -f 11 | RewriteRule ^(.*)$ cache/$1 [L] 12 | 13 | # for all files not found in the file system, 14 | # reroute to "index.php" bootstrap script, 15 | # keeping the query string intact. 16 | RewriteCond %{REQUEST_FILENAME} !-d 17 | RewriteCond %{REQUEST_FILENAME} !-f 18 | RewriteCond %{REQUEST_FILENAME} !favicon.ico$ 19 | RewriteRule ^(.*)$ index.php [QSA,L] 20 | 21 | -------------------------------------------------------------------------------- /web/index.php: -------------------------------------------------------------------------------- 1 | newKernel( 14 | $path, 15 | 'Aura\Web_Kernel\WebKernel' 16 | ); 17 | $kernel(); 18 | --------------------------------------------------------------------------------