├── .gitignore
├── LICENSE
├── README.md
├── bootstrap
├── app.php
└── routes.php
├── composer.json
├── composer.lock
├── misc
├── .env.example
├── Dockerfile
├── Vagrantfile
├── config
│ └── nginx
│ │ ├── docker.conf
│ │ └── vagrant.conf
└── docker-compose.yml
├── public
├── assets
│ └── css
│ │ └── styles.css
└── index.php
├── src
└── Controllers
│ ├── GreetController.php
│ └── IndexController.php
└── views
├── base.html.twig
└── pages
├── greet.html.twig
└── index.html.twig
/.gitignore:
--------------------------------------------------------------------------------
1 | ### JetBrains template
2 | *.iml
3 | .idea/
4 | *.ipr
5 | *.iws
6 |
7 |
8 | ### Composer template
9 | composer.phar
10 | vendor/
11 |
12 |
13 | ### Vagrant template
14 | .vagrant/
15 |
16 |
17 | ### Custom
18 | .env
19 |
20 |
21 | ### OSX template
22 | .DS_Store
23 | .AppleDouble
24 | .LSOverride
25 |
26 | # Icon must end with two \r
27 | Icon
28 |
29 | # Thumbnails
30 | ._*
31 |
32 | # Files that might appear in the root of a volume
33 | .DocumentRevisions-V100
34 | .fseventsd
35 | .Spotlight-V100
36 | .TemporaryItems
37 | .Trashes
38 | .VolumeIcon.icns
39 |
40 | # Directories potentially created on remote AFP share
41 | .AppleDB
42 | .AppleDesktop
43 | Network Trash Folder
44 | Temporary Items
45 | .apdisk
46 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Frameworkless
2 | An admittedly overly simplistic example of combining a few popular packages into your own micro-framework.
3 |
4 |
5 | ## Why?
6 |
7 | **Education.**
8 |
9 | I do not recommend building your own framework unless you have a very compelling reason to do so.
10 | Instead,use a popular & well-supported framework like [Symfony](http://symfony.com), [Slim](https://www.slimframework.com), or [Laravel](http://laravel.com).
11 |
12 | #### What's included?
13 | I spent some time picking out packages, preferring those used by existing large applications or frameworks. Here is what's included, in no particular order:
14 |
15 | * **[nikic/fast-route](https://github.com/nikic/FastRoute)**
16 | * Popular routing library used by frameworks like [Slim](http://www.slimframework.com).
17 | * **[filp/whoops](https://github.com/filp/whoops)**
18 | * Stunning error handler, it makes errors sting a bit less.
19 | * **[symfony/http-foundation](https://github.com/symfony/http-foundation)**
20 | * Simplifies request & reponse handling.
21 | * **[league/container](https://github.com/thephpleague/container)**
22 | * Dependency injection container, for sharing common resources (like a database connection).
23 | * **[twig/twig](https://github.com/twigphp/Twig)**
24 | * The rock solid templating engine used by Symfony and many others.
25 | * **[vlucas/phpdotenv](https://github.com/vlucas/phpdotenv)**
26 | * Please don't push your database credentials to GitHub.
27 |
28 |
29 | ## Getting started with Vagrant
30 |
31 | #### Prerequisites
32 | * [Vagrant](https://www.vagrantup.com)
33 | * [VirtualBox](https://www.virtualbox.org)
34 | * [composer](https://getcomposer.org)
35 |
36 | #### Steps
37 | 1. `git clone` this repository
38 | 2. `cd` into the cloned repository
39 | 3. `composer install`
40 | 4. `cp misc/.env.example .env`
41 | 5. `cp misc/Vagrantfile .`
42 | 6. `vagrant up`
43 |
44 | From here, you should be able to access http://localhost:8080/. This website is served using NGINX & PHP 7.
45 |
46 |
47 | ## Getting started with Docker
48 |
49 | #### Prerequisites
50 | * [Docker](https://www.docker.com)
51 | * [Docker Compose](https://docs.docker.com/compose)
52 | * [composer](https://getcomposer.org)
53 |
54 | #### Steps
55 | 1. `git clone` this repository
56 | 2. `cd` into the cloned repository
57 | 3. `composer install`
58 | 4. `cp misc/.env.example .env`
59 | 5. `cp misc/Dockerfile .`
60 | 6. `cp misc/docker-compose.yml .`
61 | 7. `docker-compose up`
62 |
63 | Run `docker-compose port application 80` to find the public port this application is running on.
64 |
65 |
66 | ## Batteries not included
67 | I've intentionally made this project as simplistic as possible. A lot of things are left up to you to design and implement. On the plus side, you won't have to remove much boilerplate.
68 |
69 | Below you will find instructions on how to implement a few things, feel free to contribute more examples :).
70 |
71 | ### PDO (database)
72 | Edit `bootstrap/app.php` and add the following:
73 | ```php
74 | $container
75 | ->add('PDO')
76 | ->withArgument(getenv('DB_CONN'))
77 | ->withArgument(getenv('DB_USER'))
78 | ->withArgument(getenv('DB_PASS'));
79 | ```
80 |
81 | You will also need to add some values to your `.env`
82 | ```
83 | # Database access
84 | DB_CONN=mysql:host=127.0.0.1;dbname=frameworkless;charset=utf8
85 | DB_USER=fwl_user
86 | DB_PASS=hopefullysecure
87 | ```
88 |
89 | Now, from a controller:
90 | ```php
91 | private $pdo;
92 |
93 | public function __construct(PDO $pdo)
94 | {
95 | $this->pdo = $pdo;
96 | }
97 |
98 | public function get()
99 | {
100 | $handle = $this->pdo->prepare('SELECT * FROM `todos`');
101 | $handle->execute();
102 | return new JsonResponse($handle->fetchAll(PDO::FETCH_ASSOC));
103 | }
104 | ```
105 |
106 | ### Spot (database, ORM)
107 | ```
108 | composer require vlucas/spot2
109 | ```
110 |
111 | from here, edit `bootstrap/app.php` and add the following:
112 | ```php
113 | $db = new \Spot\Config();
114 | $db->addConnection('mysql', [
115 | 'dbname' => getenv('DB_NAME'),
116 | 'user' => getenv('DB_USER'),
117 | 'password' => getenv('DB_PASS'),
118 | 'host' => getenv('DB_HOST')
119 | ]);
120 |
121 | $container
122 | ->add('\Spot\Locator')
123 | ->withArgument($db);
124 | ```
125 |
126 | You will also need to add some values to your `.env`
127 | ```
128 | # Database access
129 | DB_CONN=mysql:host=127.0.0.1;dbname=frameworkless;charset=utf8
130 | DB_USER=fwl_user
131 | DB_PASS=hopefullysecure
132 | ```
133 |
134 | Now you can create models! I recommend adding them under a src/Models directory for separation. For example, `src/Models/Posts.php`:
135 | ```php
136 | namespace Frameworkless\Models;
137 |
138 | use Spot\Entity;
139 |
140 | class Posts extends Entity
141 | {
142 | protected static $table = 'posts';
143 | // etc.
144 | }
145 | ```
146 |
147 | And finally from your controller:
148 | ```php
149 | private $spot;
150 |
151 | public function __construct(\Spot\Locator $spot)
152 | {
153 | $this->spot = $spot;
154 | }
155 |
156 | public function get()
157 | {
158 | $posts = $this->spot->mapper('Frameworkless\Models\Posts')->all();
159 | return new Response('Here are your posts ' . print_r($posts, true));
160 | }
161 | ```
162 |
163 |
164 | ## Contributing
165 | Submit a pull request :) I'll be friendly
166 |
167 |
168 | Thanks to **@waxim** for contributing the Spot example
169 |
170 | Thanks to **@jaakkytt** for clearing up part of this readme
171 |
172 | Thanks to **@Luciam91** for contributing Docker support
173 |
--------------------------------------------------------------------------------
/bootstrap/app.php:
--------------------------------------------------------------------------------
1 | prepare($request)
26 | ->send();
27 | return;
28 | }
29 | $dotenv = new Dotenv\Dotenv(__DIR__ . '/../');
30 | $dotenv->load();
31 |
32 |
33 | /*
34 | * Error handler
35 | */
36 | $whoops = new Run;
37 | if (getenv('MODE') === 'dev') {
38 | $whoops->pushHandler(
39 | new PrettyPageHandler()
40 | );
41 | } else {
42 | $whoops->pushHandler(
43 | // Using the pretty error handler in production is likely a bad idea.
44 | // Instead respond with a generic error message.
45 | function () use ($request) {
46 | Response::create('An internal server error has occurred.', Response::HTTP_INTERNAL_SERVER_ERROR)
47 | ->prepare($request)
48 | ->send();
49 | }
50 | );
51 | }
52 | $whoops->register();
53 |
54 |
55 | /*
56 | * Container setup
57 | */
58 | $container = new Container();
59 | $container
60 | ->add('Twig_Environment')
61 | ->withArgument(
62 | // Our twig templates are stored inside of the views directory.
63 | new Twig_Loader_Filesystem(__DIR__ . '/../views/')
64 | );
65 | $container
66 | ->delegate(
67 | // Auto-wiring based on constructor typehints.
68 | // http://container.thephpleague.com/auto-wiring
69 | new ReflectionContainer()
70 | );
71 |
72 |
73 | /*
74 | * Routes
75 | */
76 | $dispatcher = FastRoute\simpleDispatcher(function (FastRoute\RouteCollector $r) {
77 | $routes = require __DIR__ . '/routes.php';
78 | foreach ($routes as $route) {
79 | $r->addRoute($route[0], $route[1], $route[2]);
80 | }
81 | });
82 |
83 |
84 | /*
85 | * Dispatch
86 | */
87 | $routeInfo = $dispatcher->dispatch($request->getMethod(), $request->getPathInfo());
88 | switch ($routeInfo[0]) {
89 | case Dispatcher::NOT_FOUND:
90 | // No matching route was found.
91 | Response::create("404 Not Found", Response::HTTP_NOT_FOUND)
92 | ->prepare($request)
93 | ->send();
94 | break;
95 | case Dispatcher::METHOD_NOT_ALLOWED:
96 | // A matching route was found, but the wrong HTTP method was used.
97 | Response::create("405 Method Not Allowed", Response::HTTP_METHOD_NOT_ALLOWED)
98 | ->prepare($request)
99 | ->send();
100 | break;
101 | case Dispatcher::FOUND:
102 | // Fully qualified class name of the controller
103 | $fqcn = $routeInfo[1][0];
104 | // Controller method responsible for handling the request
105 | $routeMethod = $routeInfo[1][1];
106 | // Route parameters (ex. /products/{category}/{id})
107 | $routeParams = $routeInfo[2];
108 |
109 | // Obtain an instance of route's controller
110 | // Resolves constructor dependencies using the container
111 | $controller = $container->get($fqcn);
112 |
113 | // Generate a response by invoking the appropriate route method in the controller
114 | $response = $controller->$routeMethod($routeParams);
115 | if ($response instanceof Response) {
116 | // Send the generated response back to the user
117 | $response
118 | ->prepare($request)
119 | ->send();
120 | }
121 | break;
122 | default:
123 | // According to the dispatch(..) method's documentation this shouldn't happen.
124 | // But it's here anyways just to cover all of our bases.
125 | Response::create('Received unexpected response from dispatcher.', Response::HTTP_INTERNAL_SERVER_ERROR)
126 | ->prepare($request)
127 | ->send();
128 | return;
129 | }
130 |
--------------------------------------------------------------------------------
/bootstrap/routes.php:
--------------------------------------------------------------------------------
1 | =5.4.0"
114 | },
115 | "provide": {
116 | "container-interop/container-interop-implementation": "^1.1"
117 | },
118 | "replace": {
119 | "orno/di": "~2.0"
120 | },
121 | "require-dev": {
122 | "phpunit/phpunit": "4.*"
123 | },
124 | "type": "library",
125 | "extra": {
126 | "branch-alias": {
127 | "dev-master": "2.x-dev",
128 | "dev-1.x": "1.x-dev"
129 | }
130 | },
131 | "autoload": {
132 | "psr-4": {
133 | "League\\Container\\": "src"
134 | }
135 | },
136 | "notification-url": "https://packagist.org/downloads/",
137 | "license": [
138 | "MIT"
139 | ],
140 | "authors": [
141 | {
142 | "name": "Phil Bennett",
143 | "email": "philipobenito@gmail.com",
144 | "homepage": "http://www.philipobenito.com",
145 | "role": "Developer"
146 | }
147 | ],
148 | "description": "A fast and intuitive dependency injection container.",
149 | "homepage": "https://github.com/thephpleague/container",
150 | "keywords": [
151 | "container",
152 | "dependency",
153 | "di",
154 | "injection",
155 | "league",
156 | "provider",
157 | "service"
158 | ],
159 | "time": "2016-03-17 11:07:59"
160 | },
161 | {
162 | "name": "nikic/fast-route",
163 | "version": "v1.0.1",
164 | "source": {
165 | "type": "git",
166 | "url": "https://github.com/nikic/FastRoute.git",
167 | "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af"
168 | },
169 | "dist": {
170 | "type": "zip",
171 | "url": "https://api.github.com/repos/nikic/FastRoute/zipball/8ea928195fa9b907f0d6e48312d323c1a13cc2af",
172 | "reference": "8ea928195fa9b907f0d6e48312d323c1a13cc2af",
173 | "shasum": ""
174 | },
175 | "require": {
176 | "php": ">=5.4.0"
177 | },
178 | "type": "library",
179 | "autoload": {
180 | "psr-4": {
181 | "FastRoute\\": "src/"
182 | },
183 | "files": [
184 | "src/functions.php"
185 | ]
186 | },
187 | "notification-url": "https://packagist.org/downloads/",
188 | "license": [
189 | "BSD-3-Clause"
190 | ],
191 | "authors": [
192 | {
193 | "name": "Nikita Popov",
194 | "email": "nikic@php.net"
195 | }
196 | ],
197 | "description": "Fast request router for PHP",
198 | "keywords": [
199 | "router",
200 | "routing"
201 | ],
202 | "time": "2016-06-12 19:08:51"
203 | },
204 | {
205 | "name": "symfony/http-foundation",
206 | "version": "v3.2.0",
207 | "source": {
208 | "type": "git",
209 | "url": "https://github.com/symfony/http-foundation.git",
210 | "reference": "9963bc29d7f4398b137dd8efc480efe54fdbe5f1"
211 | },
212 | "dist": {
213 | "type": "zip",
214 | "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9963bc29d7f4398b137dd8efc480efe54fdbe5f1",
215 | "reference": "9963bc29d7f4398b137dd8efc480efe54fdbe5f1",
216 | "shasum": ""
217 | },
218 | "require": {
219 | "php": ">=5.5.9",
220 | "symfony/polyfill-mbstring": "~1.1"
221 | },
222 | "require-dev": {
223 | "symfony/expression-language": "~2.8|~3.0"
224 | },
225 | "type": "library",
226 | "extra": {
227 | "branch-alias": {
228 | "dev-master": "3.2-dev"
229 | }
230 | },
231 | "autoload": {
232 | "psr-4": {
233 | "Symfony\\Component\\HttpFoundation\\": ""
234 | },
235 | "exclude-from-classmap": [
236 | "/Tests/"
237 | ]
238 | },
239 | "notification-url": "https://packagist.org/downloads/",
240 | "license": [
241 | "MIT"
242 | ],
243 | "authors": [
244 | {
245 | "name": "Fabien Potencier",
246 | "email": "fabien@symfony.com"
247 | },
248 | {
249 | "name": "Symfony Community",
250 | "homepage": "https://symfony.com/contributors"
251 | }
252 | ],
253 | "description": "Symfony HttpFoundation Component",
254 | "homepage": "https://symfony.com",
255 | "time": "2016-11-27 04:21:38"
256 | },
257 | {
258 | "name": "symfony/polyfill-mbstring",
259 | "version": "v1.3.0",
260 | "source": {
261 | "type": "git",
262 | "url": "https://github.com/symfony/polyfill-mbstring.git",
263 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4"
264 | },
265 | "dist": {
266 | "type": "zip",
267 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4",
268 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4",
269 | "shasum": ""
270 | },
271 | "require": {
272 | "php": ">=5.3.3"
273 | },
274 | "suggest": {
275 | "ext-mbstring": "For best performance"
276 | },
277 | "type": "library",
278 | "extra": {
279 | "branch-alias": {
280 | "dev-master": "1.3-dev"
281 | }
282 | },
283 | "autoload": {
284 | "psr-4": {
285 | "Symfony\\Polyfill\\Mbstring\\": ""
286 | },
287 | "files": [
288 | "bootstrap.php"
289 | ]
290 | },
291 | "notification-url": "https://packagist.org/downloads/",
292 | "license": [
293 | "MIT"
294 | ],
295 | "authors": [
296 | {
297 | "name": "Nicolas Grekas",
298 | "email": "p@tchwork.com"
299 | },
300 | {
301 | "name": "Symfony Community",
302 | "homepage": "https://symfony.com/contributors"
303 | }
304 | ],
305 | "description": "Symfony polyfill for the Mbstring extension",
306 | "homepage": "https://symfony.com",
307 | "keywords": [
308 | "compatibility",
309 | "mbstring",
310 | "polyfill",
311 | "portable",
312 | "shim"
313 | ],
314 | "time": "2016-11-14 01:06:16"
315 | },
316 | {
317 | "name": "symfony/var-dumper",
318 | "version": "v3.2.0",
319 | "source": {
320 | "type": "git",
321 | "url": "https://github.com/symfony/var-dumper.git",
322 | "reference": "86f4e8aeb07bd5fb467f6bdd599a30298d19fa5f"
323 | },
324 | "dist": {
325 | "type": "zip",
326 | "url": "https://api.github.com/repos/symfony/var-dumper/zipball/86f4e8aeb07bd5fb467f6bdd599a30298d19fa5f",
327 | "reference": "86f4e8aeb07bd5fb467f6bdd599a30298d19fa5f",
328 | "shasum": ""
329 | },
330 | "require": {
331 | "php": ">=5.5.9",
332 | "symfony/polyfill-mbstring": "~1.0"
333 | },
334 | "require-dev": {
335 | "twig/twig": "~1.20|~2.0"
336 | },
337 | "suggest": {
338 | "ext-symfony_debug": ""
339 | },
340 | "type": "library",
341 | "extra": {
342 | "branch-alias": {
343 | "dev-master": "3.2-dev"
344 | }
345 | },
346 | "autoload": {
347 | "files": [
348 | "Resources/functions/dump.php"
349 | ],
350 | "psr-4": {
351 | "Symfony\\Component\\VarDumper\\": ""
352 | },
353 | "exclude-from-classmap": [
354 | "/Tests/"
355 | ]
356 | },
357 | "notification-url": "https://packagist.org/downloads/",
358 | "license": [
359 | "MIT"
360 | ],
361 | "authors": [
362 | {
363 | "name": "Nicolas Grekas",
364 | "email": "p@tchwork.com"
365 | },
366 | {
367 | "name": "Symfony Community",
368 | "homepage": "https://symfony.com/contributors"
369 | }
370 | ],
371 | "description": "Symfony mechanism for exploring and dumping PHP variables",
372 | "homepage": "https://symfony.com",
373 | "keywords": [
374 | "debug",
375 | "dump"
376 | ],
377 | "time": "2016-11-29 10:33:09"
378 | },
379 | {
380 | "name": "twig/twig",
381 | "version": "v1.28.2",
382 | "source": {
383 | "type": "git",
384 | "url": "https://github.com/twigphp/Twig.git",
385 | "reference": "b22ce0eb070e41f7cba65d78fe216de29726459c"
386 | },
387 | "dist": {
388 | "type": "zip",
389 | "url": "https://api.github.com/repos/twigphp/Twig/zipball/b22ce0eb070e41f7cba65d78fe216de29726459c",
390 | "reference": "b22ce0eb070e41f7cba65d78fe216de29726459c",
391 | "shasum": ""
392 | },
393 | "require": {
394 | "php": ">=5.2.7"
395 | },
396 | "require-dev": {
397 | "symfony/debug": "~2.7",
398 | "symfony/phpunit-bridge": "~3.2@dev"
399 | },
400 | "type": "library",
401 | "extra": {
402 | "branch-alias": {
403 | "dev-master": "1.28-dev"
404 | }
405 | },
406 | "autoload": {
407 | "psr-0": {
408 | "Twig_": "lib/"
409 | }
410 | },
411 | "notification-url": "https://packagist.org/downloads/",
412 | "license": [
413 | "BSD-3-Clause"
414 | ],
415 | "authors": [
416 | {
417 | "name": "Fabien Potencier",
418 | "email": "fabien@symfony.com",
419 | "homepage": "http://fabien.potencier.org",
420 | "role": "Lead Developer"
421 | },
422 | {
423 | "name": "Armin Ronacher",
424 | "email": "armin.ronacher@active-4.com",
425 | "role": "Project Founder"
426 | },
427 | {
428 | "name": "Twig Team",
429 | "homepage": "http://twig.sensiolabs.org/contributors",
430 | "role": "Contributors"
431 | }
432 | ],
433 | "description": "Twig, the flexible, fast, and secure template language for PHP",
434 | "homepage": "http://twig.sensiolabs.org",
435 | "keywords": [
436 | "templating"
437 | ],
438 | "time": "2016-11-23 18:41:40"
439 | },
440 | {
441 | "name": "vlucas/phpdotenv",
442 | "version": "v2.4.0",
443 | "source": {
444 | "type": "git",
445 | "url": "https://github.com/vlucas/phpdotenv.git",
446 | "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c"
447 | },
448 | "dist": {
449 | "type": "zip",
450 | "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c",
451 | "reference": "3cc116adbe4b11be5ec557bf1d24dc5e3a21d18c",
452 | "shasum": ""
453 | },
454 | "require": {
455 | "php": ">=5.3.9"
456 | },
457 | "require-dev": {
458 | "phpunit/phpunit": "^4.8 || ^5.0"
459 | },
460 | "type": "library",
461 | "extra": {
462 | "branch-alias": {
463 | "dev-master": "2.4-dev"
464 | }
465 | },
466 | "autoload": {
467 | "psr-4": {
468 | "Dotenv\\": "src/"
469 | }
470 | },
471 | "notification-url": "https://packagist.org/downloads/",
472 | "license": [
473 | "BSD-3-Clause-Attribution"
474 | ],
475 | "authors": [
476 | {
477 | "name": "Vance Lucas",
478 | "email": "vance@vancelucas.com",
479 | "homepage": "http://www.vancelucas.com"
480 | }
481 | ],
482 | "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
483 | "keywords": [
484 | "dotenv",
485 | "env",
486 | "environment"
487 | ],
488 | "time": "2016-09-01 10:05:43"
489 | }
490 | ],
491 | "packages-dev": [],
492 | "aliases": [],
493 | "minimum-stability": "stable",
494 | "stability-flags": [],
495 | "prefer-stable": false,
496 | "prefer-lowest": false,
497 | "platform": [],
498 | "platform-dev": []
499 | }
500 |
--------------------------------------------------------------------------------
/misc/.env.example:
--------------------------------------------------------------------------------
1 | # If this is set to dev, an error handler will be shown. Not good for production.
2 | MODE=dev
3 |
4 | # Note: Instead of hard coding credentials and pushing them to GitHub,
5 | # put them in this file (.env, *not* in your .env.example) which is .gitignore'd.
6 |
--------------------------------------------------------------------------------
/misc/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:7-fpm
2 |
3 | RUN apt-get update \
4 | && apt-get install -y nginx \
5 | && apt-get clean && apt-get purge \
6 | && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
7 |
8 | EXPOSE 80 443
9 |
10 | WORKDIR /opt/frameworkless/public
11 |
12 | ENTRYPOINT /usr/local/sbin/php-fpm -D && /usr/sbin/nginx -g 'daemon off;'
--------------------------------------------------------------------------------
/misc/Vagrantfile:
--------------------------------------------------------------------------------
1 | $script = <<'SCRIPT'
2 | #!/usr/bin/env bash
3 | # ################################################### #
4 | # ! Frameworkless: Initial setup for Ubuntu 16.04 ! #
5 | # ################################################### #
6 |
7 | # Install NGINX & PHP 7
8 | sudo apt-get update
9 | sudo apt-get install -y nginx php7.0-fpm
10 |
11 | # Symlink the nginx config and restart nginx
12 | sudo rm -f /etc/nginx/sites-available/*
13 | sudo rm -f /etc/nginx/sites-enabled/*
14 | sudo ln -s /opt/frameworkless/misc/config/nginx/vagrant.conf /etc/nginx/sites-enabled/default
15 | sudo systemctl restart nginx
16 | SCRIPT
17 |
18 | Vagrant.configure(2) do |config|
19 | config.vm.box = "ubuntu/xenial64"
20 | config.vm.network "forwarded_port", guest: 80, host: 8080
21 |
22 | config.vm.synced_folder ".", "/vagrant", disabled: true
23 | config.vm.synced_folder ".", "/opt/frameworkless"
24 |
25 | config.ssh.insert_key = true
26 |
27 | config.vm.provision "shell", inline: $script
28 | end
29 |
--------------------------------------------------------------------------------
/misc/config/nginx/docker.conf:
--------------------------------------------------------------------------------
1 | server {
2 | root /opt/frameworkless/public;
3 | index index.php;
4 |
5 | # Disable cache (FOR DEVELOPMENT SERVER ONLY)
6 | expires off;
7 | sendfile off;
8 |
9 | # Try the requested file first, otherwise use the front controller
10 | location / {
11 | try_files $uri /index.php?$query_string;
12 | }
13 |
14 | # Interpret PHP
15 | location ~ \.php$ {
16 | try_files $uri =404;
17 | fastcgi_split_path_info ^(.+\.php)(/.+)$;
18 | fastcgi_pass 127.0.0.1:9000;
19 | fastcgi_index index.php;
20 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
21 | include fastcgi_params;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/misc/config/nginx/vagrant.conf:
--------------------------------------------------------------------------------
1 | server {
2 | root /opt/frameworkless/public;
3 | index index.php;
4 |
5 | # Disable cache (FOR DEVELOPMENT SERVER ONLY)
6 | expires off;
7 | sendfile off;
8 |
9 | # Try the requested file first, otherwise use the front controller
10 | location / {
11 | try_files $uri /index.php?$query_string;
12 | }
13 |
14 | # Interpret PHP
15 | location ~ \.php$ {
16 | try_files $uri =404;
17 | fastcgi_split_path_info ^(.+\.php)(/.+)$;
18 | fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
19 | fastcgi_index index.php;
20 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
21 | include fastcgi_params;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/misc/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 |
3 | services:
4 | application:
5 | build:
6 | context: .
7 | dockerfile: Dockerfile
8 | volumes:
9 | - ./misc/config/nginx/docker.conf:/etc/nginx/sites-enabled/default
10 | - .:/opt/frameworkless
11 | ports:
12 | - 80
13 |
--------------------------------------------------------------------------------
/public/assets/css/styles.css:
--------------------------------------------------------------------------------
1 | /*
2 | Original CSS taken from http://evenbettermotherfucking.website
3 | */
4 |
5 | body {
6 | margin: 2% auto;
7 | background: #f2f2f2;
8 | color: #444444;
9 | font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;
10 | font-size: 14px;
11 | line-height: 1.6;
12 | text-shadow: 0 1px 0 #ffffff;
13 | min-width: 768px;
14 | max-width: 50%;
15 | padding: 1em;
16 | }
17 |
18 | code {
19 | background: white;
20 | }
21 |
22 | a {
23 | border-bottom: 1px solid #444444;
24 | color: #444444;
25 | text-decoration: none;
26 | }
27 |
28 | a:hover {
29 | border-bottom: 0;
30 | }
31 |
32 | h1, h2 {
33 | line-height: 1.3;
34 | }
35 | ul li {
36 | padding-bottom: 5px;
37 | }
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 | class GreetController
13 | {
14 | /** @var Twig_Environment */
15 | private $twig;
16 |
17 | /**
18 | * GreetController, constructed by the container
19 | *
20 | * @param Twig_Environment $twig
21 | */
22 | public function __construct(Twig_Environment $twig)
23 | {
24 | $this->twig = $twig;
25 | }
26 |
27 | /**
28 | * Name reversing thing
29 | *
30 | * @param array $routeParams
31 | * @return Response
32 | */
33 | public function greet($routeParams)
34 | {
35 | $response = new Response(
36 | $this->twig->render('pages/greet.html.twig', [
37 | 'name' => strrev($routeParams['name'])
38 | ])
39 | );
40 | return $response;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Controllers/IndexController.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | class IndexController
14 | {
15 | /** @var Twig_Environment */
16 | private $twig;
17 |
18 | /**
19 | * IndexController, constructed by the container
20 | *
21 | * @param Twig_Environment $twig
22 | */
23 | public function __construct(Twig_Environment $twig)
24 | {
25 | $this->twig = $twig;
26 | }
27 |
28 | /**
29 | * Index page
30 | *
31 | * @return Response
32 | */
33 | public function index()
34 | {
35 | return new Response($this->twig->render('pages/index.html.twig'));
36 | }
37 |
38 | /**
39 | * Throw an exception (for testing the error handler)
40 | *
41 | * @throws Exception
42 | */
43 | public function exception()
44 | {
45 | throw new Exception('Test exception');
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/views/base.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {% block title %}Default title{% endblock %}
5 |
6 |
7 |
8 | {% block content %}Default content{% endblock %}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/views/pages/greet.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block title %}
4 | Name
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
9 |
Hello {{ name }}!
10 |
I really need to create a better test page.
11 |
12 | {% endblock %}
13 |
--------------------------------------------------------------------------------
/views/pages/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block title %}
4 | Welcome
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
9 |
Yay, it works!
10 |
11 |
Example pages
12 |
20 |
21 | {% endblock %}
22 |
--------------------------------------------------------------------------------