PHP


25
Mar 12

Why I moved on from PHP

Alex Hudson has written a good piece on Zend Framework 2, and why he’s moving on from Zend Framework. I was an active contributor to Zend Framework from 2006 until 2008, and I moved on also.  In fact, I mostly moved on from PHP altogether, in large part directly because of Zend Framework.

I’d like to say it was because of the Java influence which is on its face largely at odds with the language it’s built on—but really, it was because I was tired of PHP and its ecosystem. I was tired of the weak typing (not dynamic typing), inconsistent function names, anything-goes argument orders, the generally poor quality of libraries and open source projects, the community values that led to both, the resulting difficulty in hiring good developers from that community… well, I could go on.

There were counterpoints to most of these arguments, and I made them to others. But eventually the weight of the problems added up, and I wanted options. Zend Framework seemed to be trying to turn PHP into Java, and although I hadn’t yet made a value judgment about Java I knew that wasn’t appropriate for PHP. It’s essentially a glue language like Perl, and the “PHP way” (such as it exists) is about lightweight, quickly-bootstrapped solutions. Otherwise, what is PHP good for?

At best, most developers see PHP as a hammer—not particularly fast or elegant, but it gets the job done.

Zend Framework highlighted these problems for me.  It served as a stark contrast to the quality of other PHP components, but exemplified the schizophrenic direction of PHP as a whole since 5.0 (PHP’s SPL—its Standard PHP Library—is every bit as Java-like as Zend Framework).

I glanced at Symfony and some other projects, but what I really wanted was something that addressed my complaints: strongly-typed, consistent, good libraries and community, etc. Professionally I began writing Java, both with and without frameworks like Spring and GWT. At home I began writing a lot of Ruby, using the MacRuby project to supplement some Cocoa I had already learned using Objective-C. I also played with Rails 2 and Merb.

The Java started off well enough—I was creating the same types of complex multi-tier applications that I did under PHP, but this time backed by static typing and a huge library of components from Spring and Apache. But even after I was up to speed, development was slower. I had always heard how Java was heavy, but now I truly experienced it: Spring, a “lightweight” alternative to Struts, had so much explicit (and, to my mind, pointless) infrastructure setup that I was thoroughly disillusioned with it within six months.

I had already blogged about why I thought writing JavaScript by proxy was a bad idea, but I was questioning all my assumptions and so I decided to explore GWT as well. In the end, my experience was similar to Spring—it was all too slow. In the case of GWT I felt both too far removed from the end result and occasionally too near (when I needed to jump into writing native JavaScript using JSNI). This leaky abstraction was explained as a fundamental design decision, but never sat quite right with me. I knew it was necessary, and that was the problem.

At the same time, I experienced none of these problems with Ruby. During this time of exploration I wrote a variety of things: a parser library for a non-trivial binary file format, some GUI components using MacRuby, a website in Rails 2, and an API in Sinatra. I started looking into Merb, but learned it was merging with Rails and so started becoming familiar with Rails 3 instead.

Contrary to my experience in both PHP and Java, I loved every moment writing Ruby. Like Python, it is both strongly- and dynamically-typed. I found the libraries to be generally high-quality, and when they weren’t, the authors tended to be up-front about that fact. The community, inspired by the Rails philosophy, was constantly pushing the envelope by embracing the latest and greatest, almost to a fault. It had a good community that valued pragmatic solutions.

It’s four years later now and I still love Ruby. It’s not the best solution for everything, so I’ve continued to learn new languages (my latest being Python), but it’s generally my first choice.

I still occasionally write some PHP at work. There’s a lot of sighing involved. Zend Framework has some good components and when appropriate I recommend it as a library. I wish it were more modular.

I wouldn’t recommend the MVC—it’s slow, and it places things in the way of routing that should probably go elsewhere. Zend Framework architect Matthew Weier O’Phinney is a smart guy, but he’s trying to drag the PHP community almost single-handedly toward the PHP-as-Java point of view. Frankly, I don’t think it’s right for the community and I don’t think the community is that interested. I predict Zend Framework 2.0 adoption will be glacial. Most people probably won’t ever bother making the switch.

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

23
Oct 10

You’re doing it wrong

The following appeared on a mailing list I subscribe to.

Hi,

I have 3000 definitions in my config.ini .

routes.cates1.route = “list1/:page”
routes.cates1.defaults.module = “default”
routes.cates1.defaults.controller = “list”
routes.cates1.defaults.action = “index”
routes.cates1.defaults.id = 1
routes.cates1.defaults.page = 1
routes.cates1.reqs.page = “d+”

….
….

routes.cates3000.route = “list3000/:page”
routes.cates3000.defaults.module = “default”
routes.cates3000.defaults.controller = “list”
routes.cates3000.defaults.action = “index”
routes.cates3000.defaults.id = 3000
routes.cates3000.defaults.page = 3000
routes.cates3000.reqs.page = “d+”

I think my web site (it isn´t production) is slower than before. This is Okay or I need other solution.

bye

George

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

7
Nov 08

Zend_Search_Lucene: Not enterprise-ready

Zend Framework has been attracting more and more attention from the PHP community lately, and while it lacks certain things (like code generation) that other frameworks (like Rails) have implemented to great effect, Zend Framework 2.0 is slowly taking shape and it looks like it will be the framework of choice for startups and enterprises alike. (Yes, it will even have code generation.)

But despite having several “enterprise-ready” components, I’ve found that one in particular is not: Zend_Search_Lucene, Zend Framework’s native PHP implementation of Apache Lucene, written in Java.

Don’t get me wrong; Zend_Search_Lucene is great for a small site or blog. However, from extensive personal experience, it is not appropriate for a site with a medium or large index. I think this should be noted upfront in the documentation.

Against my better judgment, the company I work for migrated our previous search solution to Zend_Search_Lucene. On pretty heavy-duty hardware, indexing a million documents took several hours, and searches were relatively slow. The indexing process consumed vast amounts of memory, and the indexes frequently became corrupted (using 1.5.2). A single wild card search literally brought the web server to its knees, so we disabled that feature. Memory usage was very high for searches, and as a result requests per second necessarily declined heavily as we had to reduce the number of Apache child processes.

We have since moved to Solr (a Lucene-based Java search server) and the difference is dramatic. Indexing now takes around 10 minutes and searches are lightning fast. What a difference a language makes.

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

26
Sep 08

PHP gets lambda methods, closures

Not one month after I wrote about the future of PHP (June 2008), I was quite happily proven wrong.

For my part, I’d like to see first-class functions and closures included in the language. [...]

But none of that will happen, because PHP is a language in decline. Not a decline in usage—it will only continue to expand its reach—but in the addition of innovative features from other languages. There will be no need to evolve; most of the agitators for change will have moved on.
Me

It’s always been in my nature to own up to it when I’m proven wrong, so consider this my mea culpa. PHP has always been a klugey language, borrowing from other languages and implementing those ideas in somewhat endearingly clunky ways. I naively believed that that dynamism was coming to an end, but as you can see from the link above, that’s demonstrably not the case. Despite that, I still think there is a slow but steady “brain drain” from the ranks of the top tier of PHP developers—I’ve seen it first hand in the last few years and the overall trend should make PHP developers at least a little uncomfortable.

Anyway, the closure implementation coming in PHP 5.3 is, like namespaces, a little clunky.

function replace_in_array($search, $replacement, $array) {
    $map = function ($text) use ($search, $replacement) {
        if (strpos($text, $search) > 50) {
            return str_replace($search, $replacement, $text);
        }
        return $text;
    };
    return array_map($map, $array);
}

Yeah, you have to manually link the variables to make them available to the closure. Not ideal, but neither is having to manually specify your scope in JavaScript (via Function.apply()).

There are a few of other differences in PHP 5.3′s implementation of closures and other languages:

  • First, like other functions, they have access to the global scope with the global keyword. Do yourself a great big favor and just avoid doing that.
  • Second, you can choose which variables are linked by reference and which are not.
  • Finally, you can declare an anonymous function static if it’s declared in a class but doesn’t use an instance of that class for anything. If you have a large object, this would prevent the closure from retaining a reference to that instance (and therefore, its memory footprint) after it has outlived its usefulness. This will probably be the least understood aspect of PHP closures for most developers.

Currying is now possible as well. Ryan Timmons wasted no time in writing a method for doing just that:

function curry($function, $argument) {
    return function() use ($function, $argument) {
        $arguments = func_get_args();
        array_unshift($arguments, $argument);
        return call_user_func_array($function, $arguments);
    };
}

Between this, namespaces, late static binding, and a bundled packaging method (ext/phar), the next version of PHP is looking more like a major release instead of a minor one.

PHP 5.3 is scheduled for final release in October [update: it's been pushed back to the end of Q1 2009].

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!

3
Sep 08

Zend_Paginator

On and off for the last two or three months, Jurriën Stutterheim and I wrote Zend_Paginator, the pagination component for Zend Framework. Yesterday it was officially released as part of Zend Framework 1.6.

This was our first contribution to the framework, and was very much a collaborative working relationship. I first created a proposal in about half an hour on Christmas Eve 2007 for how I thought a pagination component should work after being dissatisfied with existing solutions. It contained some good ideas about flexibility, but on its own it was half an idea, at best. So I promptly forgot about it.

Then Jurriën came along and created a proposal based on his Zym_Paginate component, which was part of Zym Framework, itself an extension of Zend Framework.

At the urging of Zend, we merged our proposals. We refined our ideas, incorporating aspects from each of our proposals in addition to brand new thoughts. Then I wrote a new component from scratch based in part on Jurriën’s existing work. He wrote the excellent unit tests (with 100% code coverage, not always easy to achieve!), and I wrote the DocBook documentation. I also can’t overstate the positive impact the community had, particularly from Bryce Lohr who prompted us to decouple and reorganize major portions of the component.

Anyway, I’m very happy with how it turned out. There are still a few issues, most of them minor—and because of the component’s flexible design, there are almost always workarounds. They should be fixed in time for 1.6.1.

Here’s some praise for the component:

Upcoming Zend_Paginator in 1.6 is absolutely brilliant. Wasted time be gone.
Joakim Nygård

The new Zend Framework 1.6 release candidate includes a Zend_Paginator class, which is an excellent thing to have around because I know I’ve re-invented that wheel on every site I’ve developed. My only criticism of the new Zend_Paginator is it offers a daunting amount of possibilities.
Chris Beer

This really is a beautifully crafted component, very elegant, very classy.
—David Mintz, via e-mail

I’ve seen dozens of different paginators in the last couple of years, and to be honest, this one is by far the best. You got everything right! I can’t wait for this component to hit the incubator.

It’s great, well done guys.
Federico Cargnelutti

Like this post? You might also like Coalmine, my centralized error tracking service for your apps. Coalmine captures errors and all kinds of helpful debugging information, notifies you, and makes it all searchable. Check it out!