If you have a library of code you want to convert to PHP 5.3 namespaces and it follows the Zend class naming standard, this tool will do the grunt work for you. Clone the repo using git or just grab the archive and start playing with it.
The fun version
RALPH! That’s how these conversations usually start. I can feel Ralph cringe over IM every time I do that too. (And I can see Matthew smiling reading this because it used to be MATTHEW!) Ralph Schindler is one of 2 full-time Zend employees whose job it is to work on the Zend Framework. (Yeah, awesome job if you can get it!) Ralph works on a lost of stuff but my favorite is Zend_Tool. Every time Ralph releases a new version of Zend_Tool, he and I end up having an extended debugging session making sure that my zf twitter client still works.
The other day however Ralph released something new. He announced that he had written a tool to take a library using the Zend (and PEAR?) standard for class naming – My_Class_Name is actually My\Class\Name.php – and convert them to PHP 5.3 namespaces.
It’s actually a pretty cool little tool, especially if you have a large library you want to convert.
I ran it on a part of the Zend Framwork, Zend_Acl, and it worked correctly, well after I sent up the Ralph signal and he fixed the issue with it running on Windows. (This is exactly what I love about working in the PHP community. If something doesn’t work, or you don’t understand something there are hundreds of people out there that will help you. If all else fails, you can grab he code, dig in and figure out what is going wrong. If Microsoft ever figures this secret out, open source could be in real trouble!) :)
Testing the tool
The command I used to test was this:
D:\tmp\PHPTools\bin>php php-namespacer.php -l=d:\tmp\Zend -o=d:\tmp\newlib -m=d:\tmp\newlib
Here are the steps I took to setup and test.
- To keep from accidentally screwing up my copy of ZF, I copied just the Zend\ACL and Zend\Acl.php into it’s own directory,
- I stripped out all the .svn directories from my test copy before running. This is no longer necessary as Ralph has set it up to ignore them now.
- I ran the command shown above. It created the
d:\tmp\newlibdirectory for me since it didn’t actually exist.
The only option I didn’t use was the
-p option. If you have a large library and only want to convert a section or sections of it, you can specify them with the
-p option. In my test case above, if I had used the entire Zend Framework, I could have used -p=Acl to limit it to just the Acl. As an aside, even though you specify a single area to work, it does seem to scan the entire Zend Framework. I'm not sure if this is an oversight or on purpose.
The first things I noticed was that it moved Acl.php into the Acl directory for me. Opening the new Acl.php, I saw that it had not only added the namespace for me but had also added the phpdocblock also.
/** * @namespace */ namespace Acl;
So far so good. The only other file in the Acl directory now was the Exception as the other classes that had matching directories has also been moved into their respective directories. The Exception had the same namespace and docblock.
Digging a little deeper, I opened up
/** * @namespace */ namespace Acl\Role;
Ok, this was interesting. each sub-directory becomes a sub-namespace. I'll be honest and admit that I've not done a lot of thinking on this so I can't say this is a good or bad thing. I can say that I expected all the files to remain in the same namespace. As I said, I don't know if it's good or bad, I do know that this is by design though.
Nothing is completed without an ugly XML file
The final thing the tool will do is write out an XML mapping file for you. This monster is always named
PHPNamespacer-MappedClasses.xml and you have the option (
-m) of deciding where the file is put. If you don't specify a location the mapper file is not output. This is a sample of what is in the file.
<MappedClasses libraryPath="D:\tmp"> <MappedClass> <originalRelativeFilePath>Zend\Acl\Assert\Interface.php</originalRelativeFilePath> <originalClassName>Zend_Acl_Assert_Interface</originalClassName> <newRelativeFilePath>Zend/Acl/Assert/AssertInterface.php</newRelativeFilePath> <newNamespace>Zend\Acl\Assert</newNamespace> <newClassName>AssertInterface</newClassName> <newFullyQualifiedName>Zend\Acl\Assert\AssertInterface</newFullyQualifiedName> </MappedClass>
I know as Ralph refines the tool he will elaborate on the XML and what the mapping is designed to be used for. For now, it's just enough to know that if you like the way it generates sub-namespaces, you can safely leave off the
-m option and not generate the XML.
All the help you get
Beyon Ralph's original post (linked above) and this blog, the only other help you get is to call the script with the
-h flag. Doing so will output the following:
This tool is intended to be used to namespace previously prefixed library code developed with a PEAR/ZF coding standard in place. It will attempt to find all class names and convert them to namespaces. Furthermore, it will attempt to find any references to those classes in method signatures, and body code, and docblocks and convert those to known translations. Usage: (Option should be passed in a form that php's getopt() can parse.) php path/to/Namespace/Namespacer.php [options] Options: -h, --help This help screen. -l, --lib, --library-directory The library directory to iterate, this would be the same directory you would anticipate registered as an include_path. -d, --dir, --directory-filter The part of the library directory you want to operate on. -o, --out, --output-path If supplied, this directory will be where converted files are written to. -p, --prefix, --prefixes The base prefix to mind when converting. Can be comma separated list. -m, --map, --map-path The directory where an xml file will be produced that will list the file and class translations that were used. Notes: * library and directory are separate entities b/c library will be first scanned to identify all names in general usage. Directory will be used to filter out the relative path that is to be considered the working set of file that the converter should convert.
This is a good first effort and I want to thank both Zend and Ralph for this contribution. As it's stored in GitHub and I am ASSUMING it is released under an OS licenses (it's not actually in the code so I can't be sure) you can go grab it, fork it and start helping to make it better. Ralph hasn't stated whether he will accept patches or not but I can't help but think that he would appreciate any help he can get. :)
Until next time,
I <3 |<