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 edited the build.properties file to set the component’s name and version number. I need to finish setting up the component’s metadata by editing package.xml.

Introducing package.xml

Every PEAR-compatible component needs to ship with a manifest file called package.xml. You can see the the unedited version on GitHub that we’re about to change.

package.xml contains the following useful information:

  • The component’s name, channel, version number, and description.
  • A list of the component’s authors.
  • The component’s license.
  • A list of the component’s contents.
  • A list of the component’s dependencies, including PHP version, PHP extensions, and other components.

(package.xml can hold other information too, but I’ve yet to see them being put to practical use, so we’ll leave them for today and come back to them if needed later on).

In our component skeleton, we need to add some of this data to package.xml, and the rest will be added automatically by the tools when we build a PEAR-compatible package, to save us the trouble of doing it by hand.

Setting Up The Component’s Name And Channel

All PEAR-compatible packages have a fully-qualified name of the form <channel>/<name>. In this skeleton, our tools will automatically inject project.name from the build.properties file into package.xml’s <name> tag when we build the PEAR-compatible package. We just need to edit the <channel> tag in package.xml to point to our server.

As I’m going to publish these packages via our public PEAR channel, I’ve set <channel> to be “pear.gradwell.com”. Don’t worry if you don’t have your own PEAR channel yet; they’re very easy to create, and I’ll look at exactly how to set one up and publish it later in this series.

Setting Up The Component’s Version Number, And Description

All PEAR-compatible packages have a version number. We’ve already set this in build.properties; our tools will automatically inject this into package.xml. (We could have put this directly into package.xml, but the version number is duplicated in a couple of places, and it seems much easier to let the tools deal with that so that we don’t forget to update all the version numbers when we make a new release).

For the description, edit the &lt:summary> and <description> tags. The descriptions get used in the human-friendly HTML page that each PEAR channel has, so they’re worth the trouble of filling in.

Setting Up The Component’s Author

There’s a few tags inside package.xml that tell anyone who is interested who the current author of the component is. This information gets used in the human-friendly HTML page that each PEAR channel has. I’ve set these tags as follows:

[code lang=”xml”]
Stuart Herbert
stuartherbert
stuart@stuartherbert.com
yes
[/code]

Setting Up The Component’s License

The <license> tag contains text to say under what license the component has been released. By default, the skeleton sets this to be “All rights reserved.” Whilst I’d love you to opensource all of your components, I wouldn’t like to presume 😉

For our component, I’ve set this tag to say “New BSD license.”.

Setting The List Of The Component’s Contents

The <contents> tag is where the PEAR installer expects to find a file-by-file list of all of the files that need to be installed, along with instructions on where to install them. Each file is flagged as being a specific ‘role’ – script, php code, data file, unit test, website page – and the PEAR installer then decides for you where it will put them. Don’t try fighting it; it has some built-in assumptions that aren’t worth trying to work around.

We don’t need to edit this tag at all. When we build our PEAR-compatible package later on, the tools will manage this section for us. It saves a lot of time and effort, and debugging!

Setting Up The Component’s Dependencies

Finally, we get to the bit that makes it all worthwhile: the list of what this component needs in order to work. By getting these right, we can reliably re-create the entire environment that our app needs with just a single command.

A practical demonstration is needed, I think, because this is probably something you’ve never had the opportunity to do before now.

stuart:~/Devel/sental/repustateApi: phing build-vendor

When I run that command, our tools will download all of the dependencies listed in package.xml, and install them into a folder called ‘vendor’. This gives us a reproducible sandbox, where we can find the correct versions of all the code needed to unit test our component. We don’t have to ensure the right version is installed on the computer; we get our own copy of everything needed. If you develop on shared servers, or even if you end up maintaining a lot of components, this is a real time saver.

If you run that command locally, and look inside the ‘vendor’ folder it creates, you should see that our tools have downloaded and installed the Autoloader package that’s listed in package.xml’s list of dependencies. As we add more PEAR-compatible packages to the package.xml’s dependency list, we can rebuild the vendor folder and install all of the dependencies side by side. I’ve picked the repustateApi component because it will allow me to demonstrate that as we go along.

Please ignore the errors that you will see scroll up the screen when you run ‘phing build-vendor’ at this stage. Unfortunately, the PEAR installer doesn’t seem to have a command to install just the dependencies (i.e. pear install –onlydeps) listed. It’s also trying to install our component’s PEAR-compatible package, which doesn’t exist yet.

The Final package.xml File

You can see the final package.xml file, containing all of the edits listed in this blog post, on Github.

As we work on the component and then release it, we will need to come back and edit package.xml a little more. But we’ve done what we need to, for now, and can get started on creating some code.

My apologies if it seems like a lot of work just to create an empty component and then sort out the component’s metadata. In all honesty, after you’ve done it a few times, you can create a new component in a matter of minutes, and this is work you only have to do the once.

In the next blog post, we’re going to start creating the initial tests for this component.

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 post, I used phix to create an empty component. I now need to edit the component’s manifest files before I can start cutting code.

What’s Your Component Called?

The first file we need to edit is called build.properties. It’s a standard-format .ini file that contains a few bits of data for us to edit. When I designed the component skeleton, I put these in their own file so that we never have to edit the build.xml file … which means we can upgrade build.xml in future via the phix php-library:upgrade command.

An unedited build.properties file looks like this:

project.name=<your project name>
project.majorVersion=X
project.minorVersion=Y
project.patchLevel=Z

checkstyle.standard=Zend

component.type=php-library
component.version=3

As this is the first version of my component, I’m going to call this version of the component repustateApi-0.1.0. That means that I need to change the top four lines of build.properties to look like this:

project.name=repustateApi
project.majorVersion=0
project.minorVersion=1
project.patchLevel=0

(You can see the fullly-edited build.properties file on GitHub).

Why did I pick 0.1.0 as the version number?

What’s In A Version Number?

When it comes to components, we need to adopt a sane and engineering-focused version numbering scheme, otherwise we run into a lot of trouble when trying to trust our own and other people’s components over time. I went into this in some detail in my Beyond Frameworks talk, and it basically boils down to this:

  • The scheme itself reads major.minor.patchLevel, or, if you prefer, x.y.z.
  • All versions 1.y.z must be 100% backwards-compatible. You can fix bugs and add new features, but if you break backwards-compatibility, you need to create version 2.y.z.

    The people who use your components need to be confident that they can upgrade the component (to get the latest fixes and features) without any nasty surprises that force them to also go to the trouble of editing their own code. Make the major version number your promise to other developers that they can upgrade safely.

    Don’t be afraid to create version 2.y.z, version 3.y.z etc as rapidly as needed. Google has done exactly this with Chrome, and it hasn’t exactly done them any harm.

  • If you’re adding new features, and not breaking backwards compatibility, turn version 1.0 into version 1.1, 1.2, and so on.
  • And if you’re only putting out bug fixes, just increase the last number, and turn version 1.0.0 into version 1.0.1, 1.0.2 and so on.

This numbering scheme is called Semantic Versioning. Please do follow it.

That’s all that we need to edit in build.properties. We still need to setup package.xml, which I’ll cover 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.

In my last article, I posted a list of questions to consider when decomposing the design of an app, and I put together the first cut of the components that will make up my sentiment analysis app. Now it’s time to get into creating the app’s first component, using phix.

Dev Environment Prep

If you haven’t already, you’ll need to install phix onto your dev computer. You’ll find the latest instructions on how to install phix on the Phix Project’s website. Thankfully, we only have to do that once. Now, with the development environment prepared, we can get our component under way.

Creating The Skeleton For The Component

Creating a skeleton component is as easy as:

stuart:~/Devel/sental$ mkdir repustateApi
stuart:~/Devel/sental$ cd repustateApi
stuart:~/Devel/sental$ git init .
Initialized empty Git repository in /home/stuart/Devel/sental/repustateApi/.git
stuart:~/Devel/sental/repustateApi$ phix php-library:init .
Initialised empty php-library component in .

What have we created?

A Quick Tour Of The Skeleton

Here’s a quick list of what the php-library:init command has created in the repustateApi folder:

stuart:~/Devel/sental/repustateApi$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#	.gitignore
#	.hgignore
#	LICENSE.txt
#	README.md
#	build.properties
#	build.xml
#	package.xml
#	src/
nothing added to commit but untracked files present (use "git add" to track)

Each of the files serves a useful purpose:

  • .gitignore and .hgignore

    These are basic filters to tell Git and Mercurial what to ignore in here. As we develop the component, there will be a few temporary folders created which we’ll never want to end up in version control. Filter files for other version control systems are welcome.

  • LICENSE.txt

    Every component needs to come with a clear statement about the rules for re-use, even if it just says All rights reserved.

    If you’re looking to open-source your code, you’ll find many well-tested licenses from the Open Source Initiative’s website.

  • README.md

    Every component needs basic documentation to help a new user get started with it. By putting that into a README.md file, GitHub will automatically pick that up and display it on the component’s website.

  • build.properties

    This is a file we’re going to edit shortly. It contains a little bit of metadata about your component, such as it’s name and version number.

  • build.xml

    This is a file for phing, a sort-of Ant clone written in PHP. We’re going to use the commands defined in this file to run our unit tests, build our PEAR-compatible package, and even install it for local testing.

  • package.xml

    This is the manifest file that the PEAR installer looks for when trying to install your component.

    We’re going to edit this file shortly, adding in some data about our component, but most importantly, listing all of the components that our component depends on. Don’t let the terse PEAR documentation put you off; it’s quite an easy file to work with, and the error-prone bits get auto-generated for you by the build.xml file when the time comes.

  • src/ folder

    Here’s where your source code goes. There’s a subfolder under here for each of the different types of file that your component might contain. Don’t worry about that too much for now; we’ll explain what goes where as we build these components up.

Why A Skeleton Helps

Our skeleton takes care of all of the chores and housekeeping for you, leaving you free to focus on writing your code and your tests. It gives you a standard structure to work within, making it very easy to move from one component to the next, or share development duties with a wider (and possibly remote) team.

This structure has been carefully designed to work with the somewhat fickle PEAR installer’s preconceptions, and also to work well with both PHPUnit and Netbeans. It should work well with Eclipse/PDT too; let me know how you get on. And old skool vim users shouldn’t have any troubles either 🙂

As the skeleton improves (pull requests are very welcome!), you can use the very handy phix php-library:upgrade command to get the improvements dropped right into your components. Another bonus feature of adopting a standardised skeleton instead of rolling everything by hand.

In the next blog post, we’ll get build.properties and package.xml setup, and get the vendor/ folder created. What’s the vendor folder? I’ll tell you next time 🙂

Be the first to leave a comment »

This Month

March 2011
M T W T F S S
« Feb   Apr »
 123456
78910111213
14151617181920
21222324252627
28293031