Download pdf - DWX2015 Code Generierung

Transcript

Code-GenerierungCode-GenerierungMit der Konsole

Repository: https://github.com/RalfEggert/dwx2015-code-generierungSlides: http://de.slideshare.net/eggertralf/dwx2015-codegenerierung

1 / 59

Über michÜber mich

2 / 59www.RalfEggert.dewww.RalfEggert.de

[B01]

Motivation Motivation

3 / 59

Frage ans PublikumFrage ans Publikum

4 / 59

[b02][b02]

Einsatzzwecke: KonsoleEinsatzzwecke: Konsole

5 / 59

Code generierung

Deployment Skripte

InstallationsSkripteDatenbank Migration

Socket ServerCron Jobs

Spider / Crawler

[B03]

ToolsTools

6 / 59

Tools Konsole & CodeTools Konsole & Code

7 / 59

Konsole Code

Tools Konsole & CodeTools Konsole & Code

8 / 59

Konsole Code

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

[B00]

ZF\ConsoleZF\Console

14 / 59

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

[B04]

KommandosKommandos

21 / 59

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

[B05]

CODE CODE Generator Generator

31 / 59

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); }}----------------------------------------------------------------------------------------

[B06]

DatenbankDatenbank

40 / 59

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

DatenbankmodellDatenbankmodell

43 / 59

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; } [...]}-------------------------------------------------------------------------------------------------

[B07]

War es das?War es das?55 / 59

Weitere IdeenWeitere Ideen

56 / 59

EntitiesAktualisieren

Formularegenerieren

ValidierungIn Entity✓

Entitieslöschen

InputFilterGenerieren

Fragen vom Publikum?Fragen vom Publikum?

57 / 59

[b08]

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


Recommended