An application framework is a set of functions, classes, and conventions that make it easier to accomplish common tasks. Lots of programming languages have popular frameworks, and PHP is no exception. This chapter provides an overview of three popular PHP frameworks. These frameworks speed your journey from nothing to a functioning web application.
Frameworks aimed at web development generally provide standard ways to accomplish at least the following tasks:
By using a framework, you save time compared to implementing all of the framework’s functionality yourself. You may also be able to jump-start new developers coming to work with you if they are familiar with the framework. The trade-off is that you must invest time in learning the framework and adapting to its conventions of how to accomplish things.
The three frameworks explored in this chapter are Laravel, Symfony, and Zend Framework. Each provides a very different kind of solution to the “framework” question. They differ in how they are installed, what their documentation explains, how they balance simplicity and capability, and what you do to find more information when you’re stumped.
There are many other PHP frameworks out there. The three in this chapter are included because they are some of the most popular and most capable, but the exclusion of other frameworks should not be taken as an injunction against trying something else. The Internet abounds with guides that attempt to answer the question “What PHP framework should I use?” For up-to-date information, check out the PHP Frameworks topic on Quora or search for php framework on Hacker News or SitePoint.
Laravel’s creator describes it as a framework for people who value “elegance, simplicity, and readability.” It has well-thought-out documentation, a vibrant ecosystem of users, and available hosting providers and tutorials.
To install Laravel, run the command php composer.phar global require laravel/installer=~1.1". Then, to create a new web project that uses Laravel, run laravel new project-name,1 substituting your project name for project-name. For example, running laravel new menu creates a directory called menu and populates it with the necessary code and configuration scaffolding for Laravel to work properly.
To see the scaffolding in action, fire up the built-in PHP web server by pointing it at server.php in your project directory. For example, php -S localhost:8000 -t menu2/public menu/server.php lets you access the new Laravel project in the menu subdirectory at http://localhost:8000.
Laravel’s routing is controlled by the code in app/Http/routes.php. Each call to a static method in the Route class tells Laravel what to do when an HTTP request comes in with a certain method and URL path. The code in Example 18-1 tells Laravel to respond to a GET request for /show.
Route::get('/show',function(){$now=newDateTime();$items=["Fried Potatoes","Boiled Potatoes","Baked Potatoes"];returnview('show-menu',['when'=>$now,'what'=>$items]);});
In Example 18-1, the call to Route::get() tells Laravel that it should be responding to HTTP GET (not POST) requests, and the first argument of /show tells Laravel that this Route::get() call provides information on what to do
when the URL /show is visited. The second argument to Route::get() is the function that Laravel runs to compute the response to GET /show. This function sets up two variables, $now and $items, and then passes them to the show-menu view as keys when and what.
A view is a template that contains presentation logic—what your application should display. The view() function in Laravel looks for a file in a predefined location and then runs the PHP code in that file to generate a response. The call to view('show-menu') tells Laravel to look for a file named show-menu.php in the resources/views directory. Example 18-2 contains the code for this view.
<p>At<?phpecho$when->format('g:i a')?>, here is what's available: </p><ul><?phpforeach($whatas$item){?><li><?phpecho$item?></li><?php}?></ul>
The view is just plain PHP. Any data coming from an external source such as a user or database should be properly escaped to prevent cross-site scripting problems, as discussed in “HTML and JavaScript”. Laravel includes support for the Blade templating engine, which makes many things easier, including escaping output by default.
Symfony describes itself as both a set of reusable components and a framework for web projects. This means that even if you don’t use its framework for request routing or other web-related tasks, you can still use its individual components for tasks such as templating, managing configuration files, or debugging.
Like Laravel, Symfony has a command-line program used to create and manage projects. Install the symfony program and rename the downloaded installer file to symfony. Move it into a directory in your system path. On Linux or OS X, make the symfony program executable by typing chmod a+x /path/to/symfony (where /path/to/symfony is the full path of the place you’ve put the symfony program).
Then, to create a new web project that uses Symfony, run symfony new project-name, substituting your project name for project-name. For example, running the command symfony new menu creates a directory called menu and populates it with the code and configuration scaffolding necessary for Symfony to work properly.
Symfony includes some glue that makes it easy to run your project in PHP’s built-in web server. Just change your current directory to your project directory (e.g., cd menu) and then run php app/console server:run. Then visit http://localhost:8000/ in your web browser, and you’ll see a “Welcome to Symfony” page complete with lots of interesting diagnostic information at the bottom.
With Symfony, routes are not specified in one central place. Instead, individual classes in the src/AppBundle/Controller directory define the methods that are triggered by the routes that the app handles. A special annotation in a comment next to a method indicates what route the method handles. Example 18-3 defines a handler for a GET /show request. Put it in MenuController.php in src/AppBundle/Controllers.
namespaceAppBundle\Controller;useSymfony\Bundle\FrameworkBundle\Controller\Controller;useSensio\Bundle\FrameworkExtraBundle\Configuration\Route;useSensio\Bundle\FrameworkExtraBundle\Configuration\Method;useSymfony\Component\HttpFoundation\Response;classMenuControllerextendsController{/*** @Route("/show")* @Method("GET")*/publicfunctionshowAction(){$now=new\DateTime();$items=["Fried Potatoes","Boiled Potatoes","Baked Potatoes"];return$this->render("show-menu.html.twig",['when'=>$now,'what'=>$items]);}}
In Example 18-3, the items in the comment before the showAction() method indicate the route that showAction() handles: URL path /show with method GET. The render() method returns a Symfony data structure that holds the contents of the response. Its first argument is the name of a view template file to use, and the second argument is data to pass to the template. It is possible to use plain PHP as a template language with Symfony, but its default setup is to use the Twig templating engine, so that’s what’s specified here.
Symfony’s view directory is app/Resources/views. This means that passing show-menu.html.twig to render() tells Symfony to look for app/Resources/views/show-menu.html.twig in your project directory. Save the contents of Example 18-4 in that place.
{% extends 'base.html.twig' %}
{% block body %}
<p> At {{ when|date("g:i a") }}, here is what's available: </p>
<ul>
{% for item in what %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endblock %}
In Twig, {% %} indicates a templating language command and {{ }} indicates a variable whose value (with proper HTML escaping) should be included in the output. Its syntax may take some getting used to, but Twig is a powerful and speedy templating language.
More so than the other two frameworks reviewed in this chapter, Zend Framework takes a “collection of components” approach. While this makes it easy to drop a component or two into an existing project without conforming to a particular file structure or request routing convention, it also means starting from scratch is a little more complicated.
To install a Zend Framework “skeleton” app into the menu directory that contains the basics necessary to get up and running, run the following Composer command all on one line:
composer create-project --no-interaction --stability="dev" zendframework/skeleton-application menu
Then, to make the built-in PHP web server serve up your new Zend Framework application, change into the project directory and run php -S localhost:8000 -t public/ public/index.php. Visit http://localhost:8000 to see the default front page of your new application.
Zend Framework organizes related application code into modules. In a big application, you can create separate modules for separate high-level parts of your program. For this small sample application, we’ll add code to the base Application module that’s already there. This module contains some default routing logic that maps paths under /Application to code in controller classes in a specific place in the filesystem. Example 18-5 shows a new MenuController.php. Save it in the module/Application/src/Application/Controller directory of your Zend Framework project.
namespaceApplication\Controller;useZend\Mvc\Controller\AbstractActionController;useZend\View\Model\ViewModel;classMenuControllerextendsAbstractActionController{publicfunctionshowAction(){$now=new\DateTime();$items=["Fried Potatoes","Boiled Potatoes","Baked Potatoes"];returnnewViewModel(array('when'=>$now,'what'=>$items));}}
Then, to tell the framework about your new class, find the section of module/Application/config/module.config.php that looks like this:
'controllers'=>array('invokables'=>array('Application\Controller\Index'=>'Application\Controller\IndexController'),),
And add this line as a second element in the invokables array:
'Application\Controller\Menu'=>'Application\Controller\MenuController'
Don’t forget to add a comma after 'Application\Controller\IndexController' so that the array elements have the proper syntax. When you’re done, this section of the config file should look like this:
'controllers'=>array('invokables'=>array('Application\Controller\Index'=>'Application\Controller\IndexController','Application\Controller\Menu'=>'Application\Controller\MenuController'),),
Now you’ve got a new controller and the framework knows how to use it. The last step is to add a view so the time and items information can be rendered. With Zend Framework, the default template language is just plain PHP. Save the code in Example 18-6 in module/Application/view/application/menu/show.phtml under your project directory.
<p>At<?phpecho$when->format("g:i a")?>, here is what's available: </p><ul><?phpforeach($whatas$item){?><li><?phpecho$this->escapeHtml($item)?></li><?php}?></ul>
The keys in the array passed to new ViewModel() in the controller are local variable names in the view. This makes accessing these values very straightforward. However, because the template language is plain PHP, HTML entities and other special characters are not escaped by default. Example 18-6 uses the escapeHtml() helper method to escape special characters in each item name.
This chapter covered:
1 This requires that the global composer binary directory be in your system’s $PATH. See “Running a PHP REPL” for more information.