Code-Generierung Code-Generierung Mit der Konsole Repository: https://github.com/RalfEggert/dwx2015-code-generierung Slides: http://de.slideshare.net/eggertralf/dwx2015-codegenerierung 1 / 59
Code-GenerierungCode-GenerierungMit der Konsole
Repository: https://github.com/RalfEggert/dwx2015-code-generierungSlides: http://de.slideshare.net/eggertralf/dwx2015-codegenerierung
1 / 59
Einsatzzwecke: KonsoleEinsatzzwecke: Konsole
5 / 59
Code generierung
Deployment Skripte
InstallationsSkripteDatenbank Migration
Socket ServerCron Jobs
Spider / Crawler
VariantenVarianten
9 / 59
Zend Framework 2
Full-Stack ZF2 Applikation
Mit MVC
Gute ZF2-Kenntnisse
Zend\Code\Generator
Zend\Console
ZF\Console
»Richtige« Konsolen-Anwendung
Ohne MVC
Wenige ZF2-Kenntnisse
Zend\Code\Generator
Zend\Console
VariantenVarianten
10 / 59
Zend Framework 2
Full-Stack ZF2 Applikation
Mit MVC
Gute ZF2-Kenntnisse
Zend\Code\Generator
Zend\Console
ZF\Console
»Richtige« Konsolen-Anwendung
Ohne MVC
Wenige ZF2-Kenntnisse
Zend\Code\Generator
Zend\Console
???
BausteineBausteine
11 / 59
PHP 5.5
C0mposer
ZF\Console
Zend\Console
Zend\CodeZend\Config
Zend\Db
Zend\Filter
Zend\Validator
Composer.jsonComposer.json
12 / 59
{ "name": "ralfeggert/dwx2015-code-generierung", "description": "DWX2015: Tool zur Code-Generierung", "license": "MIT", "require": { "php": ">=5.5", "zfcampus/zf-console": "~1.0", "zendframework/zend-code": "~2.5", "zendframework/zend-config": "~2.5", "zendframework/zend-console": "~2.5", "zendframework/zend-db": "~2.5", "zendframework/zend-filter": "~2.5", "zendframework/zend-validator": "~2.5" }, "autoload": { "psr-4": { "PHPCG\\": "src/PHPCG" } }, "bin": ["bin/phpcg.php"]}
InstallationInstallation
13 / 59
// Projekt klonen$ cd /home/devhost/$ git clone https://github.com/RalfEggert/dwx2015-code-generierung$ cd dwx2015-code-generierung/
// Abhängigkeiten per Composer installieren$ php composer.phar install
// PHP Code Generator ausführen$ bin/phpcg.php
ProjektProjekt
https://github.com/zfcampus/zf-console 15 / 59
[b00]
ApplicationApplication
16 / 59
<?php// Datei /bin/phpcg.php
use Zend\Console\Console;use ZF\Console\Application;
define('DWX2015_PHPCG_ROOT', __DIR__ . '/..');define('VERSION', '1.0.0');
include DWX2015_PHPCG_ROOT . '/vendor/autoload.php';
$routes = include DWX2015_PHPCG_ROOT . '/config/routes.php';$console = Console::getInstance();
$application = new Application( 'PHP Code Generator (DWX2015)', VERSION, $routes, $console);
$exit = $application->run();exit($exit);
AutovervollständigungAutovervollständigung
17 / 59
// Autovervollständigung einrichten$ sudo bin/phpcg.php autocomplete > /etc/bash_completion.d/phpcg.php.sh$ source /etc/bash_completion.d/phpcg.php.sh
// Autovervollständigung nutzen$ bin/phpcg.php <TAB>autocomplete create-hello-you-class create-user-entities hello-someone hello-world hello-you update-user-entities help version
PHAR GenerierenPHAR Generieren
18 / 59
// PHAR Paket erstellen lassen$ bin/create-phar.php Phar created successfully in /home/devhost/dwx2015-code-generate/phpcg.phar
// Phar Paket verwenden$ php phpcg.phar ---------------------------------------------------------------------------PHP Code Generator (DWX2015), version 1.0.0
Available commands:
autocomplete Command autocompletion setup create-hello-you-class Create hello you class create-user-entities Create user entities hello-someone Hello someone hello-world Hello world hello-you Hello you help Get help for individual commands update-user-entities Update user entities version Display the version of the script---------------------------------------------------------------------------
HilfeHilfe
19 / 59
// Autovervollständigung einrichten$ bin/phpcg.php help ---------------------------------------------------------------------------PHP Code Generator (DWX2015), version 1.0.0
Available commands:
autocomplete Command autocompletion setup create-hello-you-class Create hello you class create-user-entities Create user entities hello-someone Hello someone hello-world Hello world hello-you Hello you help Get help for individual commands update-user-entities Update user entities version Display the version of the script---------------------------------------------------------------------------
Routing BeispieleRouting Beispiele
20 / 59
// Route ohne Parameter 'say-stuff'$ bin/phpcg.php say-stuff
// Route mit obligatorischem Wertparameter 'say-stuff <stuff>'$ bin/phpcg.php say-stuff Whatever
// Route mit optionalem Flag 'do-stuff [--strict|-s]:strict'$ bin/phpcg.php do-stuff -s
// Route mit optionalem Wertparameter 'do-stuff [--target=]'$ bin/phpcg.php do-stuff --target=Whatever
RouteRoute
22 / 59
<?php// Datei /config/routes.php
return array( array( 'name' => 'hello-world', 'route' => 'hello-world', 'description' => 'Say hello to the world', 'short_description' => 'Hello world', 'handler' => 'PHPCG\Command\HelloWorld', ),
[...]);
KommandoKommando
23 / 59
<?php// Datei /src/PHPCG/Command/HelloWorld.php
namespace PHPCG\Command;
use Zend\Console\Adapter\AdapterInterface as Console;use Zend\Console\ColorInterface as Color;use ZF\Console\Route;
class HelloWorld{ public function __invoke(Route $route, Console $console) { $console->writeLine('Hello World', Color::YELLOW); }}
KonsoleKonsole
24 / 59
$ bin/phpcg.php hello-world ---------------------------------------------------------------------------PHP Code Generator (DWX2015), version 1.0.0
Hello World---------------------------------------------------------------------------
RouteRoute
25 / 59
<?php// Datei /config/routes.php
return array( array( 'name' => 'hello-you', 'route' => 'hello-you <you>', 'description' => 'Say hello to you', 'short_description' => 'Hello you', 'options_descriptions' => array( '<you>' => 'Your name' ), 'handler' => 'PHPCG\Command\HelloYou', ),
[...]);
KommandoKommando
26 / 59
<?php// Datei /src/PHPCG/Command/HelloYou.php
namespace PHPCG\Command;
use Zend\Console\Adapter\AdapterInterface as Console;use Zend\Console\ColorInterface as Color;use ZF\Console\Route;
class HelloYou{ public function __invoke(Route $route, Console $console) { $you = $route->getMatchedParam('you');
$console->write('Hello '); $console->write(sprintf('"%s"', $you), Color::YELLOW); $console->writeLine(' ...'); }}
KonsoleKonsole
27 / 59
$ bin/phpcg.php hello-you Ralf---------------------------------------------------------------------------PHP Code Generator (DWX2015), version 1.0.0
Hello "Ralf" ...---------------------------------------------------------------------------
RouteRoute
28 / 59
<?php// Datei /config/routes.php
return array( array( 'name' => 'hello-someone', 'route' => 'hello-someone', 'description' => 'Say hello to someone', 'short_description' => 'Hello someone', 'handler' => 'PHPCG\Command\HelloSomeOne', ),
[...]);
KommandoKommando
29 / 59
<?php// Datei /src/PHPCG/Command/HelloSomeOne.php
[...]use Zend\Console\Prompt\Line;use Zend\Console\Prompt\Select;
class HelloSomeOne{ public function __invoke(Route $route, Console $console) { $prompt = new Line('Please enter any name: '); $you = $prompt->show();
$options = array(Color::BLACK => 'BLACK', [...], Color::BLUE => 'BLUE');
$prompt = new Select('Please choose any color: ', $options); $color = $prompt->show();
$console->write('Hello '); $console->write(sprintf(' %s ', $you), Color::WHITE, $color); $console->writeLine(' ...'); }}
KonsoleKonsole
30 / 59
$ bin/phpcg.php hello-someone ---------------------------------------------------------------------------PHP Code Generator (DWX2015), version 1.0.0
Please enter any name: Ralf
Please choose any color: 1) BLACK 2) RED 3) GREEN 4) YELLOW 5) BLUE
Hello ...---------------------------------------------------------------------------ralf@ralf-HP-2013:/home/devhost/dwx2015-code-generierung$
Ralf
ProjektProjekt
https://github.com/zendframework/zend-code 32 / 59
[b00]
GeneratorenGeneratoren
33 / 59
Body Generator
Class Generator
Doc Block Generator
File Generator
Method GeneratorParameter Generator
Property Generator
TRAIT Generator
Value Generator
Weitere Generatoren
RouteRoute
34 / 59
<?php// Datei /config/routes.php
return array( array( 'name' => 'create-hello-you-class', 'route' => 'create-hello-you-class', 'description' => 'Create a hello you class', 'short_description' => 'Create hello you class', 'handler' => 'PHPCG\Command\CreateHelloYou', ),
[...]);
Class Generator IClass Generator I
35 / 59
<?php// Datei /src/PHPCG/Generator/HelloYouClassGenerator.php
namespace PHPCG\Generator;
use Zend\Code\Generator\ClassGenerator;use Zend\Code\Generator\MethodGenerator;use Zend\Code\Generator\ParameterGenerator;use Zend\Code\Generator\PropertyGenerator;
class HelloYouClassGenerator { private $class;
public function getClass() { return $this->class; }
public function createClass() {}}
Class Generator IIClass Generator II
36 / 59
<?phppublic function createClass(){ $nameProperty = new PropertyGenerator('name'); $nameProperty->addFlag(PropertyGenerator::FLAG_PRIVATE);
$nameSetMethod = new MethodGenerator('setName'); $nameSetMethod->addFlag(MethodGenerator::FLAG_PUBLIC); $nameSetMethod->setParameter(new ParameterGenerator('name')); $nameSetMethod->setBody('$this->name = $name;');
$greetMethod = new MethodGenerator('greet'); $greetMethod->addFlag(MethodGenerator::FLAG_PUBLIC); $greetMethod->setBody('return sprintf("Hello %s!", $this->name);');
$this->class = new ClassGenerator('HelloYou', 'Hello\Greeting'); $this->class->addPropertyFromGenerator($nameProperty); $this->class->addMethods(array($nameSetMethod, $greetMethod));}
FILE GeneratorFILE Generator
37 / 59
<?php// Datei /src/PHPCG/Generator/ClassFileGenerator.php
namespace PHPCG\Generator;
use Zend\Code\Generator\ClassGenerator;use Zend\Code\Generator\DocBlockGenerator;use Zend\Code\Generator\FileGenerator;
class ClassFileGenerator{ private $file;
public function getFile() { return $this->file; }
public function createFile(ClassGenerator $class) { $docBlock = new DocBlockGenerator([...]);
$this->file = new FileGenerator(); $this->file->setClass($class); $this->file->setDocBlock($docBlock); }}
KommandoKommando
38 / 59
<?php// Datei /src/PHPCG/Command/CreateHelloYouClass.php
namespace PHPCG\Command;
[...]
class CreateHelloYouClass{ public function __invoke(Route $route, Console $console) { $fileName = DWX2015_PHPCG_ROOT . '/tmp/HelloYouClass.php';
$classGenerator = new HelloYouClassGenerator(); $classGenerator->createClass(); $class = $classGenerator->getClass();
$fileGenerator = new ClassFileGenerator(); $fileGenerator->createFile($class); $file = $fileGenerator->getFile();
file_put_contents($fileName, $file->generate());
[...] }}
KonsoleKonsole
39 / 59
$ bin/phpcg.php create-hello-you-class ----------------------------------------------------------------------------------------PHP Code Generator (DWX2015), version 1.0.0
Created class HelloYou in file /home/devhost/dwx2015-code-generierung/tmp/HelloYouClass.php
<?phpnamespace Hello\Greeting;
class HelloYou{ private $name = null;
public function setName($name) { $this->name = $name; }
public function greet() { return sprintf("Hello %s!", $this->name); }}----------------------------------------------------------------------------------------
ProjektProjekt
https://github.com/zendframework/zend-db 41 / 59
[b00]
Zend\Db KomponentenZend\Db Komponenten
42 / 59
Adapter
Metadata
Result Set
Row Gateway
SQLTable Gateway
DB KonfigurationDB Konfiguration
44 / 59
<?php// Datei /config/db.php
return array( 'adapter' => array( 'driver' => 'Pdo', 'dsn' => 'mysql:dbname=dwx2015.user;host=localhost;charset=utf8', 'user' => 'dwx2015', 'pass' => 'dwx2015', ),);
Meta Data Collector IMeta Data Collector I
45 / 59
<?php// Datei /src/PHPCG/MetaData/Collector.php
namespace PHPCG\Collector;
use Zend\Db\Metadata\Metadata;use Zend\Db\Metadata\Object\ColumnObject;
class MetaDataCollector{ public function __construct(Metadata $metaData) { $this->metaData = $metaData; }
public function fetchTableColumns($tableName) { $tableColumns = array();
[...]
return $tableColumns; }}
Meta Data Collector IIMeta Data Collector II
46 / 59
<?php [...]
foreach ($tableMeta->getColumns() as $column) { $config = array('required' => !$column->getIsNullable());
if (in_array($column->getDataType(), array('varchar','text','enum'))) { $config['type'] = 'string'; } else { $config['type'] = 'integer'; }
if ($column->getDataType() == 'varchar') { $config['max_length'] = $column->getCharacterMaximumLength(); } elseif ($column->getDataType() == 'enum') { $config['values'] = $column->getErrata('permitted_values'); }
$tableColumns[$column->getName()] = $config; }
User Entity Generator IUser Entity Generator I
47 / 59
<?php// Datei /src/PHPCG/Generator/UserEntityGenerator.php
namespace PHPCG\Generator;
use Zend\Code\Generator\ClassGenerator;use Zend\Code\Generator\DocBlockGenerator;use Zend\Code\Generator\MethodGenerator;use Zend\Code\Generator\ParameterGenerator;use Zend\Code\Generator\PropertyGenerator;use Zend\Code\Generator\ValueGenerator;use Zend\Filter\Word\UnderscoreToCamelCase;
class UserEntityGenerator extends ClassGenerator{ private $class; private $filterUTCC;
public function __construct() {} public function getClass() {} public function createClass() {} public function addEntityProperties(array $columns = array()) {}}
User Entity Generator IIUser Entity Generator II
48 / 59
<?phppublic function __construct() { $this->filterUTCC = new UnderscoreToCamelCase();}
public function getClass(){ return $this->class;}
public function createClass(){ $this->class = new ClassGenerator('UserEntity', 'User\Entity');
$this->class->setDocBlock( new DocBlockGenerator([...]) );}
User Entity Generator IIIUser Entity Generator III
49 / 59
<?phppublic function addEntityProperties(){ foreach ($this->columns as $name => $attributes) { $property = $this->generateProperty($name, $attributes); $getMethod = $this->generateGetMethod($name, $attributes); $setMethod = $this->generateSetMethod($name, $attributes);
$this->class->addPropertyFromGenerator($property); $this->class->addMethodFromGenerator($getMethod); $this->class->addMethodFromGenerator($setMethod); }}
private function generateProperty($name, array $attributes = array()){ $property = new PropertyGenerator($name); $property->addFlag(PropertyGenerator::FLAG_PROTECTED);
return $property;}
User Entity Generator IVUser Entity Generator IV
50 / 59
<?phpprivate function generateGetMethod($name, array $attributes = array()){ $methodName = 'get' . $this->filterUTCC->filter($name);
$getMethod = new MethodGenerator($methodName); $getMethod->addFlag(MethodGenerator::FLAG_PUBLIC); $getMethod->setBody('return $this->' . $name . ';');
return $getMethod;}
User Entity Generator VUser Entity Generator V
51 / 59
<?phpprivate function generateSetMethod($name, array $attribs = array()){ $methodName = 'set' . $this->filterUTCC->filter($name); $defaultValue = !$attribs['required'] ? new ValueGenerator(null) : null;
$setMethod = new MethodGenerator($methodName); $setMethod->addFlag(MethodGenerator::FLAG_PUBLIC); $setMethod->setParameter( new ParameterGenerator($name, null, $defaultValue) ); $setMethod->setBody('$this->' . $name . ' = $' . $name . ';');
return $setMethod;}
Kommando IKommando I
52 / 59
<?php// Datei /src/PHPCG/Command/CreateUserEntities.php
namespace PHPCG\Command;
use PHPCG\Collector\MetaDataCollector;use PHPCG\Generator\ClassFileGenerator;use PHPCG\Generator\UserEntityGenerator;use Zend\Console\Adapter\AdapterInterface as Console;use Zend\Console\ColorInterface as Color;use Zend\Db\Adapter\Adapter;use Zend\Db\Metadata\Metadata;use ZF\Console\Route;
class CreateUserEntities{ public function __invoke(Route $route, Console $console) { [...] }}
Kommando IIKommando II
53 / 59
<?phppublic function __invoke(Route $route, Console $console){ $dbConfig = include DWX2015_PHPCG_ROOT . '/config/db.php'; $fileName = DWX2015_PHPCG_ROOT . '/tmp/UserEntity.php';
$dbAdapter = new Adapter($dbConfig['adapter']); $metaData = new Metadata($dbAdapter); $collector = new MetaDataCollector($metaData);
$userColumns = $collector->fetchTableColumns('user');
$classGenerator = new UserEntityGenerator(); $classGenerator->createClass(); $classGenerator->addEntityProperties($userColumns); $class = $classGenerator->getClass();
$fileGenerator = new ClassFileGenerator(); $fileGenerator->createFile($class); $file = $fileGenerator->getFile();
file_put_contents($fileName, $file->generate());
[...]}
KonsoleKonsole
54 / 59
$ bin/phpcg.php create-user-entities-------------------------------------------------------------------------------------------------PHP Code Generator (DWX2015), version 1.0.0
Created class UserEntity in file /home/devhost/dwx2015-code-generierung/tmp/UserEntity.php
<?phpnamespace User\Entity;
class UserEntity{ protected $id = null; [...]
public function getId() { return $this->id; }
public function setId($id) { $this->id = $id; } [...]}-------------------------------------------------------------------------------------------------
Weitere IdeenWeitere Ideen
56 / 59
EntitiesAktualisieren
✓
Formularegenerieren
ValidierungIn Entity✓
Entitieslöschen
InputFilterGenerieren
DANKEDANKEFür Ihre / Eure Aufmerksamkeit!
Repository: https://github.com/RalfEggert/dwx2015-code-generierungSlides: http://de.slideshare.net/eggertralf/dwx2015-codegenerierung
58 / 59
BildnachweisBildnachweis[B00] Fotos von Ralf Eggert
[B01] Carrot And Stick Incentives Lead Manage http://www.workcompass.com/ von Alan O'Rourke - CC-BY https://creativecommons.org/licenses/by/2.0/
[B02] Frontiers 2011 - Day 2 https://www.flickr.com/photos/frontiersofinteraction/5866676276/ von Frontiersofinteraction - CC-BY https://creativecommons.org/licenses/by/2.0/
[B03] Multi Tools https://www.flickr.com/photos/pennuja/5363515039 von Jim Pennucci - CC-BY https://creativecommons.org/licenses/by/2.0/
[B04] Command https://www.flickr.com/photos/shearforce/3838603833/ von Margaret Shear - CC-BY-SA https://creativecommons.org/licenses/by-sa/2.0/
[B05] Propeller Generator in the Sunset https://www.flickr.com/photos/jiazi/2060352110/ von Tim Wang - CC-BY-SA https://creativecommons.org/licenses/by-sa/2.0/
[B06] Fixing the database https://www.flickr.com/photos/dahlstroms/4140461901 von Håkan Dahlström - CC-BY https://creativecommons.org/licenses/by/2.0/
[B07] I have an idea @ home https://www.flickr.com/photos/ful1to/3783198574/ von Julian Santacruz - CC-BY https://creativecommons.org/licenses/by/2.0/
[B08] Etech05: Audience https://www.flickr.com/photos/oreilly/6648470 von James Duncan Davidson - CC-BY https://creativecommons.org/licenses/by/2.0/
Alle weiteren Screenshots wurden von Ralf Eggert erstellt.
59 / 59