Learn More About PHP And The Web Platform!

Struggling with your web server, or to scale your PHP application to meet growing demand?

Whether you're running one server or a whole server farm; whether you're hosting on Windows Server or on Linux.

Learn from Stuart's experience with system design, delivery, support and management to help you do a better job and have an easier time.

Beneath Whitby breakwater

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.

I’ve just put out ComponentManager version 1.1.0, with the following (hopefully useful) changes:

Improvements To The php-library Skeleton

  • Once you’ve setup your metadata, phing build-vendor will build with no errors.

    I’ve added an empty src/php/dummy.php file, so that a valid empty PEAR-compatible package can be build and installed. You’ll want to remove this file when you start putting your own code into the component.

  • New build.property: project.channel. Set this to the name of your PEAR channel. Automatically picked up by package.xml now.
  • New build.property: pear.local. Set this to the folder where your local copy of your PEAR channel resides. (See my blog post for details about why you might want a local copy of your PEAR channel).
  • New build.xml target: publish-local. You can now do phing publish-local to use pirum add your component to your local copy of your PEAR channel.

Bug Fixes For The php-library Skeleton

  • Now tested on both Ubuntu and Fedora 14, especially for @phpcodemonkey.
  • Now excludes .DS_Store folders from the final component, for those using these tools on OS X.
  • Now excludes .svn folders from the final component.
  • Now excludes .empty files from the final component.

How To Upgrade

To upgrade your installation, please do the following:

$ pear clear-cache
$ pear upgrade pear/pear
$ pear upgrade Gradwell/ComponentManager

Once the latest version of ComponentManager has been installed, you can upgrade the skeletons of your existing components by doing:

$ cd <where-I-put-it>/<my-component>
$ phix php-library:upgrade .

You will then want to edit build.properties, to set the new properties added in this release.

Any problems, let me know.

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.

In previous articles, I’ve introduced you to the component skeleton that phix creates for you when you run the phix php-library:init command. Our skeleton is designed to be extremely clean, so that it is very easy to automatically generate your PEAR-compatible component and its package.xml file, so that you don’t have to maintain it yourself (a process which would only end in tears).

At the heart of our skeleton, are the design constraints imposed by the PEAR installer, and that means the way it handles files differently depending on the file’s role.

What Are File Roles?

A file’s role is simply a way of telling the PEAR installer where you want the file installed. The PEAR installer supports the following file roles:

  • data – any data files that your component needs to read at run-time
  • doc – documentation about your component
  • php – your PHP code
  • script – any command-line scripts your component includes
  • test – your (hopefully, PHPUnit-based) tests
  • www – PHP code to be served by Apache

… plus a few more that are of no interest to authors of PHP components.

Where Do I Put Files For Each Role?

To make it extremely easy for the phing pear-package command to auto-generate your package.xml file, there’s a folder in our component skeleton for each type of file.

Here’s a handy summary showing you where to put your files inside your component, based on their role:

  • data – goes in the src/data/ folder
  • doc – goes in the src/doc/ folder
  • php – goes in the src/php/ folder
  • script – goes in the src/bin/ folder
  • test – goes in the src/tests/unit-tests/ folder
  • www – goes in the src/www/ folder

In the next few articles, I’m going to look at each of these file roles in turn, and show you in detail how the PEAR installer treats them, and how to work with them in your own components, starting with the php role.

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.

In my last article, I looked at how to publish your own PEAR channel, and why today that’s the best option for you and your projects. It takes about 10 minutes to publish your first PEAR channel, thanks to Fabien’s work on creating Pirum.

But what is it like to actually work with your own PEAR channel on a long-term basis? What are the things you could do to make things as easy as possible?

Tip 1: Local Copy Of Your PEAR Channel

Sometimes, you develop a component for the sake of it, but most of the time, you end up writing your components and the app that needs them side by side. This is what happened with phix et al, and behind the scenes here it is also what is happening with the components for my example app called sental.

When that happens, no matter how focused and skilled your unit testing is, you’ll want to release preview versions of your component, try them in your app, and then go back to your component and tweak things … all before you’re ready to share the next release of your component via your PEAR channel. This is what the ‘alpha’ and ‘beta’ stability flags in package.xml were originally designed for, but it’s more pragmatic to have a local, private copy of your PEAR channel on your dev box, and leave those stability flags well alone.

Here are the steps you need to follow to setup your own private copy of your PEAR channel on a Linux box:

  1. Setup Apache on your dev box with a virtual host to publish your PEAR channel, just like you have done on your public webserver.
  2. Use pirum to create your PEAR channel’s files on your dev box (or, even better, see Tip 3 below).
  3. Edit /etc/hosts to have the fully-qualified domain name for your PEAR channel point to IP address 127.0.0.1.

With this done, every time you use the PEAR installer on your dev box to install something from your PEAR channel, the PEAR installer will actually download your component from your private copy of your PEAR channel. You can keep putting new copies of your component onto this private copy of your PEAR channel until you’re satisfied with it, and it doesn’t matter that you’re not actually bumping the version number of your component each time you do so, because only you are affected.

And when you’re ready to send this new version out into the world, you just need to tag the release in source control, and then upload your private copy of your PEAR channel to your public webserver.

(Btw, if you do a lot development disconnected from the internet like I do, having a local copy of your PEAR channel is pretty much a must!)

Tip 2: Tag Your Releases

Once you’ve decided that your component is ready to share with everyone on your PEAR channel, that’s the time to tag your release in source control. It’s dead easy to do, and it gives you and anyone else who takes over maintenance of your code a record of what was in each release.

Here’s how to do it in git.

stuart:~/Devel/sental/repustateApi$ git tag -a -m 'Release 0.1.0' 0.1.0
stuart:~/Devel/sental/repustateApi$ git push --tags origin master

If you’re publishing on GitHub, you can then go to your component on there and forever more see your code for that release. Here’s the repustateApi component at version 0.1.0 on GitHub, as a real example of tagged code. An even better example is Sebastian Bergmann’s PHPUnit project, where at the time of writing there are 193 tags to see!

As an aside, we really should be digitally signing these tags, but that is a topic in its own right for a later blog post!

Tip 3: Publish Your PEAR Channel Via Source Control

It isn’t just the code for your components that can be tracked via source control; there is nothing stopping you from publishing your PEAR channel via source control too. pear.gradwell.com is our public PEAR channel, and we have a pear.gradwell.com repo up on GitHub for it.

This makes it extremely easy to publish new packages to our PEAR channel. On my dev box, I add a new release to source control like this:

stuart:/var/www/pear.gradwell.com$ git clone git@github.com:Gradwell/pear.gradwell.com.git
stuart:/var/www/pear.gradwell.com$ pirum add . ~/Devel/repustateApi/dist/repustateApi-0.1.0.tgz
stuart:/var/www/pear.gradwell.com$ git add -i
stuart:/var/www/pear.gradwell.com$ git commit -m 'Added repustateApi-0.1.0'
stuart:/var/www/pear.gradwell.com$ git push origin master

… and then I SSH into our public webserver, and simply do:

stuart:/var/www/pear.gradwell.com$ git pull

Job done 🙂

This is actually a very handy setup when you have more than one developer publishing packages. Each of your developers merges their new releases into source control, so that no-one trips over each other (very important in a distributed team), and everyone can clearly see who has published what.

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.

In the last article, I explained how to create a PEAR-compatible package from your component, and how to install the package both for local testing and for system-wide use on your own computer. One of the strengths of picking the PEAR installer for our components is that it’s a very easy way for others to download and consume our components.

We just need somewhere to publish them. We either need to find an existing PEAR channel to publish to, or we need to publish our own.

To Self-Publish Or Not

It’s worth taking a moment to consider whether you should publish your own PEAR channel or not.

At the time of writing, the components culture in the PHP community is at an embryonic stage of development. There are curated pockets here and there, but we have nothing yet that compares with both the traction and ubiquity of RubyForge or Perl’s CPAN.

There is the venerable PEAR project, which has given us the installer I’m using for the components skeleton featured in these blog posts, but its no-compete policy for packages means that you have to apply for permission to have your package carried by their channel.

There are other efforts around such as Pearhub and Pearfarm, but neither of them have really nailed the complete experience for both package publisher and package user at this time. If anyone wants to take up the challenge of providing our community with a modern, credible equivalent to RubyForge, I’d love to hear from you 🙂

This is why many of the tools you’ll hear talked about at PHP conferences (such as the QA tools that Sebastian talks regularly about) end up being self-published. Today, it’s simply easier to do.

How To Setup Your Own PEAR Channel

Self-publishing your PEAR channel is incredibly easy. All you need is some web-hosting space, and Fabien’s Pirum. Pirum is a very simple, very straight-forward tool that creates and updates all the files needed for your own PEAR channel. Best of all, these files are all static files, keeping things lean and mean.

To install Pirum, simply run these commands from the command-line:

pear channel-discover pear.pirum-project.org
pear install pirum/Pirum

This installs a command-line tool that you’ll use to create your PEAR channel.

Next, you need to configure Apache to serve your PEAR channel to the world. By convention, PEAR channels normally are http://pear.<project>.whatever or http://pear.<vendor>.whatever. The PEAR installer works best if your PEAR channel files are in the DocumentRoot of your website.

Let’s say that the DocumentRoot of your PEAR channel is going to be /var/www/pear.example.com. Once you’ve configured Apache to serve pear.example.from from /var/www/pear.example.com, you need to create a pirum.xml file to describe your PEAR channel. This is a very simple file that tells Pirum the essential information it needs to create your PEAR channel’s files.

mkdir /var/www/pear.example.com
cd /var/www/pear.example.com
vi pirum.xml

For pear.example.com, the pirum.xml file would look like this:

<?xml version="1.0" encoding="UTF-8" ?>
<server>
	<name>pear.example.com</name>
	<summary>Example PEAR channel</summary>
	<alias>Example</alias>
	<url>http://pear.example.com</url>
</server>

Now we need to tell pirum to build our PEAR channel files:

cd /var/www/pear.example.com
pirum build .

Congratulations – you now have your own PEAR channel. Remember to change ‘pear.example.com’ to be the actual name of your own PEAR channel, and you too can have your own PEAR channel up and running in about 10 minutes first time around.

Once you’ve built a PEAR-compatible package from your component, it’s one command in Pirum to publish that package on your PEAR channel.

Adding A Package To Your Own PEAR Channel

Let’s say I’m going to publish my RepustateApi package on the pear.example.com channel I created above. The full sequence of commands to create and publish the channel is:

stuart:~/Devel/repustateApi$ phing pear-package
stuart:~/Devel/repustateApi$ pirum add /var/www/pear.example.com dist/repustateAPI-0.1.0.tgz

It’s that straight forward 🙂

Now, in reality, you’re unlikely to be developing your PHP components on your public webserver. You’re more likely to be developing your PHP components on your local desktop or laptop (or on a shared development server), and then uploading the final results to your public webserver. This is how we work at Gradwell right now, and in the next blog post I’ll go through our actual workflow for publishing a new or updated component, showing you how we’re setup to both support multiple contributors and disconnected development.

5 comments »

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.

Now that my repustateApi client component both has working API calls and 100% code coverage from its unit tests, I want to make a PEAR package ready for release. At this stage, I’m only going to release it for internal testing (and so that the other components in my app can use it); there are plenty of other things to be done before it is really fit to release to the wider world.

What Is A PEAR-Compatible Package?

The PEAR installer is the de facto standard tool for installing reusable components into a PHP environment. Chances are that it was installed onto your computer when PHP was installed; if not, it’s normally available as a package for your operating system of choice. One day it will be replaced by Pyrus (the next-generation PEAR installer); Pyrus supports the same packages that the PEAR installer does.

Both installers know how to download PEAR-compatible packages from websites (known as channels), how to install them, and importantly how to upgrade them when new releases become available. This makes PEAR-compatible packages a good choice when picking the format to ship your component.

The package itself is a tarball containing:

  • package.xml, a manifest file that tells the PEAR installer all about the package and its contents, and
  • your PHP code (plus any additional files) that you want the PEAR installer to install

A lot of the work that has gone into the skeleton files for the component is make it easy to create a PEAR-compatible package.

How To Make A PEAR-Compatible Package

To make a PEAR-compatible package, go into the top-level folder of your component (where the build.xml file is), and run this command:

stuart:~/Devel/sental/repustateApi$ phing pear-package

This will build a PEAR-compatible package from your source code, and put it in the dist/ folder for you.

How To Test The Package

If you want to test that the package itself is compatible with the PEAR installer, go into the top-level folder of your component, and run this command:

stuart:~/Devel/sental/repustateApi$ phing install-vendor

This will install your PEAR-compatible package into the ‘vendor/’ folder for you, alongside your component’s dependencies.

How To Install The Package Onto Your Computer

If you want to install your PEAR-compatible package into /usr/share/php on your computer, go into the top-level folder of your component, and run this command:

stuart:~/Devel/sental/repustateApi$ sudo phing install-system

The sudo command will prompt you for your password, and will then run phing as the ‘root’ user, so that it has permissions to write into /usr/share/php.

Of course, the very best way to install your PEAR-compatible package is by publishing it to your own PEAR channel, and that’s something I’ll explain in the next blog post.

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.

Working unit tests is only half the battle. If your unit test doesn’t cover 100% of the code, chances are you’re shipping bugs. 100% code coverage doesn’t guarantee bug-free code by any means, but it’s an important step in the right direction. There isn’t much point in shipping code that other developers cannot trust; they will just go elsewhere to get their components.

How Much Of My Code Is Covered By My Tests?

The skeleton component created by the phix php-library:init command makes it very easy for you to see how much of your code is covered by your unit tests. To do this, you need to make sure that you have Derick’s excellent xdebug extension installed. After that, just run your unit tests from the command line, and our skeleton will take care of generating the code coverage data.

stuart:~/Devel/sental/repustateApi$ phing test

This command will generate a HTML-based report in the ‘review/code-coverage’ folder:

This report shows you exactly which lines have been executed during the unit tests, and which lines of code have gone untested, making it very easy for you to see where the gaps in your testing are.

Aim For 100% Code Coverage

I’m the first to admit that this is something I’ve changed my tune over. When I was trained as a professional engineer in the 1990’s, we were taught to do 100% code coverage … and, frankly, the cost of writing all those tests seemed horrendous to me. On one project I worked on, the project manager told me that he budgeted 40% of our time for writing tests. As the dot com bubble came, and everyone rushed to compete on Internet Time (no, I didn’t believe in it then, and I definitely don’t believe in it now!), the emphasis was on shipping code with all possible haste. 100% code coverage seemed a luxury no-one could afford.

Today, with the benefit of 20/20 hindsight, I can clearly see that the costs of shipping partially-working / barely-working code are just too high. Even cobbled-together code ends up surviving for many years longer than anyone anticipated, and that just means generation after generation of programmer having to waste time maintaining the code, or spending their time instead creating and shipping their own barely-working code.

I’ve been experimenting with, and developing, this approach to components in PHP since summer 2010 (annual vacations are great for getting some hacking done!), and there’s no way I’m going to admit how many bugs I found in my own code – code I was actively using – when I went back to add 100% coverage 🙂 Suffice to say it was a lot, and more than enough to convince me of just how important 100% code coverage is to a component.

100% code coverage does not guarantee that your code is bug-free; it is not the magic target that will produce zero-defect code. But it is a good step in the right direction.

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.

To be a success, all components need high-quality unit tests, and this applies to the component I am building, a client for Repustate.com’s semantic analysis API. But how do you go about creating the unit tests for a remote web service without the process becoming onerous or even dangerous?

Can You Test The Quick And Nasty Way?

This is the first question that always comes to mind whenever I’m writing an API client. I don’t want to do it the classical way, of creating my own mockup of the web service, if that can be avoided. Mockups are slower to build, and they perpetuate any misunderstandings I have about the API and its behaviour. I want to test directly against the API, so that I can catch errors immediately, and have confidence that my code will work in production. Technically, these are integration tests not unit tests, and there are good arguments out there for also having the mocked up unit tests too, but I’m a pragmatic engineer, and I need to get this done before my app’s requirements change.

Now, this all comes down to whether or not the web service makes life easy for developers or not.

  • Does the web service provide a test API, where I can reset the state of my account to a known position before I start testing?

    This is the holy grail for writing tests against an API. Tests must be deterministic – same data in must always produce the same result out – to be trustworthy. Being able to use a test API, where I can control the starting conditions before I run my tests, gives me everything I need to safely test against the web service’s endpoint.

    Sadly, you’re more likely to see a unicorn than come across one of these, but never give up hope!

  • Is the API destructive in a disruptive way?
  • If I have to test against the live API, can I do so safely? Can I write tests that will not cause trouble for my production systems that are using the API?

    Often, the answer to this is ‘yes’, which is great news. Not as good as our unicorn-test-API above, but something I can work with.

  • Do I have to mock up the API locally?

    This is the testing of last resort, tbh … but sometimes you’re left with no choice on the matter.

    And, it’s worth me mentioning that API mockups are actually the best way to deal with regression tests against your own client, as they allow you to catch badly-formed requests to the remote API perfectly.

At the time of writing, I couldn’t find my unicorn-test-API for Repustate, but because their live API is entirely non-destructive, there is little risk in making my unit tests for this component work against the live API.

Never Commit Your API Key

Like many web services, Repustate’s requires you to apply for an API key, which is then used to authorise your web service requests. This allows Repustate to keep track of who is doing what, and allows them to revoke access if the web service is abused.

To run the tests against the live API, my test code is going to need to know the API key that I’ve obtained from Repustate. But if I commit that to the component’s public GitHub repo, I’m simply asking for every script kiddie to abuse that key. It’s simply not safe to commit this key. And it wouldn’t be safe if the repo was private; how do I know that one day the repo won’t be open-sourced, with the key available to find in the repo’s history?

Never, ever, ever, commit an API key to a component’s source control repo.

But my test code needs this API key. Where can it get the API key from? We could put the key in a config file that’s installed by an uber-secret component, and indeed this is a practical approach when you’re controlling the deployment of apps in the enterprise. (Just don’t make it so secret that your own devs can’t work on it. That kinda brings a lot of work to a standstill). But that won’t work for an opensourced component that hopefully others will find useful.

So we need to put the API key somewhere else, just for the tests to work.

Getting The Key From The Environment

The easiest place for the unit tests to look is in the process’s environment. First, I need to set the key, like this:

stuart:~/Devel/sental/repustateApi$ export REPUSTATE_KEY="<my API key>"

This puts the key into the environment of my terminal’s bash shell. When I run the tests from this shell, the API key will be available for my tests to use:

[code lang=”php”]
$apiKey = getenv(“REPUSTATE_KEY”);
[/code]

This is a handy tip, and it means I can now get on with the quick-and-dirty approach to unit testing my component, without worrying about giving anyone my API key to abuse.

It does cause one problem though: anyone who downloads my component and tries to run the unit tests will simply see them fail. I will mention it in the component’s README.md file, but I cannot rely on anyone actually reading that file in all honesty. For now, I’ve addressed that by testing for the REPUSTATE_KEY environment variable, and if it doesn’t exist, the unit tests die() with clear instructions rather than fail.

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.

A component-based approach works well with the new namespace support added to PHP 5.3, and indeed I’m making full use of this in the components I’m building for this tutorial. But not everyone is ready to move to namespaces, and when you start to consume older components inside yours, you might run into errors.

Namespaces Recapped

The whole idea behind namespaces is to make life easier for developers, by doing away with having to type incredibly long class names all the time. For example, take the ConsoleDisplayLib component I recently released. In the pre-PHP 5.3 days, I would have had to define the classes it provides like this:

[code lang=”php”]
class Phix_Project_ConsoleDisplayLib_StdOut { … }
[/code]

… and then when I wanted to use it, I would have to do this:

[code lang=”php”]
$stdout = new Phix_Project_ConsoleDisplayLib_StdOut();
[/code]

A workable system, to be sure, and one that OO PHP programmers have used for many years, but hardly RSI-friendly, I’m sure you agree. With namespaces, however, things change. The class is now defined like this:

[code lang=”php”]
class Phix_ProjectConsoleDisplayLibStdOut { … }
[/code]

Note the use of ” instead of underscores. That’s PHP’s new namespace separator, and it tells PHP that the class StdOut lives inside the Phix_ProjectConsoleDisplayLib namespace, which in turn lives inside the Phix_Project namespace. Namespaces are just another kind of scope, like local scope vs global scope. Hold that thought, because it’s these new scopes that affect our attempts to mix in non-namespaced code.

If I’m writing code that is part of ConsoleDisplayLib, to create a new StdOut object, I now only need to do this:

[code lang=”php”]
namespace Phix_ProjectConsoleDisplayLib;

$stdout = new StdOut();
[/code]

PHP automatically expands ‘StdOut’ to mean ‘Phix_ProjectConsoleDisplayLibStdOut’, because I’ve used the namespace keyword to tell PHP that this code is part of Phix_ProjectConsoleDisplayLib.

And that is where the fun begins.

Adding HTTP_Request2 To RepustateApi

I’ve made the choice to reuse the existing PEAR component HTTP_Request2. The PEAR project doesn’t currently use namespaces; all classes defined by HTTP_Request2 exist in the global scope. So if I try to use HTTP_Request2 like this inside my Repustate API client:

[code lang=”php”]
namespace GradwellRepustateApi;

$httpClient = new HTTP_Request2($url, HTTP_Request2::METHOD_POST);
[/code]

… PHP reports the fatal error: Class GradwellRepustateApiHTTP_Request2 not found.

First time you see this, you might be wondering what is going on, and how to fix it. After all, the class is called HTTP_Request2. Why is PHP trying to load a class called GradwellRepustateApiHTTP_Request2?

The answer is simple. By using the namespace keyword at the top of the file, I’ve told PHP to assume that all of the code in this file is part of the GradwellRepustateAPI scope. So, just like in my ConsoleDisplayLib example where PHP automatically expanded StdOut to be Phix_ProjectConsoleDisplayLibStdOut, PHP is going to expand HTTP_Request2 to be GradwellRepustateApiHTTP_Request2.

That isn’t what we want, but that’s PHP’s fault. We need to tell PHP that, in this case, we want it to load HTTP_Request2, and not GradwellRepustateApiHTTP_Request2.

Load From The Global Namespace

Getting PHP to load code from the global namespace, instead of from your component’s namespace, is very easy … you’ve just got to remember to do it everywhere. Simply make sure you’ve put a ” at the start of any classnames that are part of the global namespace:

[code lang=”php”]
namespace GradwellRepustateApi;

$httpClient = new HTTP_Request2($url, HTTP_Request2::METHOD_POST);
[/code]

Remember to do this, and you’ll have no trouble working with non-namespaced components inside your own components.

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.

Last week, I began work on a simple component to talk to the Repustate semantic analysis API. To save myself a bit of effort, I thought it would make sense to make my API client reuse PEAR’s existing HTTP_Request2 component. No sense in re-inventing the wheel, I thought. But that’s where my troubles began.

There are a few quirks in the way that the PEAR installer handles version numbers, and you need to know how to deal with them if you’re going to re-use PEAR project components in your own apps.

Adding A Dependency On HTTP_Request2

HTTP_Request2 is PEAR’s very useful wrapper around making HTTP requests from your app. At the time of writing, there are 22 PEAR packages that rely on it: a good indicator that this component is doing something right.

Making the repustateApi component rely on PEAR’s HTTP_Request2 should be as simple as adding the following to the %lt;required> section in package.xml:

<package>
  <name>HTTP_Request2</name>
  <channel>pear.php.net</channel>
  <min>2.0.0</min>
  <max>2.999.9999</max>
</package>

But, when I try to rebuild the vendor/ folder (this is the sandbox where all of the component’s dependencies are installed, so that we can run our unit tests), using the command phing build-vendor, I get an error:

[echo] Populating vendor/ with dependencies
[exec] Executing command: phix pear:register-channels 2>&1
[exec] Registering PEAR channel pear.gradwell.com
[exec] Adding Channel "pear.gradwell.com" succeeded
[exec] Discovery of channel "pear.gradwell.com" succeeded
[exec] Registering PEAR channel pear.php.net
[exec] Channel "pear.php.net" is already initialized
[exec] Executing command: pear -c /home/stuarth/Devel/sental/repustateApi/.tm
p/pear-config install --alldeps /home/stuarth/Devel/sental/repustateApi/.buil
d/package.xml 2>&1
[exec] Failed to download pear/HTTP_Request2 (version >= 2.0.0, version = 2.0.0, version <= 2.999.9999)
[exec] downloading Autoloader-2.0.1.tgz ...
[exec] Starting to download Autoloader-2.0.1.tgz (2,080 bytes)
[exec] ....done: 2,080 bytes
[exec] install ok: channel://pear.gradwell.com/Autoloader-2.0.1

So what’s going on? And what do we need to change to make this dependency work?

PEAR Version Numbers and Stability

There are two things preventing the PEAR installer from downloading the package:

  • The package’s version number is 2.0.0beta2, not plain old 2.0.0
  • The package has been marked as beta quality, rather than as a stable release.

From HTTP_Request2’s point of view, this is all perfectly reasonable. The package authors are currently transitioning from the older PHP4-based HTTP_Request, and they’re not yet ready to unleash HTTP_Request2 on the world.

As a result, the PEAR installer is (rightly) looking at the dependency information I’ve set, and telling me that HTTP_Request2 is not yet at version 2.0.0.

The PEAR installer doesn’t just use version numbers when handling dependencies. If you dig deep into package.xml, you’ll find not only a <version> tag, but also a <stability> tag. Here’s the tags from PEAR’s HTTP_Request2’s package.xml at the time of writing:

  <version>
    <release>2.0.0beta2</release>
    <api>2.0.0</api>
  </version>
  <stability>
    <release>beta</release>
    <api>beta</api>
  </stability>

How To Depend On A Beta PEAR Component

The ‘fix’ we need to make to package.xml is very simple; simply depend on the beta version:

<package>
  <name>HTTP_Request2</name>
  <channel>pear.php.net</channel>
  <min>2.0.0beta1</min>
  <max>2.999.9999</max>
</package>

With this change made, the PEAR installer does the right thing, and installs HTTP_Request2 just like I want it to 🙂

It remains to be seen what will happen when HTTP_Request-2.0.0 and beyond are released. Will the PEAR installer download it, or will I have to come back and edit the dependency in package.xml? I’ll post news on that when the time comes.

With the right dependency information in package.xml, I can now get back to cranking out the code for the repustateApi component.

Be the first to leave a comment »

Beyond Frameworks: The Page

Posted by Stuart Herbert on March 26th, 2011 in Toolbox.

I’ve put together a page on my blog to collate my Beyond Frameworks series of articles about building PHP components into one convenient place. If you’re enjoying the series, you might find it a handy reference page to bookmark.

And if you missed the beginning of the series, why not head on over and see what I’m up to? 🙂

PS: Thank you to everyone who has left comments or pinged me on Twitter so far. The feedback is excellent to have – more please 🙂

Be the first to leave a comment »
Page 8 of 18« First...678910...Last »

This Month

January 2018
M T W T F S S
« Jul    
1234567
891011121314
15161718192021
22232425262728
293031