Summary from http://fabien.potencier.org/article/51/create-your-own-framework-on-top-of-the-symfony2-components-part-1 -12
$ mkdir framework
$ cd
framework
$ vi composer.json
{
"require": {
"symfony/class-loader": "2.1.*"
}
}
:wq
$ wget http://getcomposer.org/composer.phar
$
# or
$ curl -O http://getcomposer.org/composer.phar
$ php composer.phar install
$ vi autoload.php
<?php // framework/autoload.php require_once __DIR__.'/vendor/symfony/class-loader/Symfony/Component/ClassLoader/UniversalClassLoader.php'; use Symfony\Component\ClassLoader\UniversalClassLoader; $loader = new UniversalClassLoader(); $loader->register();
:wq
$ php autoload.php
$ vi index.php (error version if no get parameter supply)
<?php // framework/index.php $input = $_GET['name']; printf('Hello %s', $input);
:wq
=> go to http://localhost and it will show hello
$ vi index.php (unsecure version : Internet security issue, XSS (Cross-Site Scripting))
<?php // framework/index.php $input = isset($_GET['name']) ? $_GET['name'] : 'World'; printf('Hello %s', $input);
:wq
$vi index.php (secure versinon)
<?php $input = isset($_GET['name']) ? $_GET['name'] : 'World'; header('Content-Type: text/html; charset=utf-8'); printf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8'));
:wq
==>test unit
vi test.php
<?php // framework/test.php class IndexTest extends \PHPUnit_Framework_TestCase { public function testHello() { $_GET['name'] = 'Fabien'; ob_start(); include 'index.php'; $content = ob_get_clean(); $this->assertEquals('Hello Fabien', $content); } }
:wq
=> At this point, if you are not convinced that security and testing are indeed two very good reasons to stop writing code the old way and adopt a framework instead
In PHP, the request is represented by global variables ($_GET
,$_POST
,$_FILE
,$_COOKIE
,$_SESSION
...) and the response is generated by functions (echo
,header
,setcookie
, ...).
=>better code : Object-Oriented approach, Symfony2 HttpFoundation component
$ vi framework/composer.json { "require": { "symfony/class-loader": "2.1.*", "symfony/http-foundation": "2.1.*" } }
:wq
php composer.phar update
vi autoload.php add at bootom :
<?php // framework/autoload.php $loader->registerNamespace('Symfony\\Component\\HttpFoundation', __DIR__.'/vendor/symfony/http-foundation');
wq:
$ vi index.php
<?php // framework/index.php require_once __DIR__.'/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $input = $request->get('name', 'World'); $response = new Response(sprintf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8'))); $response->send();
:wq
$ vi bye.php
<?php // framework/bye.php require_once __DIR__.'/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $response = new Response('Goodbye!'); $response->send();
:wq
$ vi init.php
<?php // framework/init.php require_once __DIR__.'/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $response = new Response();
:wq
$ vi index.php<?php // framework/index.php require_once __DIR__.'/init.php'; $input = $request->get('name', 'World'); $response->setContent(sprintf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8'))); $response->send();
wq
$ vi bye.php
<?php // framework/bye.php require_once __DIR__.'/init.php'; $response->setContent('Goodbye!'); $response->send();
:wq
$ vi front.php
<?php // framework/front.php require_once __DIR__.'/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $response = new Response(); $map = array( '/hello' => __DIR__.'/hello.php', '/bye' => __DIR__.'/bye.php', ); $path = $request->getPathInfo(); if (isset($map[$path])) { require $map[$path]; } else { $response->setStatusCode(404); $response->setContent('Not Found'); } $response->send();
:wq
$ vi hello.php
<?php // framework/hello.php $input = $request->get('name', 'World'); $response->setContent(sprintf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8')));
:wq
==> http://example.com/front.php/hello?name=Fabien
==>
http://example.com/front.php/bye
Now that the web server always access the same script (front.php
) for all
our pages, we can secure our code further by moving all other PHP files
outside the web root directory:example.com
??? composer.json
? src
? ??? autoload.php
? ??? pages
? ??? hello.php
? ??? bye.php
??? vendor
??? web
??? front.php
Now, configure your web server root directory to point to
web/
and all
other files won't be accessible from the client anymore.vi src/pages/hello.php
<!-- example.com/src/pages/hello.php --> <?php $name = $request->get('name', 'World') ?> Hello <?php echo htmlspecialchars($name, ENT_QUOTES, 'UTF-8') ?>
:wq
$ vi web/front.php
<?php // example.com/web/front.php require_once __DIR__.'/../src/autoload.php'; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $request = Request::createFromGlobals(); $response = new Response(); $map = array( '/hello' => __DIR__.'/../src/pages/hello.php', '/bye' => __DIR__.'/../src/pages/bye.php', ); $path = $request->getPathInfo(); if (isset($map[$path])) { ob_start(); include $map[$path]; $response->setContent(ob_get_clean()); } else { $response->setStatusCode(404); $response->setContent('Not Found'); } $response->send();
:wq
..
.
.
.
.
.
.
.
That's it! Our application has now four different layers and each of them has a well defined goal:
web/front.php
: The front controller; the only exposed PHP code that makes the interface with the client (it gets the Request and sends the Response) and provides the boiler-plate code to initialize the framework and our application;src/Simplex
: The reusable framework code that abstracts the handling of incoming Requests (by the way, it makes your controllers/templates easily testable -- more about that later on);src/Calendar
: Our application specific code (the controllers and the model);src/app.php
: The application configuration/framework customization.
No comments:
Post a Comment