Phing 3 is a significant update with some breaking changes compared to Phing 2.
This document aims to summarize all those breaking changes and noteworthy things that you might stumble across when upgrading from Phing 2 to 3.
The list below is not exhaustive. We've tried to list all significant/breaking changes, but there's a chance we missed something. If that's the case, let us know!
- Phing now requires at least PHP 7.4.
- All Phing code is now namespaced. This means that existing references to classes
that existed in earlier Phing versions will no longer work. For example, the
class
PhingFile
has been moved toPhing\Io\File
. If you are used to providing a specific logger or listener when running Phing (such asphing.listener.DefaultLogger
), you will need to adjust this (toPhing\Listener\DefaultLogger
, for example). The documentation has been modified to reflect this. - Support for dot-path classnames (i.e.,
foo.bar.FooBar
) has been removed. The associatedPackageAsPath
task was also removed. - Omitting the
basedir
property in the rootproject
tag now means "." instead of the current working directory. This effectively reverts the change made in http://www.phing.info/trac/ticket/309 (dfdb0bc)
- The behavior of
MkdirTask
has changed to be same as ofmkdir
Linux command:- When using
MkdirTask
to create a nested directory including its parents (eg.<mkdir dir="a/b/c" />
), the task now creates the parent directories with default permissions and not the permissions specified inmode
attribute. Only the last directory in the created hierarchy (ie. "c" in "a/b/c") should have permissions corresponding to the specifiedmode
attribute. Previously,MkdirTask
used to apply the samemode
to all the directories in the hierarchy including the last one. - When using
MkdirTask
withmode
attribute, the newly created directory now has exact the permissions specified inmode
attribute. If any parent directories are created, they have default permissions affected by umask setting. Previously,MkdirTask
used to mask the permissions of the last directory in the hierarchy according to umask too. - These changes are also important for POSIX Access Control Lists (ACL) to work
properly. When using ACL, the mask used to determine the effective pemissions
corresponds to the standard group permissions. The ACL mask of a newly
created directory should be inherited from the default ACL mask its parent
directory. However, previously
MkdirTask
withoutmode
attribute used mask the group permissions of newly created directories according to umask setting which resulted in lower than expected permissions. This should not happen when using ACL. Now,MkdirTask
respects ACL settings.
- When using
- The tasks to generate PEAR packages (including supporting code) have been removed from Phing.
- [AppendTask] The default behavior of
append
attribute was changed totrue
- [MoveTask] The default behavior of
overwrite
attribute was changed totrue
- [PHPUnitTask] Support for PHPUnit 9.
- [PhpCodeSnifferTask] was removed in favor of [PhpCSTask].
- The Zend Guard tasks were removed (Zend Guard is no longer supported).
- A number of tasks (or group of tasks) are also published to read-only repositories, but are
installed when you install the main repository:
- Amazon
- Analyzer (contains Sonar, PDepend, PHPStan, etc.)
- ApiGen
- Archive (contains Tar, Zip, etc.)
- Code coverage
- DbDeploy
- FtpDeploy
- Git
- Hg
- Http
- IniFile
- Ioncube
- JsHint
- JsMin
- Liquibase
- PhkPackage
- PhpDoc
- Sass
- Smarty
- SSH
- Svn
- Visualizer
- ZendCodeAnalyser
- ZendServerDevelopmentTools
- Obsolete
ExportPropertiesTask
was removed in favor of theEchoPropertiesTask
<exportproperties targetfile="output.props" /> <!-- is the same as --> <echoproperties destfile="output.props" regex="/^((?!host\.)(?!os\.)(?!env\.)(?!phing\.)(?!php\.)(?!line\.)(?!user\.)[\s\S])*$/"/>
FileHashTask
creates now a file by default- Deprecated
scpsend
alias for theScpTask
was removed - Deprecated
command
attribute for theExecTask
was removed, in favor of theexecutable
attribute andarg
nested elements:<exec command="echo foo"/> <!-- should become --> <exec executable="/bin/echo"> <arg value="foo"/> </exec>
- The
tstamp
task now supports ICU syntax - The
phpcpd
andphploc
tasks are removed, because their upstream projects have been abandoned - The signature from
\Phing\Listener\DefaultLogger::formatTime
has been changed. Therefore, if you have written a logger that overrides this method, you will need to update its signature accordingly. - The way how Phing handles file sizes has been normalized, this is explained in documentation.
- FileSizeTask:
unit
attribute can be an IEC or SI suffix. - HasFreeSpace condition:
needed
attribute can include an IEC or SI suffix. - Size selector:
units
attribute has been removed,value
attribute can include an IEC or SI suffix. - TruncateTask:
length
attribute can include an IEC or SI suffix.
- FileSizeTask:
- The way Phing handles and parses boolean values has changed significantly! In general, strings such as
true
,false
,TRUE
,FALSE
, etc. are no longer parsed into their PHP native equivalent. Specifically:- The way how boolean values are handled inside tasks has been normalized. Therefore
t
is not a validtrue
value any longer. For a list of effected components follow https://github.com/phingofficial/phing/search?p=1&q=booleanValue - Boolean values (such as
true
andfalse
) are no longer parsed when loading property files. Instead, the literal string value will be kept as property value. - Property expansion (such as through the
ExpandProperties
filter) also no longer handles boolean values as anything other than literal string values.
- The way how boolean values are handled inside tasks has been normalized. Therefore
- The order of property loading and expansion in property files has changed. When a property exists, but is shadowed / masked by a property of the same name
(while loading a property file), the value inside the property file takes precedence:
(with
<property name="http.port" value="8080"/> <property file="foo.properties"/>
foo.properties
containing the following):In this casehttp.port = 80 http.url = https://localhost:${http.port}
http.url
expands tohttps://localhost:80
, nothttps://localhost:8080
.