by Andres Baravalle
This sessions borrows the name from the material collected by Josh Lockhart et al on phptherightway.com. It is your final PHP class and will focus on good practice in your PHP applications.
Some of the tecniques showed in the next slides require shell access and some familiarity with the shell. You will need to be able to use the shell to change directories and run files.
Some of this week's readings suggest to use curl or wget but they are not strictly required (as all the tools we have seen in the past weeks, both are Open Source and available for Windows, Mac and Linux).
As this is the final lecture, there is no set of activities for labs.
Namespaces are designed to solve two problems that developers find when creating or using re-usable code elements:
PHP Namespaces provide a way in which to group related classes, interfaces, functions and constants.
In PHP, namespaces apply only to classes, interfaces, functions and constants (not to global variables).
No non-PHP code before the namespace declaration!
<?php
namespace baravalle;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
<?php
namespace baravalle\im2801;
?>
You can alias (also called import) a namespace:
<?php
// this will be our root namespace
namespace uel;
use baravalle\im2801\Classname as Another;
// class baravalle\im2801\Classname is known as Another
// class baravalle\im2801\Classname is also accessible as \uel\Another
use baravalle\im2801 as module;
// class baravalle\im2801\Classname is now known as module\Classname
?>
Use namespaces to isolate your classes, functions and constants from other libraries that you might be using.
The PHP Framework Interop Group (FIG) is a group of PHP developers working on the most disparate projects, including:
The group is dedicated to interoperability and as such as published a number of style guides on coding in PHP
The group produced a set of standards covering different aspects of PHP programming.
We willl cover only PSR-0 to PSR-2 (and not in its entirety). For the full standard, please see the FIG website.
\<Vendor Name>\(<Namespace>\)*<Class Name>
Example:
<?php
namespace Vendor\Package;
use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;
class Foo extends Bar implements FooInterface
{
public function sampleFunction($a, $b = null) {
if ($a === $b) {
bar();
}
}
?>
Composer is a dependency manager for PHP. List your project’s dependencies in a composer.json
file and, with a few simple commands, Composer will automatically download your project’s dependencies and setup autoloading for you.
There are already a lot of PHP libraries that are compatible with Composer, ready to be used in your project. These “packages” are listed on Packagist, the official repository for Composer-compatible PHP libraries.
The installation requires two steps: step 1 to download the installer; step 2 to download composer:
"c:\Program Files (x86)\php\php.exe" installer
Applications using Composer will normally have the following folder structure:
/vendor
will include all the Composer packages/web
will be the (public) root of your web site; public files will be subfolders of /web\<Vendor Name>\<Namespace>\
(Composer is compliant with FIG-0)In the next slides we are going to look at the process step by step, starting from the installation.
Edit (or create) the file composer.json in the root of your application, including the packages that you want to load in json format:
{
"require": {
"silex/silex": "~1.1",
"symfony/expression-language": "*",
"symfony/form": "*",
"oryzone/boilerplate-bundle": "*"
}
}
Each line is normally a different package. In "symfony/form": "*"
, we are asking to install the latest version available of the package form from vendor symfony.
To install the packages, you need command line access.
In the command line, go to the root folder of your application and run php composer.phar update
Replace php with the path of your PHP executable (varies according to OS - in recent versions of Windows is in c:\Program Files (x86)\php\php.exe
).
To load the packages, include the file /vendor/autoload.php
in your application.
GIYF - possible packages include:
Beside Packagist, the other large PHP components repository is pear.php.net.
Selected PEAR components are often installed by default; many components are available both in PEAR and in Packagist.
"A software framework is a universal, reusable software platform to develop applications, products and solutions."
Wikipedia, 2013
While using frameworks is good practice, in the short term, writing code using a framework can take longer than writing custom code.
Using a frameworks improves software reuse and allows to integrate more easily reusable components.
The most popular PHP frameworks are:
They are all based on the Model-View-Controller (MVC) design pattern. Their popularity varies according to the different countries; in the last year, the most popular framework wordwide was CodeIgniter.
From the Yii documentation:
MVC aims to separate business logic from user interface considerations, so that developers can more easily change each part without affecting the other. In MVC:
If you implement the MVC design patter in your applications it is a good start (+ ideally a front controller or router).
In the next slides we will see how to use a lightweight framework, Silex. Silex is developed by the same team developing Synfony, but targetting a different type of projects.
We are going to develop a simple application (based on week 9 activities) that:
The application is visible here and the code is available here for inspection.
/src
: here will reside your app
/src/pages
: here will reside your views/vendor
: here will reside your components/web
: here will reside your front controller
/web/subfolders
: place in subfolders of web all theresources (e.g. js, images, css)This assumes that you have already installed Composer.
Use this as a starting point (and add extra components as needed)t:
{
"require": {
"silex/silex": "~1.1",
"symfony/expression-language": "*",
"symfony/form": "*",
"components/html5-boilerplate": "*",
}
}
Download the components:
php composer.phar update
Your index.php will just include your app.php file.
Your app.php file will:
<?php
// starts output buffering
ob_start();
// autoload the classes
require_once __DIR__ . '/../vendor/autoload.php';
// create the framework object
$app = new Silex\Application();
// now connect to the database
$connection = new MongoClient("mongodb://andres:*******@localhost/andres");
// use your own database name instead of andres (your student number)
$collection = $connection->andres->marks;
// router section
// this construct is called "anonymous function"
// or closure
$app->get('/', function() {
$title = "Home";
include_once(__DIR__ . "/../src/pages/home.php");
// stopping output buffering and capturing the include
$body = ob_get_clean();
// starting output buffering again
ob_start();
include_once(__DIR__ . "/../src/pages/template.php");
// stopping output buffering and returning
return ob_get_clean();
});
// another router
$app->get('/save-module', function() use ($collection) {
$title = "Saving record";
// doing sanity checks on $_GET
$student_number = filter_var($_GET["student_number"], FILTER_SANITIZE_STRING);
$module_number = filter_var($_GET["module_number"], FILTER_SANITIZE_STRING);
$mark = filter_var($_GET["mark"], FILTER_SANITIZE_NUMBER_INT);
// storing the data in an array
$result = array("student_number" => $student_number, "module_number" => $module_number, "mark" => $mark);
// and saving it in MongoDB
if($collection->insert($result)) {
$body = "<p>Insertion correct</p>";
}
else {
$body = "<p>Could not insert correctly.</p>";
}
include_once(__DIR__ . "/../src/pages/template.php");
// stopping output buffering and returning
return ob_get_clean();
});
$app->get('/list-modules', function() use ($collection) {
$title = "List modules";
$cursor = $collection->find();
$body = "<table>\n";
foreach ($cursor as $key => $val) {
$body .= "\t<tr>\n";
$body .= "\t\t<td>${val['student_number']}</td>\n";
$body .= "\t\t<td>${val['module_number']}</td>\n";
$body .= "\t\t<td>${val['mark']}</td>\n";
$body .= "\t</tr>\n";
}
$body .= "</table>";
include_once(__DIR__ . "/../src/pages/template.php");
return ob_get_clean();
});
// Run
$app->run();
Please note that the solution is simplified. Limitations include the basic template implementation and no .htaccess support.
These are the core readings for this week:
Lockhart, J. et al. (2013). PHP The Right Way. Available from http://www.phptherightway.com
Adermann, N. and Boggiano, J. (2013). Getting started. Available from http://getcomposer.org/doc/00-intro.md (ready the sections "Getting started", "Basic usage" and "Libraries")
SensioLabs.org (2013). Silex. Available from http://silex.sensiolabs.org/doc/usage.html