NomadPHP EU, June 2015 1
Getting Started with AuraChris TankersleyNomadPHP EU June 2015
NomadPHP EU, June 2015 2
Who Am I
• PHP Programmer for over 10 years• Work/know a lot of different
languages, even COBOL• Primarily do Zend Framework 2• https://github.com/dragonmantank
NomadPHP EU, June 2015 3
Professional Tools for Professional Applications
NomadPHP EU, June 2015 4
About Aura
• Started by Paul M. Jones• Maintained by him and the community• Originally a rewrite of Solar (not Solr)• There are three versions, 1.x, 2.x, and a 3.x!• Works well by themselves, or in supplied Bundles/Kernels/Projects
NomadPHP EU, June 2015 5
Requirements
• PHP 5.3 or PHP 5.4, depending on the package
NomadPHP EU, June 2015 6
Each Package is Self Contained
http://looselycoupled.info/
NomadPHP EU, June 2015 7
Getting Started
NomadPHP EU, June 2015 8
2 Steps
• Find a package you want on https://github.com/auraphp• Install via Composer
NomadPHP EU, June 2015 9
Winning was never so easy!
NomadPHP EU, June 2015 10
Aura is built to use whatever, whenever
• Aura.Filter• Aura.Router• Aura.Sql• Aura.SqlQuery• Aura.Di• Aura.Http• Aura.Html• Aura.Session
• Aura.Cli• Aura.View• Aura.Intl• Aura.Input• Aura.Includer• Aura.Dispatcher• Aura.Auth
NomadPHP EU, June 2015 11
Or go all in
• Aura.SqlMapper_Bundle• Aura.Framework_Project• Aura.Web_Project• Aura.Web_Kernel• Aura.Cli_Project• Aura.Cli_Kernel
NomadPHP EU, June 2015 12
Most Common Packages
NomadPHP EU, June 2015 13
Aura.Di
NomadPHP EU, June 2015 14
Dependency Injection, Not Service Location• Provides a way to lazily create services• Interface for providing Constructor and Setter Injection• Can provide auto resolution to injection, you should probably turn it
off though
NomadPHP EU, June 2015 15
use Aura\Di\Container as DiContainer;use Aura\Di\Factory as DiFactory;
$di = new DiContainer(new DiFactory());
$di->set('database.handler', function() use ($di) { $config = $di->get('config'); return new \Aura\Sql\ExtendedPdo( 'mysql:host='.$config['db']['host'].';dbname='.$config['db']['dbname'], $config['db']['username'], $config['db']['password'] );});
$di->params['Aura\SqlQuery\QueryFactory'] = array( 'db' => 'mysql');
$di->set('database.query_handler', $di->lazyNew('Aura\SqlQuery\QueryFactory'));
NomadPHP EU, June 2015 16
Aura.Router
NomadPHP EU, June 2015 17
Almost like a micro-framework
• Provides a way to match a route to a chunk of code• Can handle different HTTP verbs• Can filter parameters based on regex• Can set default parameters• Generate URLs from the attached routes
NomadPHP EU, June 2015 18
Setting up a Route
$router_factory = new Aura\Router\RouterFactory();$router = $router_factory->newInstance();$router ->addPost('bitbucket_webhook', '/api/v0/bitbucket/webhook/{token}') ->addTokens([ 'token' => '\w+', ]) ->addValues(array( 'controller' => 'bitbucket', 'action' => 'webhook', ));
NomadPHP EU, June 2015 19
Dispatching
$app = function ($request, $response) use($di, $router) { $server['REQUEST_METHOD'] = $request->getMethod(); $route = $router->match($request->getPath(), $server); if(!$route) { echo sprintf('[%s] %s 404', date('Y-m-d H:i:s'), $request->getPath()).PHP_EOL; $response->writeHead(404, array('Content-Type' => 'text/plain')); $response->end('404'); return; } else { $controllerName = ‘My\\App\\Controller\\'.ucfirst($route->params['controller']).'Controller'; $actionName = $route->params['action'].'Action'; $controller = new $controllerName($request, $response, $di); $controller->$actionName(); }};
NomadPHP EU, June 2015 20
Aura.Dispatcher
NomadPHP EU, June 2015 21
It’s an Object Mapper
• Maps names to objects, and then invokes them in some way• Will continue to dispatch until there is nothing left to do
NomadPHP EU, June 2015 22
$dispatcher = new Aura\Dispatcher\Dispatcher();
$dispatcher->setObjectParam('controller');$dispatcher->setMethodParam('action');$dispatcher->setObject('projects', $di->lazyNew('Primus\App\Command\ProjectsCommand'));
$argv = $context->argv->get();if(count($argv) < 2) { $stdio = $di->get('cli.stdio'); $stdio->outln('Please enter a commmand to run'); die();}$controller = $argv[1];if(isset($argv[2])) { $args = $context->argv->get(); $action = $args[2].'Action';} else { $action = 'indexAction';}$dispatcher->__invoke(compact('controller', 'action'));
NomadPHP EU, June 2015 23
Aura.SqlQuery
NomadPHP EU, June 2015 24
Fluent Query Builder
• Generates SQL for MySQL, Postgres, SQLite, and SQL Server• Does not require a DB connection• Select, Insert, Update, and Delete builders are available
NomadPHP EU, June 2015 25
protected function buildSelectQuery($table, $criteria = array(), $cols = array('*'), $order = 'id ASC') { $select = $this->queryHandler->newSelect(); $select ->cols($cols) ->from($table) ->orderBy(array($order)) ; foreach($criteria as $column => $value) { $select->where($column.' = :'.$column); } if(!empty($criteria)) { $select->bindValues($criteria); } return $select;}
public function save($data, $table, $identifierColumn = 'id') { $data = $this->convertToArray($data); if(!empty($data[$identifierColumn])) { // Removed for brevity } else { $insert = $this->queryHandler->newInsert(); $insert ->into($table) ->cols(array_keys($data)) ->bindValues($data) ; $this->db->perform($insert->__toString(), $insert->getBindValues()); $name = $insert->getLastInsertIdName($identifierColumn); return $this->db->lastInsertId($name); }}
NomadPHP EU, June 2015 26
/** * Returns a single result based on the criteria * Criteria must be an array, with the DB column the key and the DB value the value * * @param array $criteria Search criteria * @param string $table Table to search against * @return array */public function find($criteria, $table){ $select = $this->buildSelectQuery($table, $criteria); return $this->db->fetchOne($select->__toString(), $select->getBindValues());}
NomadPHP EU, June 2015 27
Aura.Sql
NomadPHP EU, June 2015 28
A Better Wrapper around PDO
• Lazy connections to your DB• Allows you to quote arrays of strings• Prepare, bind and fetch in one step• SQL Profiler to see what went on during a query
NomadPHP EU, June 2015 29
use Aura\Di\Container as DiContainer;use Aura\Di\Factory as DiFactory;
$di = new DiContainer(new DiFactory());
$di->set('database.handler', function() use ($di) { $config = $di->get('config'); return new \Aura\Sql\ExtendedPdo( 'mysql:host='.$config['db']['host'].';dbname='.$config['db']['dbname'], $config['db']['username'], $config['db']['password'] );});
$di->params['Aura\SqlQuery\QueryFactory'] = array( 'db' => 'mysql');
$di->set('database.query_handler', $di->lazyNew('Aura\SqlQuery\QueryFactory'));
NomadPHP EU, June 2015 30
public function delete($criteria, $table){ $delete = $this->queryHandler->newDelete(); $delete->from($table); foreach($criteria as $col => $value) { $delete->where($col.' = :'.$col); } $delete->bindValues($criteria);
return $this->db->perform($delete->__toString(), $delete->getBindValues());}
public function fetchAllBy($criteria, $table, $order = 'id ASC'){ $select = $this->buildSelectQuery($table, $criteria, array('*'), $order); return $this->db->fetchAll($select->__toString(), $select->getBindValues());}
NomadPHP EU, June 2015 31
Aura.Cli
NomadPHP EU, June 2015 32
Very nice wrapper around the CLI
• Wraps the request and response for CLI interfaces• Supports options and help
NomadPHP EU, June 2015 33
Setup
use Aura\Cli\CliFactory;
$cli_factory = new CliFactory();$context = $cli_factory->newContext($GLOBALS);$cli_stdio = $cli_factory->newStdio();
NomadPHP EU, June 2015 34
public function createAction(){ $opts = $this->context->getopt(array('name:', 'repo:', 'branch:', 'deploy-path:')); // ... $name = $opts->get('--name'); $repo = $opts->get('--repo'); while (empty($name)) { $stdio->out('Please enter the name of this project: '); $name = $stdio->in(); } // ...}
public function deployAction(){ $args = $this->context->argv->get(); $project = $this->projectService->fetchProject($args[3]); if($project && $project->active) { $deploymentService = $this->di->get('service.deployment'); $deploymentService->deploy($project); $this->stdio->outln('Deployed'); } else { $this->stdio->outln('There is no project by that name'); }}
NomadPHP EU, June 2015 35
Aura.Filter
NomadPHP EU, June 2015 36
Better Filtering and Sanitization
• Provides a better interface for filtering than the Filter module• Ships with a ton of filters and validators• Allows chains of commands for working with data• Provides soft, hard, and full stop validation chains
NomadPHP EU, June 2015 37
NomadPHP EU, June 2015 38
NomadPHP EU, June 2015 39
Bundles, Kernels, and Projects
NomadPHP EU, June 2015 40
Using modules as building blocks
• Bundles are larger-weight versions of the individual packages• Kernels are ‘core’ logic for projects• Projects are more like using ZF2 or Symfony 2 as full stacks
NomadPHP EU, June 2015 41
Aura.SqlMapper_Bundle
• Use at your own risk• Links together Aura.Sql and Aura.SqlQuery into a mapper pattern
NomadPHP EU, June 2015 42
Project Kernel, Web Kernel, CLI Kernel• Provides the core setup for the Web and CLI projects• Mostly config and classes. Still needs wired up to work fully• You can create your own custom kernels by basing it off Project Kernel
NomadPHP EU, June 2015 43
Web Project, CLI Project
• Full stack project skeletons for those project types• They pull in a specific Kernel, and bootstrap from there• Make heavy use of Aura.Di, so make sure you know how to use it
NomadPHP EU, June 2015 44
Web Project
• Web Project follows Action Domain Responder instead of the normal MVC• Can be used as a Micro Framework or as a Full Stack
NomadPHP EU, June 2015 45
Questions?
NomadPHP EU, June 2015 47
Notes
• Code is taken from:• https://github.com/dragonmantank/primus• https://github.com/dragonmantank/casket
• All code in this presentation is available under the MIT license