I was recently working with someone who was using Zend Framework in their project. To keep things stable and releasable, he was doing an export of framework into his repository and checking it in. Since files change so much in the ZF project currently, instead of doing an rsync from a checkout into his own repository, he decided instead to delete the directory from the repository and re-add it everytime he was updating framework.
This seemed really inefficient to me, especially considering that it made it incredibly difficult to merge changes from his development branch into his production branch (deleting and re-adding directories breaks the merge process considerably). I knew there had to be a better way.
I'd heard of the svn:externals property before, but never really played with it. As it turns out, it exists for just this very type of situation. The problem is that the documentation of svn:externals in the SVN book doesn't indicate at all how the property should be set, and most howto's I've read omit one or more very important details. I finally figured things out through some trial and error of my own, so I'm going to share the process so others hopefully can learn from the experience as well.
It's actually pretty easy. This assumes that your project layout looks something like this:
project/ branch/ production/ tag/ trunk/
svn propedit svn:externals .
framework -r2616 http://framework.zend.com/svn/framework/trunk
One thing to note: any directory you specify for an svn:externals checkout should not already exist in your repository. If it does, you will get an error like the following:
svn: Working copy 'sharedproject' locked svn: run 'svn cleanup' to remove locks
I show using revisions above; you could also pin to tags by simply checkout the external repository from a given tag. Either way works well.
Then, when moving from one branch to another, or from the trunk to a branch, you simply set a different svn:externals for each branch. For instance, your current production might check from one particular revision, but your trunk might simply track head; you then simply determine what the current revision being used is on your trunk, and update svn:externals in your production branch when you're ready to push changes in.
Hope this helps some of you out there!
I've been playing with PHPUnit a lot of late, particularly with framework development. One thing that's always hard to determine is how well your code is exercised -- basically, how much of the code is tested in the unit tests?
In PHPUnit 3, you can now generate code coverage reports using XDebug, and the usage is very simple:
matthew@localhost:~/dev/zend/framework-svn/tests$ phpunit --report ~/tmp/report AllTests
The above command creates a coverage report directory 'report' under my tmp directory. You can then browse through the reports in a web browser and visually see which lines of code were executed during tests, and which were not, as well as a synopsis showing the percentage of coverage for any given file or directory -- useful stuff indeed!
So, what's the problem? Getting XDebug running.
The executive summary:
$ /path/to/phpize $ ./configure --with-php-config=/path/to/php-config $ make $ make install
For the detailed narrative, read on.
Several months ago, Andi asked me to take the role of lead developer on a refactoring of the Zend Framework MVC components. I agreed, though somewhat reluctantly; I already maintain another MVC library, and wasn't sure how well I could fill the shoes of people like my friends Mike, who had done the initial development on the controller classes, and Paul, who provided Zend_View.
The experience has been incredibly rewarding, however, and I've had the chance to pick the brains of and work with some top-notch developers in the process. In the next week or so, we'll be releasing version 0.6.0 of the framework, and it will include much of my work in the MVC components as part of the core distribution. A big thanks to all those who have contributed opinions, design help, code, tests, and documentation; another thank you goes to Andi for trusting and supporting me in this endeavor.
So, what are the changes? Read on to find out...
Yesterday, Mike and I presented our session "Best Practices of PHP Development" at this year's Zend Conference. It was a marathon three hour tutorial first thing in the morning, and we had an incredible turnout, with some fairly enthusiastic people in the audience.
As Mike already noted, he and I are presenting a session on "Best Practices of PHP Development" at this year's Zend Conference and Expo. It has been my fortunate experience to work with Mike in the past, and, as he noted, we had so much fun presenting during last year's conference, we thought we'd do it again.
The session is a pre-conference tutorial session, running for 3 hours on Monday morning, 30 October 2006. Currently, we're shaping up the session into the following subject areas:
Emphasis is going to be on working in teams, particularly those operating in geographically diverse areas. With roughly 30 minute blocks per topic, we've certainly got plenty to cover!
If you're coming to the conference, we look forward to seeing you in our session!
As noted previously by myself and Davey, I've been working on Zend_XmlRpc_Server for some months now. In the past couple weeks, I've refactored it to push the class/function reflection into Zend_Server_Reflection, and, in doing so, noted that there were further areas for refactoring into additional helper classes. Currently, it now has classes for the Request, Response, and Faults, and all actual XML wrangling is done in those, making the server basically XML-agnostic.
As Davey Shafik noted recently, he and I have been working together on some web services for the Zend Framework. In doing so, I've become very familiar with PHP 5's Reflection API, and am coming to love it.
When I first read about the Reflection API in a pre-PHP 5 changelog, my initial reaction was, "who cares?" I simply failed to see how it was a useful addition to the language. Having done some projects recently that needed to know something about the classes they are using, I now understand when and how it can be used. It shines when you need to work with classes that may not be defined when you write your code -- any code that dispatches to other classes, basically.
I may work at Zend, but I've never been a fan of IDEs. They simply don't suit my programming style. I can usually keep track of file locations in my head pretty easily, and what I really need is a blank slate on which I can write, and one that doesn't consume resource that can better be used running web servers and other programs. Syntax highlighting, good indentation -- these are important, but you can get these from good, minimal text editors very easily. Vim is my editor of choice.
I will admit, though, that one area where I have had IDE-envy is the area of code completion. I often find myself doing quick lookups to php.net or perldoc to determine the order of arguments to a function or method call, or checking for the expected return value. Most of the time, this doesn't take much time, however, so I just live with it.
Today, however, cruising through the blogosphere, I came across an article showcasing some new features of Vim 7.0, and discovered Vim 7's code completion.
Basically, while in insert mode, you can type <C-x> <C-o> to have vim attempt to autocomplete the current keyword. If more than one possibility exists, it shows a dropdown, and you can use your arrow keys to highlight the keyword that you wish to use.
But it gets better! Not only does it do this kind of autocompletion, but it also opens a small 'scratch preview' pane showing the function/method signature -- i.e., the expected arguments and return value!
I thought I had little need for IDEs before... now I have even less! Bram and the rest of the Vim team, my hat's off to you for more fine work!
In response to Scott Johnson's request for advice on variable functions, I decided to run some benchmarks.
<rant>Writing benchmarks is easy. Yet I see a lot of blog entries and mailing list postings asking, "Which is faster?" My first thought is always, "Why didn't they test and find out?" If I ever have a question about how something will work, I open up a temporary file, start coding, and run the code. It's the easiest way to learn. Also, it teaches you to break things into manageable, testable chunks, and this code often forms the basis for a unit test later.</rant>
Back to benchmarking. Scott asks, "Is there a real difference between call_user_func versus call_user_func_array and the variable function syntax i.e. $function_name()?"
The short answer: absolutely. The long answer? Read on.
I upgraded Serendipity today, due to the recent announcement of the 1.0 release, as well as to combat some rampant issues with trackback spam.
I've been very happy with Serendipity so far; it just runs, and the default install gives just what you need to get a blog up and running, and nothing more; any extra functionality comes via plugins which you, the blogger, get to decide upon.
Additionally, it's incredibly easy to upgrade. Unpack the tarball, rsync it over your existing install (I rsync it, because I don't use 'serendipity' as my directory name), visit the admin, boom, you're done. I've upgraded several times, and never lost data, nor configuration settings.
My primary reason for the upgrade was, as noted earlier, to combat trackback spam. As of this morning, I had 15,000 pending trackbacks, none of which appeared to be valid (if any of them were, and you're not seeing yours, I'm very sorry; I deleted them en masse). These had accumulated in less than a month -- that's an average of about one every 3 minutes.
Since upgrading, and using the Akismet service, I've received not a single spam trackback. Needless to say, I'm happy I performed the upgrade!
If you're a Serendipity user, and haven't upgraded to 1.0.0 yet (or one of it's reportedly very stable release candidates), do it today -- you have nothing to lose, and a lot of lost time to gain!