Goodbye, Phix

Posted by Stuart Herbert on March 2nd, 2015 in phix.

Back in 2009, I spoke at the PHP UK Conference about the pain of living with PHP’s fledgling frameworks, and I returned in 2011 to promote component-driven applications:



Back then, PEAR was the only tool available for distributing components. It was built in a time when hosting and sharing code was hard, and although PEAR made it possible to create components in PHP, PEAR never made it easy to do so.

Phix was an open-source tool that I wrote to sit on top of PEAR and make things easier. It gave you an easy-to-use build.xml file for Phing to automate all of the common tasks, a standardised file layout so that you could just drop in your code, and integration with Pirum so that you could build and publish.

Today, we don’t need any of these tools. PEAR has been replaced by Composer, and it’s so easy to use that there’s no need for Phing or a build.xml file. The PHP FIG standards have given us our file layouts, and as for publishing … today, all you need to do is push to GitHub and publishing happens automatically.

We no longer need Phix, and that’s a good thing.

Be the first to leave a comment »

Phix 0.16.0 Released

Posted by Stuart Herbert on May 23rd, 2013 in phix.

Phix is a tool for creating and managing PHP components and tools and releasing them as PEAR packages.

I’ve pushed out Phix 0.16.0 this evening, with the following changes:

  • phing build-vendor now removes the component’s own code from the vendor/ folder. (We build the vendor/ folder using PEAR, which installs the component into the vendor/ folder … sigh)
  • An update to Phing changed the default behaviour of the <fileset> tag, breaking backwards-compatibility. I’ve updated our build.xml file to make the <fileset> tag revert back to its original behaviour.

To update your copy of Phix, please run:

pear upgrade phix/phix4componentdev

Any problems, please let me know.

Be the first to leave a comment »

So that I don’t forget how to do this next time around. Worked for me, your mileage may vary.

First step is to get a working install of PHP.

  1. Download PHP 5.4.latest ZIP file from the PHP Windows website
  2. Unpack the ZIP file into c:php. You should end up with c:phpphp.exe
  3. Copy c:phpphp.ini-development to be c:phpphp.ini
  4. Edit c:phpphp.ini to suit (e.g. set date.timezone)
  5. Make sure you add c:php to your system PATH (via Computer’s Advanced Properties -> Environment Variables)
  6. Reboot (this is Windows, after all ๐Ÿ™‚

At this point, you should be able to open up a Command Prompt, and type ‘php -v’, and see the response ‘PHP v5.4.latest …’ appear as expected.

Now for PEAR itself.

  1. Open http://pear.php.net/go-pear.phar in a browser, save this file into c:php
  2. In a Command Prompt, cd to c:php and then run “php c:phpgo-pear.phar”
  3. At the prompt, select ‘system’. A text menu of paths will appear
  4. Fix the default path for pear.ini (option 11) to be c:phppear.ini
  5. Fix the default folder to look inside for php.exe to be c:php
  6. Make sure the binaries folder (option 4) is c:php
  7. Check all of the other options, make sure they are prefixed with c:php
  8. Press ENTER, and you should see PEAR downloading various PEAR packages onto your system
  9. Double-click the PEAR_ENV.reg file in c:php
  10. Reboot again to make sure PEAR_ENV registry entries have taken effect

At this point, PEAR is installed and should be available to use in your own projects, or with something like Phix.

Personal Notes

Some reminders to myself for the next time I have to do this.

  • Documentation for PHP for Windows and PEAR for Windows both seem to be out of step with current downloads. There’s currently no Windows installer for PHP available, and the PHP .ZIP file doesn’t contain the ‘go-pear.bat’ file.
  • You have to pay close attention to the default folders offered when running ‘go-pear.phar’. They appear to use the current working directory as the prefix even when installing system-wide, except for the location of pear.ini and php.exe – neither of these defaults are sane, and must be manually changed during the install ๐Ÿ™
  • After install, pear command doesn’t seem to be 100% compatible with its behaviour on Linux and OS X. -D switch didn’t work, there may be other problems too that I haven’t yet found.
  • Both reboots are required – I’m not taking the piss there – for all running Windows apps to pick up the changes.
19 comments »

Phix 0.15 Released

Posted by Stuart Herbert on January 31st, 2012 in phix.

Phix v0.15 is now available from pear.phix-project.org.

This release is dedicated to my Dad, Leslie Herbert, who passed away in December 2011 whilst I was recovering from surgery. He was always encouraging me to spend as much time as possible working on my own software, and I’m sure he’d be happy that his PC has become my new dev box for working on things like Phix.

What’s New In This Release

  • phploc support – the “phing code-review” command now also calculates the size of your component using phploc.
  • subset support – you can now do “phix php-library:init –subset=<role>[,<role> …]” to create components that only contain some of the different file types supported by the PEAR Installer. There’s also a “phix php-library:removeunusedroles” command if you want to strip unused roles from an existing component.
  • phpunit.xml.dist support – components now use phpunit.xml.dist by default, so that you can put your own phpunit.xml in place if you ever need to override the default settings.
  • src/README.md – we now drop a (hopefully helpful) README file inside the src/ folder to explain what goes where.
  • misc robustness improvements to build.xml files – I’ve made some small tweaks to the build.xml file to try and catch a few error conditions and display helpful messages.
  • internal debugging – “phix -d …” (which has been documented for several release now) enables internal debugging tests inside Phix and its components. It’s mostly there for me to use, but I thought I’d mention it in case you’re testing a patch for phix before sending it to me.

A big thanks to everyone who attended my workshop at PHPNW11 in October for their feedback and feature requests for this release.

How To Install

To install Phix, we have handy one-line install scripts on the Phix project homepage. And I’ve put together a screencast of how to install Phix on Ubuntu. It’s my first ever screencast, so please be gentle ๐Ÿ™‚

How To Upgrade

To upgrade from an earlier release of Phix, please do the following:

sudo pear clear-cache
sudo pear upgrade phix/phix4componentdev

Once you’ve upgraded phix itself, don’t forget to go into each of your components, and run

phix php-library:upgrade .

to upgrade all of the skeleton files (build.xml et al) for your component.

What’s Coming In Phix 0.16

Windows support hasn’t happened yet, but I hopefully have a volunteer who is going to look into that during February.

My priority for phix-0.16 is to make it easy to build phix-based components in Jenkins, based on Sebastian’s Jenkins Template. I’m doing this next because I’m not sure how much I’ve got to change things to suit Jenkins, so I’d rather get it done sooner so it’s done and out of the way. (And I promise that I haven’t forgotten docblox support either …)

Our roadmap has all the details.

Be the first to leave a comment »

One of the questions I’ve been asked after yesterday’s blog post about Phix’s ContractLib is why not just use PHP’s built-in assert() function? I think it’s a great question, and the best way to answer it is to take a look at the key differences between two solutions.

Side By Side Comparison

Feature assert() ContractLib
Implementation PHP extension written in C (ships as standard part of PHP) PHP library written in PHP
Enable / disable execution Partial (there is an overhead when disabled, but it’s low) Partial (there is an overhead when disabled, but it’s higher)
Issues PHP4-style warning when tests fail Yes (configurable) No (throws a ContractFailedException instead)
Terminate PHP script when tests fail Yes (configurable) Only if the ContractFailedException is never caught
Quiet eval of test expression Yes (configurable) No (not required; test expressions are pure PHP code, not eval() strings)
Callback on failed test Yes (configurable) No (unwinds the stack instead by throwing ContractFailedException)
Throws Exception when tests fail No (but can emulate if you write your own assert() callback method) Yes (standard behaviour)
Tests are pure PHP code No – recommended way is to pass strings into assert() to be eval()’d Yes
Error report includes original value that failed the test No Yes
Support for per-test custom failure messages No Yes – are required to provide one
Support for Old Value storage and recall No (but can emulate by hand) Yes

The Differences Explained

The key difference is one of philosophy. assert() sits well with the PHP4 style of error reporting and handling, whereas ContractLib is firmly in favour of the OO world’s approach to reporting errors.

It’s a personal preference, but I think that PHP4-style errors have no place in code that has any desire to be robust. Exceptions aren’t perfect, don’t get me wrong, but their core property of unwinding the call stack in an orderly fashion makes writing robust code much easier. And they also carry a payload – information about what went wrong and why – which PHP’s assert() cannot provide to the same extent.

It’s much quicker to debug something when there’s a record of the value that failed the test. For that reason alone, I’d always prefer something like ContractLib over the built-in assert() approach.

But we can’t ignore the fact that these are tests that get shipped to, and executed in, the production environment. Unlike unit tests, adopting programming by contract will slow down your PHP code in production. The question is: by how much?

What About The Performance?

I’ve done some benchmarking between the two, using the five tests listed in the final example in yesterday’s blog post. It’s a real-world example of the kind of tests that I would look to add to code to improve robustness.

Here are the results I gathered, calling the tests 10,000 times in a tight loop. The tests were run from the command line, and the times do include PHP start-up / shutdown time and the time taken to parse each test file. I assumed a best-case scenario, where the tests would always pass.

Test Approach Time w/ Tests Disabled Time w/ Tests Enabled
Tests written using assert() 1.103s (100%) 5.989s (543%)
Tests written using ContractLib 3.055s (277%) 3.096s (281%)

When tests are disabled, using assert() is much cheaper than using ContractLib today. That’s to be expected, as assert() is written in C. I imagine that we could get close to the same performance if ContractLib was rewritten in C as a PHP extension.

But, when tests are enabled, assert() is much slower than ContractLib. Why? Because the recommended way to use assert() is to pass the test in as a string. PHP has to convert that string into bytecode to execute, and that conversion appears to be quite expensive.

Given the choice, I’d rather trade things running a little slower in production for having much faster tests when I’m writing code, and that’s why I created ContractLib. Plus I get much better information to understand why the test failed, and if I wanted to run the tests in production, I can handle their failures in a much saner way.

Final Words

In my experience, the time it takes to develop and ship code is normally more critical than how fast the code runs in production. Developer time has become a scarcer resource than CPU time.

Used intelligently, these kinds of tests in your code can help your team deliver quicker, because the code they are using and reusing is more robust first time around. Programming by contract is different to, and complements, unit testing because contract tests catch errors in using the code.

Whether you use ContractLib, assert(), or you create your own solution, you should really consider how much it is costing you when you don’t use these kinds of tests.

Be the first to leave a comment »

In my last blog post, I introduced ContractLib, a simple programming by contract library that I’ve created for PHP 5.3 onwards. And I promised some examples ๐Ÿ™‚

Installing ContractLib

ContractLib is available from the Phix project’s PEAR channel. Installing it is as easy as:

[code lang=”bash”]
$ pear channel-discover pear.phix-project.org
$ pear install -a phix/ContractLib
[/code]

At the time of writing, this will install ContractLib-2.1.0. We use semantic versioning, so these examples will continue to work with all future releases of ContractLib-2.x.

Adding ContractLib To Your Project

Assuming you’re using a PSR-0 compatible autoloader, just import the Contract class into your PHP file:

[sourcecode language=”php”]
use Phix_ProjectContractLibContract;
[/sourcecode]

Adding A Pre-condition Contract To Your Method Or Function

Take a trivial method like this:

[code lang=”php”]
class ActionToApply
{
public function appendNow($params)
{
$params[] = time();
}
}
[/code]

This method works fine … until someone passes a non-array as the parameter. At that point, your code stops working – not because your code is wrong, but because someone used it in the wrong way. This is a classic cause of buggy PHP apps. Thankfully, it’s very easy to address using ContractLib.

If we were certain that the $params parameter was always an array, then we can keep the method itself extremely simple and clean. We can ensure that by adding a pre-condition using ContractLib.

[code lang=”php”]
use Phix_ProjectContractLibContract;

class ActionToApply
{
public function appendNow($params)
{
Contract::Preconditions(function() use ($params)
{
Contract::RequiresValue(
$params,
is_array($params),
‘$params must be an array’
);
});

// original method code continues here
$params[] = time();
}
}
[/code]

Now, if someone passes in a non-array, the caller will automatically get an E5xx_ContractFailedException, which makes it clear that the fault is in the caller’s code … not your’s.

PHP 5.4’s upcoming support for better type-hinting is another way to catch this kind of error, but not only does ContractLib work today with PHP 5.3 (which means you don’t have to wait to migrate to PHP 5.4), but also that you can write tests for anything, not just the checking that’s built into PHP.

This means you can make your code much more robust, by tightening up on the quality of the parameter passed into your code by other programmers. To extend our example, we might decide that an empty array is also unacceptable:

[code lang=”php”]
use Phix_ProjectContractLibContract;

class ActionToApply
{
public function appendNow($params)
{
Contract::Preconditions(function() use ($params)
{
Contract::RequiresValue(
$params,
is_array($params),
‘$params must be an array’
);
Contract::RequiresValue(
$params,
count($params) > 0,
‘$params cannot be an empty array’
);
});

// original method code continues here
$params[] = time();
}
}
[/code]

The point here is that we can go way beyond type-hinting checks (important as they are) and look inside parameters to make sure they are suitable.

Here’s a real example from Phix’s CommandLineLib:

[code lang=”php”]
use Phix_ProjectContractLibContract;

class CommandLineParser
{
// …

public function parseSwitches($args, $argIndex, DefinedSwitches $expectedOptions)
{
// catch programming errors
Contract::Preconditions(function() use ($args, $argIndex, $expectedOptions)
{
Contract::RequiresValue(
$args,
is_array($args),
‘$args must be array’
);
Contract::RequiresValue(
$args,
count($args) > 0,
‘$args cannot be an empty array’
);

Contract::RequiresValue(
$argIndex,
is_integer($argIndex),
‘$argIndex must be an integer’
);
Contract::RequiresValue(
$argIndex,
count($args) >= $argIndex,
‘$argIndex cannot be more than +1 beyond the end of $args’
);

Contract::RequiresValue(
$expectedOptions,
count($expectedOptions->getSwitches()) > 0,
‘$expectedOptions must have some switches defined’
);
});

// method’s code follows on here …
}
}
[/code]

In this real-life code, we start off by checking for basic errors first (by making sure we’re looking at the right type for each parameter), and then we follow up with more specific tests, that ensure that we have data that we’re happy to work with. We’ve done these tests at the start of the method, so that it isn’t cluttered with error checking, which makes our code much cleaner that it might otherwise be. And, because all the tests are in one really easy to spot block, anyone reading your code can immediately see what they have to do to meet the contract you’ve created.

Because these tests are just plain-old PHP code, and don’t rely on annotations or any other such nonsense, the contracts you create and enforce are limited only by your choices.

But Aren’t All Those Tests Slow?

They are. PHP’s getting better and better at this, but function/method calls have always been painfully slow in PHP. I’m afraid that if you want robust code, you can’t have it for free. (You can in C, but that’s a topic to discuss over a decent whiskey at a conference).

I’ve done key two things with ContractLib to keep the runtime cost down:

  1. Contract::Preconditions() accepts a lambda function as its parameter. Your contract’s tests go inside this lambda function, and Contract::Preconditions() only calls the lambda function if contracts are enabled.
  2. By default, ContractLib does not enable contracts. You have to choose to do so by calling Contract::EnforceWrappedContracts().

This keeps the overhead down to just one method call (to Contract::Preconditions()) when contracts are not enabled. It isn’t as good as having no overhead, but it’s cheaper than the developer time lost trying to track down bugs in code that always assumes the caller can be trusted to do the right thing every time.

Any Questions?

I hope these examples have given you an idea on how to get started with ContractLib. If you have any questions or suggestions, please let me know, and I’ll do my best to answer them.

Be the first to leave a comment »

Phix 0.14 Released

Posted by Stuart Herbert on October 24th, 2011 in phix.

Phix v0.14 is now available from pear.phix-project.org.

What’s New In This Release

  • Snapshot versions of components – not ready to release a stable version of your component, but still need to publish your component to your PEAR channel for testing? You can now set the project.snapshot property in your build.properties file, and get non-stable packages for distribution.
  • Code coverage improvements – when you run phing test to run your component’s unit tests and generate the code coverage report, the code coverage report now automatically picks up all of your component’s PHP code, regardless of whether there is a test for it or not.
  • phpunit.xml support – phix now puts a phpunit.xml file inside your component, which includes all of the settings required to execute your component’s unit tests. This should help TextMate users a lot. This change was requested by attendees at the PHPNW11 conference.
  • More hooks in build.local.xml – for every target in your component’s build.xml file, you can now add “local.<target>” in build.local.xml, to perform any additional steps that you want to do. This feature was contributed by Martin Wernstรฅhl.
  • Usability improvements – your component’s build.xml file now traps more errors than before, hopefully making it even easier to learn how to work with components.

How To Upgrade

To upgrade from an earlier release of Phix, please do the following:

sudo pear clear-cache
sudo pear upgrade phix/phix4componentdev

Once you’ve upgraded phix itself, don’t forget to go into each of your components, and run

phix php-library:upgrade .

to upgrade all of the skeleton files (build.xml et al) for your component.

What’s Coming In Phix 0.15

Phix 0.15 is all about making sure that Phix works as well on Windows as it already does on Linux and OSX. The feedback from the ZendCon session (which I was gutted to be unable to attend) was that there isn’t much needed, mostly setup instructions. Once that is done, we’ll continue to support Phix on Windows just as we already do on Linux and OSX.

Our roadmap for Phix 0.15 has all the details.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

We’ve created a development tool, called phix, to make it as easy as possible to create and maintain your own components written in PHP. Phix is normally installed onto a development desktop or laptop; you would normally only need to install Phix on a server running CentOS if the server is a shared development server or a continuous integration server running something like Jenkins.

Follow these easy instructions to get phix installed on CentOS.

Using The One-Line Installer

The easiest way to get phix installed onto your CentOS server is to run the following command from a Terminal window:

curl -O http://phix-project.org/installers/centos-6.sh ; su -c 'bash centos-6.sh'

This command downloads a simple shell script (which you can find on GitHub if you want to read it before trying it!), which is then run as the user “root”. The shell script:

  • Makes sure that you have a suitable version of PHP installed
  • Uses apt-get to install required dependencies
  • Uses the pecl command to install PHP extensions that we can’t get packaged for CentOS
  • Upgrades the PEAR installer to the latest version
  • Installs the package phix/phix4componentdev, plus dependencies, from the PEAR channel pear.phix-project.org

If all goes well, once everything has finished, run the following command and you’ll see that phix is now installed:

$ pear list -c phix | grep phix
phix                       0.13.2  stable
phix4componentdev          0.13.2  stable

Where To Find The Latest Installation Instructions

You can always find the latest installation instructions for phix on the Phix project’s website, including full instructions on how to do a manual install if you have trouble with our one-line installer.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

We’ve created a development tool, called phix, to make it as easy as possible to create and maintain your own components written in PHP. Phix is normally installed onto a development desktop or laptop; you would normally only need to install Phix on a server running Debian if the server is a shared development server or a continuous integration server running something like Jenkins.

Follow these easy instructions to get phix installed on Debian.

Using The One-Line Installer

The easiest way to get phix installed onto your Debian server is to run the following command from a Terminal window:

curl -O http://phix-project.org/installers/debian-6.sh ; su -c 'bash debian-6.sh'

This command downloads a simple shell script (which you can find on GitHub if you want to read it before trying it!), which is then run as the user “root”. The shell script:

  • Makes sure that you have a suitable version of PHP installed
  • Uses apt-get to install required dependencies
  • Uses the pecl command to install PHP extensions that we can’t get packaged for Debian
  • Upgrades the PEAR installer to the latest version
  • Installs the package phix/phix4componentdev, plus dependencies, from the PEAR channel pear.phix-project.org

If all goes well, once everything has finished, run the following command and you’ll see that phix is now installed:

$ pear list -c phix | grep phix
phix                       0.13.2  stable
phix4componentdev          0.13.2  stable

Where To Find The Latest Installation Instructions

You can always find the latest installation instructions for phix on the Phix project’s website, including full instructions on how to do a manual install if you have trouble with our one-line installer.

Be the first to leave a comment »

In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.

We’ve created a development tool, called phix, to make it as easy as possible to create and maintain your own components written in PHP. Apple OSX users might want to follow these instructions for setting up PHP et al on OS X 10.7 Lion first, before installing phix.

We assume that you’ve installed Xcode (which is free from the Mac Store)!

Using The One-Line Installer

The easiest way to get phix installed onto your shiny Macbook Air or Macbook Pro is to run the following command from a Terminal window:

curl -O http://phix-project.org/installers/osx-10.7.sh ; sudo bash osx-10.7.sh

This command downloads a simple shell script (which you can find on GitHub if you want to read it before trying it!), which is then run as the user “root”. The shell script:

  • Makes sure that you have a suitable version of PHP installed
  • Upgrades the PEAR installer to the latest version
  • Uses the PECL command to install additional PHP extensions (this is what you need Xcode for!)
  • Installs the package phix/phix4componentdev, plus dependencies, from the PEAR channel pear.phix-project.org

If all goes well, once everything has finished, run the following command and you’ll see that phix is now installed:

$ pear list -c phix | grep phix
phix                       0.13.2  stable
phix4componentdev          0.13.2  stable

Where To Find The Latest Installation Instructions

You can always find the latest installation instructions for phix on the Phix project’s website, including full instructions on how to do a manual install if you have trouble with our one-line installer.

Be the first to leave a comment »
Page 1 of 512345

This Month

July 2017
M T W T F S S
« Jul    
 12
3456789
10111213141516
17181920212223
24252627282930
31