Your SlideShare is downloading. ×
0
Build that Phing!
PHing Is Not GNU make
/Rick Kuipers @rskuipers
io@rskuipers.com
whoami
Rick Kuipers
@rskuipers
Apeldoorn
The Webmen
Magento
Zend Framework
><
A build tool developed for and in PHP
Installation through PEAR or Composer
$ pear channel-discover pear.phing.info
$ p...
><
vs
PHP
PEAR
build.xml
Java
apt-get
build.xml
Skeleton Application
build.xml
<?xml version="1.0"?>
<project name="zf2" default="build">
<target name="build" />
</project>
$ phing -l
Buildfile: /var/www/zf2/build.xml
Warning: target 'build' has no tasks or dependencies
Default target:
--------...
$ phing
Buildfile: /var/www/zf2/build.xml
Warning: target 'build' has no tasks or dependencies
zf2 tutorial > build:
BUILD...
Fundamentals
Properties
FileSets
PatternSets
Tasks
Properties
<property name="build.dir" value="${project.basedir}/build" />
<property name="dist.dir" value="${build.dir}/di...
FileSets
<fileset id="php.files" dir=".">
<include name="*.php" />
</fileset>
.
|-- build.xml
|-- example.php
|-- phing-lo...
<fileset id="php.files" dir=".">
<include name="*/*.php" />
</fileset>
.
|-- build.xml
|-- example.php
|-- phing-logic-1
|...
<fileset id="php.files" dir=".">
<include name="**/*.php" />
</fileset>
.
|-- build.xml
|-- example.php
|-- phing-logic-1
...
PatternSets
<patternset id="php.patternset">
<include name="*/src/**/*.php" />
<include name="*/view/**/*.phtml" />
</patt...
Let's put it together!
<?xml version="1.0"?>
<project name="zf2" default="build">
<property name="build.dir" value="${proj...
$ phing
Buildfile: /var/www/zf2/build.xml
Warning: target 'build' has no tasks or dependencies
zf2 > build:
BUILD FINISHED...
How do we use Phing
QA during module development
Combination with CI
Quality Assurance
"Quality Assurance (QA) is a way of preventing
mistakes or defects in manufactured products and
avoiding...
QA Tools
PHP Lint
PHP Mess Detector
PHP Code Sniffer
PHP Unit
Example
1. <?php
2.
3. namespace MyModule
4.
5. class Example {
6.
7. function sum($x, $y, $z)
8. {
9. return $x + $y;
10....
PHP Lint
Built into the PHP executable.
Checks for syntax errors.
$ php -l example.php
PHP Parse error: syntax error, unex...
Example
1. <?php
2.
3. namespace MyModule
4.
5. class Example {
6.
7. function sum($x, $y, $z)
8. {
9. return $x + $y;
10....
PHP Mess Detector
Installation through Git, Composer or as a PEAR package.
Detects code smells such as:
Possible bugs
Subo...
Example
1. <?php
2.
3. namespace MyModule;
4.
5. class Example {
6.
7. function sum($x, $y, $z)
8. {
9. return $x + $y;
10...
PHP Code Sniffer
Installation through Git, Composer or as a PEAR package.
Checks your code for coding standards such as:
P...
Example
1. <?php
2.
3. namespace MyModule;
4.
5. class Example {
6.
7. function sum($x, $y, $z)
8. {
9. return $x + $y;
10...
PHP Unit
Installation through PHAR, Composer or as a PEAR package.
Runs tests on your code.
Provides a framework to create...
PHP Unit
$ phpunit .
PHPUnit 3.7.29 by Sebastian Bergmann.
F
Time: 17 ms, Memory: 2.75Mb
There was 1 failure:
1) MyModuleE...
Example
1. <?php
2.
3. namespace MyModule;
4.
5. class Example {
6.
7. function sum($x, $y, $z)
8. {
9. return $x + $y;
10...
Tasks
Core Tasks
AdhocTaskdefTask
AdhocTypedefTask
AppendTask
ApplyTask
AvailableTask
ChmodTask
ChownTask
ConditionTask
Co...
Optional Tasks
ApiGenTask
CoverageMergerTask
CoverageReportTask
CoverageSetupTask
CoverageThresholdTask
DbDeployTask
DocBl...
PDOSQLExecTask
PearPackageTask
PearPackage2Task
PharPackageTask
PhkPackageTask
PhpCodeSnifferTask
PHPCPDTask
PHPLocTask
PH...
XmlPropertyTask
ZendCodeAnalyzerTask
ZendGuardEncodeTask
ZendGuardLicenseTask
ZipTask
Automating QA
PHPLint Task
<target name="phplint">
<phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache">
<fileset refid="ph...
PHPCodeSniffer Task
<target name="phpcs">
<phpcodesniffer standard="PSR2">
<fileset refid="php.files" />
<formatter type="...
PHPMD Task
<target name="phpmd">
<phpmd>
<fileset refid="php.files" />
</phpmd>
</target>
PHPUnit Task
<target name="phpunit">
<exec command="phpunit -c ${src.dir}/Application/test/" passthru="true" checkreturn="...
<?xml version="1.0"?>
<project name="zf2" default="build">
<property name="build.dir" value="${project.basedir}/build" />
...
$ phing
Buildfile: /var/www/zf2/build.xml
Warning: target 'build' has no tasks or dependencies
zf2 > build:
BUILD FINISHED...
Dependencies
<target name="build" depends="phplint, phpcs, phpmd, phpunit" />
$ phing
Buildfile: /var/www/zf2/build.xml
zf2 > phplint:
BUILD FAILED
exception 'IOException' with message 'Unable to open...
<target name="prepare">
<mkdir dir="${build.dir}" />
<mkdir dir="${dist.dir}" />
<mkdir dir="${logs.dir}" />
<mkdir dir="$...
<target name="-prepare" hidden="true">
<mkdir dir="${build.dir}" />
<mkdir dir="${dist.dir}" />
<mkdir dir="${logs.dir}" /...
<target name="phplint" depends="-prepare">
<!-- ... -->
</target>
<target name="phpcs" depends="-prepare">
<!-- ... -->
</...
$ phing
Buildfile: /var/www/zf2/build.xml
zf2 > -prepare:
zf2 > phplint:
zf2 > phpcs:
FILE: /var/www/zf2/module/Applicatio...
zf2 > phpmd:
[phpmd] Processing files...
/var/www/zf2/module/Album/src/Album/Form/AlbumForm.php:8 Avoid unused parameters ...
Logical tasks
IfTask
ConditionTask
FailTask
ForeachTask
IfTask
<property name="foo" value="bar" />
<if>
<equals arg1="${foo}" arg2="bar" />
<then>
<echo message="The value of pro...
ConditionTask
<condition property="IsPhingRecursiveAcronym">
<contains string="PHing Is Not GNU make" substring="phing" ca...
<condition property="IsXmlRecursiveAcronym">
<contains string="Extensible Markup Language" substring="XML" casesensitive="...
<condition property="IsXmlRecursiveAcronym">
<contains string="Extensible Markup Language" substring="XML" casesensitive="...
FailTask
<fail message="Failed for some reason!" />
<fail if="errorprop" message="Detected error!" />
<fail unless="dontfa...
ForeachTask
<fileset id="fruits" dir=".">
<include name="fruits/*.xml" />
<include name="**/*.php" />
</fileset>
<target n...
Interesting Tasks
PropertyPromptTask
PhpEvalTask
PropertyPromptTask
<?xml version="1.0" encoding="UTF-8"?>
<project name="Example" default="build">
<propertyprompt propert...
$ phing
Buildfile: /var/www/talk-phing/web/examples/phing-prompt/build.xml
Please enter your name [anonymous] ? Rick
Examp...
PhpEvalTask
<?xml version="1.0" encoding="UTF-8"?>
<project name="Example" default="build">
<target name="build">
<php exp...
$ phing
Buildfile: /var/www/talk-phing/web/examples/phing-php-eval/build.xml
Example > build:
[php] Evaluating PHP express...
<?xml version="1.0"?>
<project name="Testing Framework" default="build">
<property name="haltOnFail" value="true" />
<targ...
$ phing
Buildfile: /var/www/talk-phing/web/examples/phing-testing-framework/build.xml
Testing Framework > build:
[php] Cal...
Extending our phpunit target
<target name="phpunit" depends="-prepare">
<propertyprompt defaultValue="all" promptText="Whi...
Create your own Task
VDD
var_dump driven development
XDebug or PHPDBG
VarDumpTask
Accept a fileset
Find lines that contain var_dump
Ignore comments
Show the files and line numbers that match
H...
<?php
require_once 'phing/Task.php';
class VarDumpTask extends Task
{
public function main()
{
}
}
<?php
require_once 'phing/Task.php';
include_once 'phing/types/FileSet.php';
class VarDumpTask extends Task
{
protected $_...
<?php
require_once 'phing/Task.php';
include_once 'phing/types/FileSet.php';
class VarDumpTask extends Task
{
protected $_...
<?php
require_once 'phing/Task.php';
include_once 'phing/types/FileSet.php';
class VarDumpTask extends Task
{
const VAR_DU...
protected function _grep($file, $val, $ignoreLinesWith = null)
{
$lines = file($file);
foreach ($lines as $nr => $line)
{
...
protected $_haltOnMatch = false;
public function setHaltOnMatch($haltOnMatch = null)
{
if (isset($haltOnMatch)) {
$this->_...
public function main()
{
if (!count($this->_fileSets)) {
throw new BuildException("Missing a nested fileset");
}
$project ...
Defining your task
AdhocTaskdefTask
TaskdefTask
AdhocTaskdefTask
<adhoc-task name="foo">
<![CDATA[
class FooTest extends Task {
private $bar;
function setBar($bar) {
$thi...
TaskdefTask
<taskdef name="vdd" classname="phing.tasks.VarDumpTask" />
Using our VarDumpTask
<taskdef name="vdd" classname="phing.tasks.VarDumpTask" />
<target name="vdd" depends="-prepare">
<v...
$ phing vdd
Buildfile: /var/www/zf2/build.xml
zf2 > -prepare:
zf2 > vdd:
[vdd] /var/www/zf2/module/Album/Module.php:15
Exe...
<?xml version="1.0"?>
<project name="zf2" default="build">
<taskdef name="vdd" classname="phing.tasks.VarDumpTask" />
<pro...
<target name="phplint" depends="-prepare">
<phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache">
<fileset ref...
<target name="phpunit" depends="-prepare">
<propertyprompt defaultValue="all" promptText="Which module would you like to r...
Duplicate build file logic
Build file inheritance
Git submodules
phing/default.xml
<?xml version="1.0"?>
<project name="zf2">
<taskdef name="vdd" classname="phing.tasks.VarDumpTask" />
<p...
build.xml
<?xml version="1.0"?>
<project name="zf2" default="build">
<import file="phing/default.xml" />
<target name="bui...
Documentation
http://www.phing.info/docs/guide/stable/
https://github.com/phingofficial/phing
Build That Phing!
Upcoming SlideShare
Loading in...5
×

Build That Phing!

1,459

Published on

PHPMD, PHPCS, PHPUnit and PHPLint; these are all tools to maintain code quality. Executing these tasks is a chore and there are many ways to automate this process, Phing being one of them. The goal of this talk is to really discover what Phing has to offer, from implementing code logic to creating your own task.

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,459
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
8
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Transcript of "Build That Phing!"

  1. 1. Build that Phing! PHing Is Not GNU make /Rick Kuipers @rskuipers io@rskuipers.com
  2. 2. whoami Rick Kuipers @rskuipers Apeldoorn The Webmen Magento Zend Framework
  3. 3. >< A build tool developed for and in PHP Installation through PEAR or Composer $ pear channel-discover pear.phing.info $ pear install --alldeps phing/phing
  4. 4. >< vs PHP PEAR build.xml Java apt-get build.xml
  5. 5. Skeleton Application
  6. 6. build.xml
  7. 7. <?xml version="1.0"?> <project name="zf2" default="build"> <target name="build" /> </project>
  8. 8. $ phing -l Buildfile: /var/www/zf2/build.xml Warning: target 'build' has no tasks or dependencies Default target: ------------------------------------------------------------------------------- build Subtargets: ------------------------------------------------------------------------------- build
  9. 9. $ phing Buildfile: /var/www/zf2/build.xml Warning: target 'build' has no tasks or dependencies zf2 tutorial > build: BUILD FINISHED Total time: 0.0457 seconds
  10. 10. Fundamentals Properties FileSets PatternSets Tasks
  11. 11. Properties <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" />
  12. 12. FileSets <fileset id="php.files" dir="."> <include name="*.php" /> </fileset> . |-- build.xml |-- example.php |-- phing-logic-1 | `-- build.xml |-- phing-logic-2 | |-- build.xml | `-- continue |-- phing-logic-foreach | |-- build.xml | `-- fruits | |-- apple.php | |-- banana.xml | |-- orange.xml | `-- pear.php `-- qa-basics |-- build.xml |-- example.php `-- tests `-- ExampleTest.php
  13. 13. <fileset id="php.files" dir="."> <include name="*/*.php" /> </fileset> . |-- build.xml |-- example.php |-- phing-logic-1 | `-- build.xml |-- phing-logic-2 | |-- build.xml | `-- continue |-- phing-logic-foreach | |-- build.xml | `-- fruits | |-- apple.php | |-- banana.xml | |-- orange.xml | `-- pear.php `-- qa-basics |-- build.xml |-- example.php `-- tests `-- ExampleTest.php
  14. 14. <fileset id="php.files" dir="."> <include name="**/*.php" /> </fileset> . |-- build.xml |-- example.php |-- phing-logic-1 | `-- build.xml |-- phing-logic-2 | |-- build.xml | `-- continue |-- phing-logic-foreach | |-- build.xml | `-- fruits | |-- apple.php | |-- banana.xml | |-- orange.xml | `-- pear.php `-- qa-basics |-- build.xml |-- example.php `-- tests `-- ExampleTest.php
  15. 15. PatternSets <patternset id="php.patternset"> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </patternset> <fileset id="php.files" dir="${src.dir}"> <patternset refid="php.patternset" /> </fileset>
  16. 16. Let's put it together! <?xml version="1.0"?> <project name="zf2" default="build"> <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" /> <fileset id="php.files" dir="${src.dir}"> <include name="*/*.php" /> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </fileset> <target name="build" /> </project>
  17. 17. $ phing Buildfile: /var/www/zf2/build.xml Warning: target 'build' has no tasks or dependencies zf2 > build: BUILD FINISHED Total time: 0.0492 seconds
  18. 18. How do we use Phing QA during module development Combination with CI
  19. 19. Quality Assurance "Quality Assurance (QA) is a way of preventing mistakes or defects in manufactured products and avoiding problems when delivering solutions or services to customers."
  20. 20. QA Tools PHP Lint PHP Mess Detector PHP Code Sniffer PHP Unit
  21. 21. Example 1. <?php 2. 3. namespace MyModule 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  22. 22. PHP Lint Built into the PHP executable. Checks for syntax errors. $ php -l example.php PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting (T_NS_SEPARATOR) o r ';' or '{' in example.php on line 5 Errors parsing example.php
  23. 23. Example 1. <?php 2. 3. namespace MyModule 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  24. 24. PHP Mess Detector Installation through Git, Composer or as a PEAR package. Detects code smells such as: Possible bugs Suboptimal code Overcomplicated expressions Unused parameters, methods, properties $ phpmd example.php text cleancode,codesize,controversial,design,naming,unusedcode example.php:7 Avoid variables with short names like $x. Configured minimum length is 3. example.php:7 Avoid variables with short names like $y. Configured minimum length is 3. example.php:7 Avoid variables with short names like $z. Configured minimum length is 3. example.php:7 Avoid unused parameters such as '$z'.
  25. 25. Example 1. <?php 2. 3. namespace MyModule; 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  26. 26. PHP Code Sniffer Installation through Git, Composer or as a PEAR package. Checks your code for coding standards such as: PEAR PSR1 PSR2 Zend Squiz $ phpcs --standard=PSR2 example.php -------------------------------------------------------------------------------- FOUND 4 ERROR(S) AFFECTING 4 LINE(S) -------------------------------------------------------------------------------- 5 | ERROR | Opening brace of a class must be on the line after the definition 7 | ERROR | Visibility must be declared on method "sum" 12 | ERROR | The closing brace for the class must go on the next line after | | the body 13 | ERROR | A closing tag is not permitted at the end of a PHP file --------------------------------------------------------------------------------
  27. 27. Example 1. <?php 2. 3. namespace MyModule; 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  28. 28. PHP Unit Installation through PHAR, Composer or as a PEAR package. Runs tests on your code. Provides a framework to create tests. <?php namespace MyModule; require_once('example.php'); class ExampleTest extends PHPUnit_Framework_TestCase { public function testSum() { $example = new Example(); $this->assertEquals($example->sum(2, 3, 5), 10); } }
  29. 29. PHP Unit $ phpunit . PHPUnit 3.7.29 by Sebastian Bergmann. F Time: 17 ms, Memory: 2.75Mb There was 1 failure: 1) MyModuleExampleTest::testSum Failed asserting that 5 matches expected 10. /var/www/talk-phing/web/examples/qa-basics/tests/ExampleTest.php:13 FAILURES! Tests: 1, Assertions: 1, Failures: 1.
  30. 30. Example 1. <?php 2. 3. namespace MyModule; 4. 5. class Example { 6. 7. function sum($x, $y, $z) 8. { 9. return $x + $y; 10. } 11. 12. } 13. ?>
  31. 31. Tasks Core Tasks AdhocTaskdefTask AdhocTypedefTask AppendTask ApplyTask AvailableTask ChmodTask ChownTask ConditionTask CopyTask CvsTask CvsPassTask DeleteTask EchoTask ExecTask FailTask ForeachTask IfTask ImportTask IncludePathTask InputTask LoadFileTask MkdirTask MoveTask PhingTask PhingCallTask PhpEvalTask PropertyTask PropertyPromptTask ReflexiveTask ResolvePathTask TaskdefTask TouchTask TryCatchTask TstampTask TypedefTask UpToDateTask WaitForTask XsltTask
  32. 32. Optional Tasks ApiGenTask CoverageMergerTask CoverageReportTask CoverageSetupTask CoverageThresholdTask DbDeployTask DocBloxTask ExportPropertiesTask FileHashTask FileSizeTask FileSyncTask FtpDeployTask GitInitTask GitCloneTask GitGcTask GitBranchTask GitFetchTask GitCheckoutTask GitCommitTask GitMergeTask GitPullTask GitPushTask GitTagTask GitLogTask GrowlNotifyTask HttpGetTask HttpRequestTask IoncubeEncoderTask IoncubeLicenseTask JslLintTask JsMinTask LiquibaseChangeLogTask LiquibaseDbDocTask LiquibaseDiffTask LiquibaseRollbackTask LiquibaseTagTask LiquibaseUpdateTask MailTask ParallelTask PatchTask
  33. 33. PDOSQLExecTask PearPackageTask PearPackage2Task PharPackageTask PhkPackageTask PhpCodeSnifferTask PHPCPDTask PHPLocTask PHPMDTask PhpDependTask PhpDocumentorTask DocBloxTask PhpDocumentorExternalTask PhpLintTask PHPUnitTask PHPUnitReport rSTTask S3PutTask S3GetTask ScpTask SshTask SimpleTestTask SvnCheckoutTask SvnCommitTask SvnCopyTask SvnExportTask SvnInfoTask SvnLastRevisionTask SvnListTask SvnLogTask SvnUpdateTask SvnSwitchTask SymfonyConsoleTask SymlinkTask TarTask UntarTask UnzipTask VersionTask WikiPublishTask XmlLintTask
  34. 34. XmlPropertyTask ZendCodeAnalyzerTask ZendGuardEncodeTask ZendGuardLicenseTask ZipTask
  35. 35. Automating QA
  36. 36. PHPLint Task <target name="phplint"> <phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache"> <fileset refid="php.files" /> </phplint> </target>
  37. 37. PHPCodeSniffer Task <target name="phpcs"> <phpcodesniffer standard="PSR2"> <fileset refid="php.files" /> <formatter type="full" usefile="false" /> </phpcodesniffer> </target>
  38. 38. PHPMD Task <target name="phpmd"> <phpmd> <fileset refid="php.files" /> </phpmd> </target>
  39. 39. PHPUnit Task <target name="phpunit"> <exec command="phpunit -c ${src.dir}/Application/test/" passthru="true" checkreturn="true" /> <exec command="phpunit -c ${src.dir}/Album/test/" passthru="true" checkreturn="true" /> </target>
  40. 40. <?xml version="1.0"?> <project name="zf2" default="build"> <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" /> <fileset id="php.files" dir="${src.dir}"> <include name="*/*.php" /> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </fileset> <target name="build" /> <target name="phplint"> <phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache"> <fileset refid="php.files" /> </phplint> </target> <target name="phpcs"> <phpcodesniffer standard="PSR2"> <fileset refid="php.files" /> <formatter type="full" usefile="false" /> </phpcodesniffer> </target> <target name="phpmd"> <phpmd> <fileset refid="php.files" /> </phpmd> </target> <target name="phpunit"> <exec command="phpunit -c ${src.dir}/Application/test/" passthru="true" checkreturn="true" /> <exec command="phpunit -c ${src.dir}/Album/test/" passthru="true" checkreturn="true" /> </target> </project>
  41. 41. $ phing Buildfile: /var/www/zf2/build.xml Warning: target 'build' has no tasks or dependencies zf2 > build: BUILD FINISHED Total time: 0.0540 seconds
  42. 42. Dependencies <target name="build" depends="phplint, phpcs, phpmd, phpunit" />
  43. 43. $ phing Buildfile: /var/www/zf2/build.xml zf2 > phplint: BUILD FAILED exception 'IOException' with message 'Unable to open /var/www/zf2/build/cache/lint.cache for writing: ' in /usr/share/php/phing/system/io/FileOutputStream.php:59 Stack trace: #0 /usr/share/php/phing/system/io/FileWriter.php(38): FileOutputStream->__construct(Object(Ph ingFile), false) #1 /usr/share/php/phing/util/DataStore.php(146): FileWriter->__construct(Object(PhingFile)) #2 /usr/share/php/phing/util/DataStore.php(107): DataStore->write() #3 /usr/share/php/phing/tasks/ext/PhpLintTask.php(198): DataStore->commit() #4 /usr/share/php/phing/UnknownElement.php(96): PhpLintTask->main() #5 /usr/share/php/phing/Task.php(260): UnknownElement->main() #6 /usr/share/php/phing/Target.php(297): Task->perform() #7 /usr/share/php/phing/Target.php(320): Target->main() #8 /usr/share/php/phing/Project.php(824): Target->performTasks() #9 /usr/share/php/phing/Project.php(797): Project->executeTarget('build') #10 /usr/share/php/phing/Phing.php(586): Project->executeTargets(Array) #11 /usr/share/php/phing/Phing.php(170): Phing->runBuild() #12 /usr/share/php/phing/Phing.php(278): Phing::start(Array, NULL) #13 /usr/share/php/phing.php(43): Phing::fire(Array) #14 {main} Total time: 0.1397 seconds
  44. 44. <target name="prepare"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> <mkdir dir="${logs.dir}" /> <mkdir dir="${cache.dir}" /> </target>
  45. 45. <target name="-prepare" hidden="true"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> <mkdir dir="${logs.dir}" /> <mkdir dir="${cache.dir}" /> </target> © Stephan Hochdörfer
  46. 46. <target name="phplint" depends="-prepare"> <!-- ... --> </target> <target name="phpcs" depends="-prepare"> <!-- ... --> </target> <target name="phpmd" depends="-prepare"> <!-- ... --> </target> <target name="phpunit" depends="-prepare"> <!-- ... --> </target>
  47. 47. $ phing Buildfile: /var/www/zf2/build.xml zf2 > -prepare: zf2 > phplint: zf2 > phpcs: FILE: /var/www/zf2/module/Application/view/layout/layout.phtml -------------------------------------------------------------------------------- FOUND 0 ERROR(S) AND 5 WARNING(S) AFFECTING 5 LINE(S) -------------------------------------------------------------------------------- 6 | WARNING | Line exceeds 120 characters; contains 127 characters 11 | WARNING | Line exceeds 120 characters; contains 154 characters 17 | WARNING | Line exceeds 120 characters; contains 137 characters 33 | WARNING | Line exceeds 120 characters; contains 125 characters 36 | WARNING | Line exceeds 120 characters; contains 123 characters --------------------------------------------------------------------------------
  48. 48. zf2 > phpmd: [phpmd] Processing files... /var/www/zf2/module/Album/src/Album/Form/AlbumForm.php:8 Avoid unused parameters such as '$ name'. /var/www/zf2/module/Album/src/Album/Model/Album.php:33 Avoid unused parameters such as '$ inputFilter'. [phpmd] Finished processing files zf2 > phpunit: PHPUnit 4.0.14 by Sebastian Bergmann. Configuration read from /var/www/zf2/module/Application/test/phpunit.xml.dist . Time: 42 ms, Memory: 5.75Mb OK (1 test, 1 assertion) PHPUnit 4.0.14 by Sebastian Bergmann. Configuration read from /var/www/zf2/module/Album/test/phpunit.xml.dist ............. Time: 72 ms, Memory: 8.50Mb OK (13 tests, 22 assertions) zf2 > build: BUILD FINISHED
  49. 49. Logical tasks IfTask ConditionTask FailTask ForeachTask
  50. 50. IfTask <property name="foo" value="bar" /> <if> <equals arg1="${foo}" arg2="bar" /> <then> <echo message="The value of property foo is bar" /> </then> <else> <echo message="The value of property foo is not bar" /> </else> </if>
  51. 51. ConditionTask <condition property="IsPhingRecursiveAcronym"> <contains string="PHing Is Not GNU make" substring="phing" casesensitive="false" /> </condition> <if> <istrue value="${IsPhingRecursiveAcronym}" /> <then> <echo message="It's recursive!" /> </then> <else> <echo message="It's not recursive!" /> </else> </if> $ phing Buildfile: /var/www/talk-phing/web/examples/phing-condition-task/build.xml Example > build: [echo] It's recursive! BUILD FINISHED Total time: 0.0487 seconds
  52. 52. <condition property="IsXmlRecursiveAcronym"> <contains string="Extensible Markup Language" substring="XML" casesensitive="false" /> </condition> <if> <istrue value="${IsXmlRecursiveAcronym}" /> <then> <echo message="It's recursive!" /> </then> <else> <echo message="It's not recursive!" /> </else> </if> $ phing Buildfile: /var/www/talk-phing/web/examples/phing-condition-task/build.xml Example > build: [echo] It's recursive! BUILD FINISHED Total time: 0.0524 seconds
  53. 53. <condition property="IsXmlRecursiveAcronym"> <contains string="Extensible Markup Language" substring="XML" casesensitive="false" /> </condition> <if> <isset property="IsXmlRecursiveAcronym" /> <then> <echo message="It's recursive!" /> </then> <else> <echo message="It's not recursive!" /> </else> </if> $ phing Buildfile: /var/www/talk-phing/web/examples/phing-condition-task/build.xml Example > build: [echo] It's not recursive! BUILD FINISHED Total time: 0.0468 seconds
  54. 54. FailTask <fail message="Failed for some reason!" /> <fail if="errorprop" message="Detected error!" /> <fail unless="dontfail" message="Detected error!" />
  55. 55. ForeachTask <fileset id="fruits" dir="."> <include name="fruits/*.xml" /> <include name="**/*.php" /> </fileset> <target name="build"> <foreach param="fruit" target="displayfruit"> <fileset refid="fruits" /> </foreach> <foreach list="apple;orange;pear;banana" target="displayfruit" param="fruit" delimiter=";" /> </target> <target name="displayfruit"> <echo message="${fruit}" /> </target>
  56. 56. Interesting Tasks PropertyPromptTask PhpEvalTask
  57. 57. PropertyPromptTask <?xml version="1.0" encoding="UTF-8"?> <project name="Example" default="build"> <propertyprompt propertyName="messages.name" promptText="Please enter your name" defaultValue="anonymous" /> <property name="messages.welcome" value="Hello, ${messages.name}!" /> <target name="build" description="Displays the project name and a personalized welcome message" <echo message="${phing.project.name}: ${messages.welcome}" /> </target> </project>
  58. 58. $ phing Buildfile: /var/www/talk-phing/web/examples/phing-prompt/build.xml Please enter your name [anonymous] ? Rick Example > build: [echo] Example: Hello, Rick! BUILD FINISHED Total time: 3.7389 seconds
  59. 59. PhpEvalTask <?xml version="1.0" encoding="UTF-8"?> <project name="Example" default="build"> <target name="build"> <php expression="function increment($i) { return ++$i; }" /> <php function="increment" returnProperty="result"> <param>1</param> </php> <echo message="${result}" /> </target> </project>
  60. 60. $ phing Buildfile: /var/www/talk-phing/web/examples/phing-php-eval/build.xml Example > build: [php] Evaluating PHP expression: function increment($i) { return ++$i; } [php] Calling PHP function: increment() [echo] 2 BUILD FINISHED Total time: 0.0511 seconds
  61. 61. <?xml version="1.0"?> <project name="Testing Framework" default="build"> <property name="haltOnFail" value="true" /> <target name="build"> <php function="ucfirst" returnProperty="result"> <param>phing</param> </php> <property name="expected" value="Phing" override="true" /> <phingcall target="test" /> <php expression="preg_replace('/php/', 'xml', 'PHP')" returnProperty="result" /> <property name="expected" value="xml" override="true" /> <phingcall target="test" /> </target> <target name="test"> <if> <equals arg1="${result}" arg2="${expected}" casesensitive="true" /> <then> <echo>✔</echo> </then> <else> <echo>✘</echo> <fail if="haltOnFail"> Expected: ${expected} Result: ${result} </fail> </else> </if> </target> </project>
  62. 62. $ phing Buildfile: /var/www/talk-phing/web/examples/phing-testing-framework/build.xml Testing Framework > build: [php] Calling PHP function: ucfirst() [phingcall] Calling Buildfile '/var/www/talk-phing/web/examples/phing-testing-framework/build .xml' with target 'test' Testing Framework > test: [echo] ✔ [php] Evaluating PHP expression: preg_replace('/php/', 'xml', 'PHP') [phingcall] Calling Buildfile '/var/www/talk-phing/web/examples/phing-testing-framework/build .xml' with target 'test' Testing Framework > test: [echo] ✘ [if] Error in IfTask Execution of target "test" failed for the following reason: /var/www/talk-phing/web/examples/ phing-testing-framework/build.xml:19:12: Error in IfTask Previous exception 'BuildException' with message '/var/www/talk-phing/web/examples/phing-test ing-framework/build.xml:26:25: /var/www/talk-phing/web/examples/phing-testing-framework/build .xml:26:25: Expected: xml Result: PHP
  63. 63. Extending our phpunit target <target name="phpunit" depends="-prepare"> <propertyprompt defaultValue="all" promptText="Which module would you like to run the tests for?" propertyName="module" /> <if> <equals arg1="${module}" arg2="all" /> <then> <phingcall target="-run-all-tests" /> </then> <else> <property name="absFile" value="${src.dir}/${module}/test/phpunit.xml.dist" /> <phingcall target="-run-test" /> </else> </if> </target> <target name="-run-all-tests" hidden="true"> <foreach param="file" absparam="absFile" target="-run-test"> <fileset dir="${src.dir}"> <include name="*/test/phpunit.xml*" /> </fileset> </foreach> </target> <target name="-run-test" hidden="true"> <php function="dirname" returnProperty="phpunitConfigDir"> <param>${absFile}</param> </php> <exec command="phpunit -c ${phpunitConfigDir}" passthru="true" checkreturn="true" /> </target>
  64. 64. Create your own Task
  65. 65. VDD var_dump driven development XDebug or PHPDBG
  66. 66. VarDumpTask Accept a fileset Find lines that contain var_dump Ignore comments Show the files and line numbers that match Halt on match
  67. 67. <?php require_once 'phing/Task.php'; class VarDumpTask extends Task { public function main() { } }
  68. 68. <?php require_once 'phing/Task.php'; include_once 'phing/types/FileSet.php'; class VarDumpTask extends Task { protected $_fileSets = array(); public function main() { } public function createFileSet() { $num = array_push($this->_fileSets, new FileSet()); return $this->_fileSets[$num-1]; } }
  69. 69. <?php require_once 'phing/Task.php'; include_once 'phing/types/FileSet.php'; class VarDumpTask extends Task { protected $_fileSets = array(); public function main() { if (!count($this->_fileSets)) { throw new BuildException("Missing a nested fileset"); } } public function createFileSet() { $num = array_push($this->_fileSets, new FileSet()); return $this->_fileSets[$num-1]; } }
  70. 70. <?php require_once 'phing/Task.php'; include_once 'phing/types/FileSet.php'; class VarDumpTask extends Task { const VAR_DUMP = 'var_dump('; protected $_fileSets = array(); public function main() { if (!count($this->_fileSets)) { throw new BuildException("Missing a nested fileset"); } $project = $this->getProject(); foreach ($this->_fileSets as $fs) { $files = $fs->getDirectoryScanner($project)->getIncludedFiles(); $dir = $fs->getDir($this->project)->getPath(); foreach($files as &$file) { $fullfile = $dir . DIRECTORY_SEPARATOR . $file; if (($nr = $this->_grep($fullfile, self::VAR_DUMP, '//'))) { $this->log($fullfile . ':' . $nr); } } } } public function createFileSet() { $num = array_push($this->_fileSets, new FileSet());
  71. 71. protected function _grep($file, $val, $ignoreLinesWith = null) { $lines = file($file); foreach ($lines as $nr => $line) { if (strpos($line, $val) !== false) { if (!isset($ignoreLinesWith) || strpos($line, $ignoreLinesWith) === false) { return $nr; } } } return false; }
  72. 72. protected $_haltOnMatch = false; public function setHaltOnMatch($haltOnMatch = null) { if (isset($haltOnMatch)) { $this->_haltOnMatch = true; } }
  73. 73. public function main() { if (!count($this->_fileSets)) { throw new BuildException("Missing a nested fileset"); } $project = $this->getProject(); $found = false; foreach ($this->_fileSets as $fs) { $files = $fs->getDirectoryScanner($project)->getIncludedFiles(); $dir = $fs->getDir($project)->getPath(); foreach($files as &$file) { $fullfile = $dir . DIRECTORY_SEPARATOR . $file; if (($nr = $this->_grep($fullfile, self::VAR_DUMP, '//'))) { $this->log($fullfile . ':' . $nr); $found = true; } } } if ($found && $this->_haltOnMatch) { throw new BuildException('Found traces of var_dump in filesets'); } }
  74. 74. Defining your task AdhocTaskdefTask TaskdefTask
  75. 75. AdhocTaskdefTask <adhoc-task name="foo"> <![CDATA[ class FooTest extends Task { private $bar; function setBar($bar) { $this->bar = $bar; } function main() { $this->log("In FooTest: " . $this->bar); } } ]]> </adhoc-task>
  76. 76. TaskdefTask <taskdef name="vdd" classname="phing.tasks.VarDumpTask" />
  77. 77. Using our VarDumpTask <taskdef name="vdd" classname="phing.tasks.VarDumpTask" /> <target name="vdd" depends="-prepare"> <vdd haltOnMatch="true"> <fileset refid="php.files" /> </vdd> </target>
  78. 78. $ phing vdd Buildfile: /var/www/zf2/build.xml zf2 > -prepare: zf2 > vdd: [vdd] /var/www/zf2/module/Album/Module.php:15 Execution of target "vdd" failed for the following reason: /var/www/zf2/build.xml:48:25: Foun d traces of var_dump in filesets BUILD FAILED /var/www/zf2/build.xml:48:25: Found traces of var_dump in filesets Total time: 0.0687 seconds
  79. 79. <?xml version="1.0"?> <project name="zf2" default="build"> <taskdef name="vdd" classname="phing.tasks.VarDumpTask" /> <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" /> <fileset id="php.files" dir="${src.dir}"> <include name="*/*.php" /> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </fileset> <target name="build" depends="phplint, phpcs, phpmd, phpunit, vdd" /> <target name="-prepare" hidden="true"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> <mkdir dir="${logs.dir}" /> <mkdir dir="${cache.dir}" /> </target>
  80. 80. <target name="phplint" depends="-prepare"> <phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache"> <fileset refid="php.files" /> </phplint> </target> <target name="phpcs" depends="-prepare"> <phpcodesniffer standard="PSR2"> <fileset refid="php.files" /> <formatter type="full" usefile="false" /> </phpcodesniffer> </target> <target name="phpmd" depends="-prepare"> <phpmd> <fileset refid="php.files" /> </phpmd> </target> <target name="vdd" depends="-prepare"> <vdd haltOnMatch="true"> <fileset refid="php.files" /> </vdd> </target>
  81. 81. <target name="phpunit" depends="-prepare"> <propertyprompt defaultValue="all" promptText="Which module would you like to run the tests for? propertyName="module" /> <if> <equals arg1="${module}" arg2="all" /> <then> <phingcall target="-run-all-tests" /> </then> <else> <property name="absFile" value="${src.dir}/${module}/test/phpunit.xml.dist" /> <phingcall target="-run-test" /> </else> </if> </target> <target name="-run-all-tests" hidden="true"> <foreach param="file" absparam="absFile" target="-run-test"> <fileset dir="${src.dir}"> <include name="*/test/phpunit.xml*" /> </fileset> </foreach> </target> <target name="-run-test" hidden="true"> <php function="dirname" returnProperty="phpunitConfigDir"> <param>${absFile}</param> </php> <exec command="phpunit -c ${phpunitConfigDir}" passthru="true" checkreturn="true" /> </target> </project>
  82. 82. Duplicate build file logic Build file inheritance Git submodules
  83. 83. phing/default.xml <?xml version="1.0"?> <project name="zf2"> <taskdef name="vdd" classname="phing.tasks.VarDumpTask" /> <property name="build.dir" value="${project.basedir}/build" /> <property name="dist.dir" value="${build.dir}/dist" /> <property name="logs.dir" value="${build.dir}/logs" /> <property name="cache.dir" value="${build.dir}/cache" /> <property name="src.dir" value="${project.basedir}/module" /> <fileset id="php.files" dir="${src.dir}"> <include name="*/*.php" /> <include name="*/src/**/*.php" /> <include name="*/view/**/*.phtml" /> </fileset> <target name="-prepare" hidden="true"> <mkdir dir="${build.dir}" /> <mkdir dir="${dist.dir}" /> <mkdir dir="${logs.dir}" /> <mkdir dir="${cache.dir}" /> </target> <target name="phplint" depends="-prepare"> <phplint haltonfailure="true" cachefile="${cache.dir}/lint.cache"> <fileset refid="php.files" /> </phplint> </target> <target name="phpcs" depends="-prepare"> <phpcodesniffer standard="PSR2"> <fileset refid="php.files" /> <formatter type="full" usefile="false" />
  84. 84. build.xml <?xml version="1.0"?> <project name="zf2" default="build"> <import file="phing/default.xml" /> <target name="build" depends="phplint, phpcs, phpmd, phpunit, vdd" /> </project>
  85. 85. Documentation http://www.phing.info/docs/guide/stable/ https://github.com/phingofficial/phing
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×