Search results
From the blog
Posted 2024-08-27
Configuring PHP.INI settings in a PHP-FPM pool
I consume PHP via Docker primarily, and to keep it manageable, I generally use a PHP-FPM container, with a web server sitting in front of it. I learned something new about PHP configuration recently that (a) made my day, and (b) kept me humble, as I should have known this all along.
From the blog
Posted 2024-05-07
Initializing ZendHQ JobQueue During Application Deployment
In the past few years, I've transitioned from engineering into product management at Zend, and it's been a hugely rewarding experience to be able to toss ideas over the fence to my own engineering team, and have them do all the fiddly tricky bits of actually implementing them!
Besides packaging long-term support versions of PHP, we also are publishing a product called ZendHQ. This is a combination of a PHP extension, and an independent service that PHP instances communicate with to do things like monitoring and queue management.
It's this latter I want to talk about a bit here, as (a) I think it's a really excellent tool, and (b) in using it, I've found some interesting patterns for prepping it during deployment.
From the blog
Posted 2023-12-14
Advent 2023: PSR-15
I've mentioned a few times over the course of this 2023 Advent series that the longer I'm in the tech field, the more I appreciate and favor simple solutions. I was reminded of this yesterday when I read this article on return types in Laravel controllers by Joel Clermont.
From the blog
Posted 2023-12-10
Advent 2023: Doctrine DBAL
I've mostly taken database abstraction for granted since I started at Zend. We had a decent abstraction layer in ZF1, and improved it for ZF2. There were a lot quirks to it — you really had to dive in and look at the various SQL abstraction classes to understand how to do more complex stuff — but it worked, and was always right there and available in the projects I worked on.
In the last couple of years, though, we came to the realization in the Laminas Project that we didn't really have anybody with the expertise or time to maintain it. We've marked it security-only twice now, and while we've managed to keep it updated to each new PHP version, it's becoming harder and harder, and whenever there's a CI issue, it's anybody's guess as to whether or not we'll be able to get it resolved.
My alternatives have been straight PDO, or Doctrine DBAL, with the latter being my preference.
From the blog
Posted 2023-12-09
Advent 2023: Forms
The first thing I was tasked with after I moved full time to the Zend Framework team (17 years ago! Yikes!) was to create a forms library. Like all the work I did for ZF in the early days, I first created a working group, gathered requirements, and prioritized features. There were a lot of requests:
- Ability to normalize values
- Ability to validate values
- Ability to get validation error messages
- Ability to render HTML forms, and have customizable markup
- Ability to do nested values
- Ability to handle optional values
- Ability to report missing values
and quite a lot more. But those are some of the things that stuck out that I can remember off the top of my head.
Zend_Form was considered a big enough new feature that we actually bumped the version from 1.0 to 1.5 to call it out.
And, honestly, in hindsight, it was a mistake.
From the blog
Posted 2022-11-28
Goodbye Twitter
This is a long, personal post.
tl;dr: I'm leaving Twitter. You can find me in the Fediverse as @matthew@mwop.net.
From the blog
Posted 2022-04-26
TailwindCSS Tips
I've been dabbling in CSS my entire career. In the early days, it was relatively simple, as our browsers were fairly limited. But over the years, CSS has become more and more capable, allowing styles to target only tags with specific tag attributes, only apply at specific screen sizes, and even perform complex layouts using things like flexbox and grid. I take a bit of time every now and then to understand these things... but since I don't use CSS a ton, it's hard to keep up.
As such, over the past decade, I've tended to use CSS frameworks, and generally Bootstrap. Every couple years, a new major version is dropped, and I have to learn new structures and components, and struggle to get things to look the way I want. Worse, when I use these frameworks, injecting custom CSS often means understanding how the framework is already styling components so I can ensure things don't conflict.
The last couple years, I've been keeping an eye on TailwindCSS. I've been a bit skeptical, as its declarative, utility-first approach looks a lot like doing CSS inside your HTML, which, honestly, feels off. I've typically subscribed to the idea of semantic HTML, which advocates separating style from markup. Having styles directly that mimic CSS directives associated with every tag feels like an unholy mix, and a far cry from semantic HTML.
And then there's the hype. The original author and project lead of Tailwind is a huge hype man, and hype tends to turn me off. That's on me, not them, but having been in the business for over two decades, I'm finding I'm more and more likely to discount hyped products and projects, because I've seen them come and go so frequently; there's often an indirect relationship between the amount of hype and the long-term viability of a project. I've also often observed that hype serves as a way for users to deflect reasonable critique, and the more vehement the user base, the less interested I am in engaging with them because of this. Clearly, YMMV, but it was definitely something keeping me from really investigating Tailwind.
However, recently, in helping out the PHP Foundation, I volunteered to setup their static website, and the team requested using TailwindCSS, so I dove in.
And I discovered... I kind of love it.
This is one of those "I'll be googling this in the future" posts.
From the blog
Posted 2022-02-23
Getting OpenSwoole and the AWS SDK to Play Nice
I have some content that I store in S3-compatible object storage, and wanted to be able to (a) push to that storage, and (b) serve items from that storage.
Easey-peasey: use the Flysystem AWS S3 adapter, point it to my storage, and be done!
Except for one monkey wrench: I'm using OpenSwoole.
From the blog
Posted 2022-01-25
Exposing webhooks via mezzio-swoole
I was first introduced to the concept of webhooks via a 2009 blog post by John Herren, a former colleague at Zend. At the time, they were in their infancy; today, they're ubiquituous, as they provide a mechanism for a service to notify interested parties of events. This saves traffic; instead of consumers polling an API for event changes, the service notifies them directly. It also means that the consumer does not need to setup things like cronjobs; they instead setup a webhook endpoint, register it with the service provider, and their application takes care of the rest.
The thing is, handling a webhook can often lead to additional processing, and you are expected to send an immediate response to the provider indicating you received the event.
How can you achieve this?
From the blog
Posted 2022-01-21
Running cronjobs via an Openswoole timer
Sites I build often utilize cronjobs to periodically pull in data from other sources. For example, I might want to poll an API once a day, or scrape content from another website once a month. Cronjobs are a perfect fit for this.
However, cron has a few problems:
- If the job is writing information into the file tree of your web application, you need to ensure permissions are correct, both at the filesystem level, and when writing the cronjob (e.g., running it as the same user, or changing permissions on completion).
- If you are running console tooling associated with your PHP application, you may need to worry about whether or not particular environment variables are in scope when you run the job.
- In containerized environments, usage of cron is strongly discouraged, as it means running another daemon. You can get around this with tools such as the s6-overlay, but it's another vector for issues.
Since most sites I build anymore use mezzio-swoole, I started wondering if I might be able to handle these jobs another way.
From the blog
Posted 2021-12-06
Caddy as a Secure Reverse Proxy
I've been using Caddy as a front-end reverse proxy for several years now, on the advice of Marco Pivetta. Somewhere along the line version 2 was released, and I updated at some point, but evidently didn't quite understand some of its configuration options, particularly around HSTS support and providing your proxied application information about how the client tried to connect.
From the blog
Posted 2021-03-31
Tinker-like REPL for Mezzio
Today in the Laminas Slack, somebody asked if there was an equivalent to Laravel's Tinker REPL. The short answer is "no", but I had a suggestion for them.
From the blog
Posted 2021-03-12
Laminas CI Automation
The Laminas Project has close to 200 repositories between the main project, Laminas API Tools, and Mezzio. It's a lot to maintain, and keeping on top of incoming patches can be a gargantuan task, much less creating releases.
That's why this past year, we've spent a bunch of time on streamlining our processes; we want to be able to review, merge, and release changes quickly and confidently. To that end, we have developed a number of GitHub Actions to make these processes as easy as possible for our maintainers.
From the blog
Posted 2020-12-04
Development-Mode Modules for Mezzio
I fielded a question in the Laminas Slack yesterday that I realized should likely be a blog post. The question was:
Is there a way to register development-mode-only modules in Mezzio?
There's actually multiple ways to do it, though one that is probably more preferable to others.
From the blog
Posted 2019-12-05
More Changes Coming for the Laminas Project
Progress has been happening at a furious pace on the Zend Framework to Laminas transition, with major changes still dropping even now.
Most recently, we decided to rename the subprojects. Apigility will become the Laminas API Tools, and Expressive will become Mezzio.
For more background, read the Zend by Perforce blog post.
From the blog
Posted 2019-10-17
An Apology to php[world] Attendees
Due to disorganization on my part, I accidentally booked php[world] 2019 to coincide with a family commitment.
From the blog
Posted 2019-09-03
Looking For A New Adventure
Update
As of 2019-10-01, I am once again employed full-time. Thank you everyone who reached out!
Fourteen years ago, almost to the day, I received a job offer from Zend to join their nascent eBiz team, where I started contributing almost immediately to the yet-to-be-announced Zend Framework. Two years later, I joined the Zend Framework team full-time. A year later, I was promoted to Architect. A year after that, I was promoted to Project Lead of Zend Framework, a role I kept for the next ten years. Over the years, Zend was acquired by RogueWave Software, which was in turn acquired by Perforce earlier this year.
Two months ago, almost to the day, was my last day with Zend/RogueWave/Perforce.
I'm now looking for a new adventure.
From the blog
Posted 2019-04-30
Managing Multiple PHP versions via the ondrej/php PPA
Last week, I did some system updates, and then decided to compile the most recent PHP releases. I've used phpbrew to manage multiple PHP releases for a number of years, and having it install a new version is fairly routine.
Except this time, it wasn't. Due to updates I installed, I was getting errors first with compiling the GD extension, then with ext-intl:
-
If you want Freetype support in ext-gd, you are expected to install the package libfreetype-dev. On Ubuntu, this now installs libfreetype6-dev, which no longer includes the
freetype-config
binary that PHP'sconfigure
script uses to determine what features it supports. -
Similarly, ext-intl depends on the package libicu-dev. Ubuntu's package now omits the
icu-config
binary used by PHP to determine feature support.
I searched for quite some time to find packages that would resolve these problems. I could have found the source code and compiled it and linked to that, but that would mean keeping that up-to-date on top of my PHP installs.
I even looked in the ondrej/php PPA, as that repository has multiple PHP versions already, including source packages.
And then I thought: why not try using those instead of phpbrew?
The rest of this post is how I made that work.
From the blog
Posted 2019-04-17
From Zend Framework To The Laminas Project
Ten years ago this month, I was involved in a couple of huge changes for Zend Framework.
First, I helped spearhead integration of the JavaScript library Dojo Toolkit into Zend Framework, and finalized the work that month. I'd worked closely with the two developers who had been leading that project at the time, and one thing that came up during our discussions was that they had helped create an open source foundation for the project, to ensure its continuity and longevity, and to ensure the project can outlive the ups and downs of any commercial company. This idea intrigued me, and has stuck in the back of my mind ever since.
The other thing that happened that month was that I was promoted to Project Lead of Zend Framework. I've held that position ever since.
Today, I get to announce another change: Zend Framework is transitioning to an open source project under the Linux Foundation!
From the blog
Posted 2019-01-24
Registering Module-Specific Routes in Expressive
In Expressive, we have standardized on a file named
config/routes.php
to contain all your route registrations. A typical file
might look something like this:
declare(strict_types=1);
use Zend\Expressive\Csrf\CsrfMiddleware;
use Zend\Expressive\Session\SessionMiddleware;
return function (
\Zend\Expressive\Application $app,
\Zend\Expressive\MiddlewareFactory $factory,
\Psr\Container\ContainerInterface $container
) : void {
$app->get('/', App\HomePageHandler::class, 'home');
$app->get('/contact', [
SessionMiddleware::class,
CsrfMiddleware::class,
App\Contact\ContactPageHandler::class
], 'contact');
$app->post('/contact', [
SessionMiddleware::class,
CsrfMiddleware::class,
App\Contact\ProcessContactRequestHandler::class
]);
$app->get(
'/contact/thank-you',
App\Contact\ThankYouHandler::class,
'contact.done'
);
$app->get(
'/blog[/]',
App\Blog\Handler\LandingPageHandler::class,
'blog'
);
$app->get('/blog/{id:[^/]+\.html', [
SessionMiddleware::class,
CsrfMiddleware::class,
App\Blog\Handler\BlogPostHandler::class,
], 'blog.post');
$app->post('/blog/comment/{id:[^/]+\.html', [
SessionMiddleware::class,
CsrfMiddleware::class,
App\Blog\Handler\ProcessBlogCommentHandler::class,
], 'blog.comment');
}
and so on.
These files can get really long, and organizing them becomes imperative.
From the blog
Posted 2018-12-05
Creating Exception types on-the-fly in modern PHP
We pioneered a pattern for exception handling for Zend Framework back as we initially began development on version 2 around seven years ago. The pattern looks like this:
- We would create a marker
ExceptionInterface
for each package. - We would extend SPL exceptions and implement the package marker interface when doing so.
What this gave users was the ability to catch in three ways:
- They could catch the most specific exception type by class name.
- They could catch all package-level exceptions using the marker interface.
- The could catch general exceptions using the associated SPL type.
From the blog
Posted 2018-11-04
Fixing Redis background-save issues on Docker
I've been running redis in Docker for a number of sites, to perform things such as storing session data, hubot settings, and more.
I recently ran into a problem on one of my systems where it was reporting:
Can't save in background: fork: Out of memory
From the blog
Posted 2018-11-01
Building a usable ext-tidy for Alpine-based PHP Docker images
I've been working on building PHP Docker images for the purposes of testing, as well as to potentially provide images containing the Swoole extension. This is generally straight-forward, as the official PHP images are well-documented.
This week, I decided to see if I could build Alpine-based images, as they can greatly reduce the final image size. And I ran into a problem.
From the blog
Posted 2018-10-17
The Future of Zend Framework
For the past thirteen years, I've been either consuming Zend Framework or directly contributing to it. Since 2009, I've operated as project lead, and, since then, shepherded the version 2 and 3 releases, added Apigility to the ZF ecosystem, and helped bring middleware paradigms to the mainstream by assisting with the creation of Stratigility and coordination of the Expressive project. As I write this, the various ZF packages have been downloaded over 300 MILLION times, with 200 million of those being in the past 18 months!
From the blog
Posted 2018-10-16
Async Expressive with Swoole
Have you used Node.js?
For those of my readers unfamiliar with Node.js, it's a server-side JavaScript framework that provides the ability to create, among other things, network services. To do so, it provides an event loop, which allows for such things as asynchronous processing.
In the PHP ecosystem, a group of Chinese developers have been creating an extension that provides many of the same capabilities as Node.js. This extension, called Swoole, allows you to create web servers with asynchronous capabilities. In many cases, the asynchronous capabilities are handled via coroutines, allowing you to write normal, synchronous code that still benefits from the asynchronous nature of the system event loop, allowing your server to continue responding to new requests as they come in!
We've been gradually adding and refining our Swoole support in Expressive, and recently issued a stable release that will work with any PSR-15 request handler. In this post, I'll enumerate what I feel are the reasons for considering Swoole when deploying your PHP middleware application.
From the blog
Posted 2018-07-18
Notes on GraphQL
The last week has been my first foray into GraphQL, using the GitHub GraphQL API endpoints. I now have OpinionsTM.
The promise is fantastic: query for everything you need, but nothing more. Get it all in one go.
But the reality is somewhat... different.
From the blog
Posted 2018-01-23
PSR-15
Yesterday, following a unanimous vote from its Core Committee, PHP-FIG formally accepted the proposed PSR-15, HTTP Server Handlers standard.
This new standard defines interfaces for request handlers and middleware. These have enormous potential impact on the PHP ecosystem, as they provide standard mechanisms for writing HTTP-facing, server-side applications. Essentially, they pave the way for developers to create re-usable web components that will work in any application that works with PSR-15 middleware or request handlers!
From the blog
Posted 2017-03-30
Using Anonymous Classes to Write Middleware
I faced an interesting question recently with regards to middleware: What happens when we go from a convention-based to a contract-based approach when programming?
Convention-based approaches usually allow for duck-typing; with middleware, it means you can write PHP callables — usually closures — and just expect them to work.
Contract-based approaches use interfaces. I think you can see where this is going.
From the blog
Posted 2017-01-26
PSR-7 Request and Method Utilities
We all know the standard HTTP request methods and status codes, right? Or do we?
We definitely know whether or not they should be integers or strings, and/or how string values should be normalized, right?
And our IDEs can totally autocomplete them, right?
Oh, that's not the case?
From the blog
Posted 2016-10-24
Automating PHPUnit with Node
I've been trying to automate everything this year. When working on OSS, this is usually as simple as setting up Travis CI; in some cases, even that becomes a little more involved, but remains possible.
But that's continuous integration. What about continuous development?
From the blog
Posted 2016-08-17
Using Composer to Autoload ZF Modules
One aspect of Zend Framework 3, we paid particular focus on was leveraging the Composer ecosystem. We now provide a number of Composer plugins for handling things such as initial project installation, registering installed modules with the application, and more. It's the "more" I particularly want to talk about.
From the blog
Posted 2016-06-30
Push-to-Deploy with AWS CodeDeploy
AWS CodeDeploy is a tool for automating application deployments to EC2 instances and clusters. It can pull application archives from either S3 or GitHub, and then allows you to specify how to install, configure, and run the application via a configuration specification and optionally hook scripts. When setup correctly, it can provide a powerful way to automate your deployments.
I started looking into it because I wanted to try out my site on PHP 7, and do a few new things with nginx that I wasn't doing before. Additionally, I've accidently forgotten to deploy a few times in the past year after writing a blog post, and I wanted to see if I solve that situation; I'd really enjoyed the "push-to-deploy" paradigm of OpenShift and EngineYard in the past, and wanted to see if I could recreate it.
Enrico first pointed me to the service, and I was later inspired by a slide deck by Ric Harvey. The process wasn't easy, due to a number of things that are not documented or not fully documented in the AWS CodeDeploy documentation, but in the end, I was able to accomplish exactly that: push-to-deploy. This post details what I found, some recommendations on how to create your deployments, and ways to avoid some of the pitfalls I fell into.
From the blog
Posted 2016-05-16
Programmatic Expressive
Enrico just returned from phpDay, where he spoke about Expressive and the upcoming Zend Framework 3. One piece of feedback he brought back had to do with how people perceive they should be building Expressive applications: many think, based on our examples, that it's completely configuration driven!
As it turns out, this is far from the truth; we developed our API to mimic that of traditional microframeworks, and then built a configuration layer on top of that to allow making substitutions. However, it's not only possible, but quite fun, to mix and match the two ideas!
From the blog
Posted 2016-04-26
On Deprecating ServiceLocatorAware
A month or two ago, we pushed a new release of zend-mvc that provides a number of forwards-compatibility features to help users prepare their applications for the upcoming v3 release.
One of those was, evidently, quite controversial: in v3, zend-servicemanager no
longer defines the ServiceLocatorAwareInterface
, and this particular release
of zend-mvc raises deprecation notices when you attempt to inject a service
locator into application services, or pull a service locator within your
controllers.
The arguments go something like this:
- "Dependency injection is too hard to understand!"
- "This feature simplifies development!"
- "If this is so bad, why was it in there in the first place?"
These are usually followed by folks:
- saying they'll switch frameworks (okay, I guess?);
- asking for re-instatement of the feature (um, no);
- asking for removal of the deprecation notices (why? so you can delay your pain until upgrading, when you'll ask for re-instatement of the feature?); or
- asking for a justification of the change.
So, I've decided to do the last, justify the change, which addresses the reasons
why we won't do the middle two, and addresses why the assumptions and assertions
about ServiceLocatorAware
's usefulness are mostly misguided.
From the blog
Posted 2016-04-17
Serve PSR-7 Middleware Via React
I've been intending to play with React for some time, but, for one reason or another, kept putting it off. This past week, I carved some time finally to experiment with it, and, specifically, to determine if serving PSR-7 middleware was possible.
From the blog
Posted 2016-01-29
Automating GitHub Pages Builds with MkDocs
One of the final tasks in prepping for the Expressive 1.0 release was setting up the documentation site. We'd decided to use GitHub Pages for this, and we wanted to automate builds so that as we push to the master branch, documentation is deployed.
The process turned out both simple and bewilderingly difficult. This post is intended to help others in the same situation.
From the blog
Posted 2016-01-28
Expressive 1.0 in the Wild!
A few hours ago, we pushed Expressive 1.0.
This is a huge milestone for the ZF3 initiative; I've even called it the cornerstone. It signals a huge shift in direction for the project, returning to its roots as a component library. Expressive itself, however, also signals the future of PHP applications we envision: composed of layered, single-purpose PSR-7 middleware.
From the blog
Posted 2015-12-14
Secure PHAR Automation
For a variety of reasons, I've been working on a utility that is best distributed via PHAR file. As has been noted by others (archive.is link, due to lack of availability of original site), PHAR distribution, while useful, is not without security concerns, and I decided to investigate how to securely create, distribute, and update PHAR utilities as part of this exercise.
This is an account of my journey, as well as concrete steps you can take to secure your own PHAR downloads.
From the blog
Posted 2015-09-18
On 10 Years at Zend
10 years ago, as I write this, I was on a plane from Burlington, VT, to San Jose, CA, where I'd be starting work at Zend Technologies the next day as a PHP Developer.
From the blog
Posted 2015-09-09
Fixing Version Issues When Running Composer from a Branch
For the Zend Framework component repositories, we occasionally need to backport changes to the 2.4 LTS releases. This requires checking out a branch based off the last LTS tag, applying patches (often with edits to translate PHP 5.5 syntax to PHP 5.3), and running tests against PHP 5.3 and 5.4.
Of course, to run the tests, you need the correct set of dependencies installed.
If you have any component dependencies, that means running a composer update
to ensure that you get the 2.4 versions of those components.
And that's where my story begins.
From the blog
Posted 2015-07-28
On PSR7 and HTTP Headers
Yesterday, a question tagged #psr7
on Twitter caught my eye:
#psr7
Request::getHeader($name)
return array of single string instead of strings in #Slim3? cc: @codeguy pic.twitter.com/ifA9hCKAPs
The image linked provides the following details:
When I call
$request->getHeader('Accept')
for example, I was expected that I'll get something like this:
Array( [0] => text/html, [1] => application/xhtml+xml, [2] => application/xml, )
but, in reallity I got this:
Array( [0] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 )
Is it correct?
In this post, I'll explain why the behavior observed is correct, as well as shed a light on a few details of header handling in PSR-7.
From the blog
Posted 2015-06-08
PHP is 20!
Today, 20 years ago, Rasmus Lerdorf publicly released PHP. Ben Ramsey has issued a call-to-action for people to blog the event and the impact PHP has had on their lives and careers; this is my entry.
From the blog
Posted 2015-05-18
PSR-7 Accepted!
I'm pleased to announce that as of 22:00 CDT on 18 May 2015, http://www.php-fig.org/psr/psr-7 PSR-7 (HTTP Message Interfaces) has been accepted!
From the blog
Posted 2015-05-15
Splitting the ZF2 Components
Today we accomplished one of the major goals towards Zend Framework 3: splitting the various components into their own repositories. This proved to be a huge challenge, due to the amount of history in our repository (the git repository has history going back to 2009, around the time ZF 1.8 was released!), and the goals we had for what component repositories should look like. This is the story of how we made it happen.
From the blog
Posted 2015-01-26
PSR-7 By Example
PSR-7 is now accepted!!!
I'm still hearing some grumbles both of "simplify!" and "not far enough!"
so I'm writing this posts to demonstrate usage of the currently published
interfaces, and to illustrate both the ease of use and the completeness and
robustness they offer.
First, though I want to clarify what PSR-7 is attempting.
From the blog
Posted 2015-01-08
On HTTP, Middleware, and PSR-7
As I've surveyed the successes and failures of ZF1 and ZF2, I've started considering how we can address usability: how do we make the framework more approachable?
One concept I've been researching a ton lately is middleware. Middleware exists in a mature form in Ruby (via Rack), Python (via WSGI), and Node (via Connect / ExpressJS); just about every language has some exemplar. Even PHP has some examples already, in StackPHP and Slim Framework.
The basic concept of middleware can be summed up in a single method signature:
function (request, response) { }
The idea is that objects, hashes, or structs representing the HTTP request and HTTP response are passed to a callable, which does something with them. You compose these in a number of ways to build an application.
From the blog
Posted 2014-09-18
Deployment with Zend Server (Part 8 of 8)
This is the final in a series of eight posts detailing tips on deploying to Zend Server. The previous post in the series detailed using the Zend Server SDK to deploy your Zend Server deployment packages (ZPKs) from the command line.
Today, I'll detail how I automate deployment with zf-deploy and zs-client (the Zend Server SDK), and wrap up the series with some closing thoughts.
From the blog
Posted 2014-09-16
Deployment with Zend Server (Part 7 of 8)
This is the seventh in a series of eight posts detailing tips on deploying to Zend Server. The previous post in the series detailed setting up and clearing page caching.
Today, I'm sharing how to use the Zend Server SDK to deploy your Zend Server deployment packages (ZPKs) from the command line.
From the blog
Posted 2014-09-11
Deployment with Zend Server (Part 6 of 8)
This is the sixth in a series of eight posts detailing tips on deploying to Zend Server. The previous post in the series detailed setting job script status codes.
Today, I'm sharing some tips around setting up page caching, and jobs for clearing the Zend Server page cache.
From the blog
Posted 2014-09-09
Deployment with Zend Server (Part 5 of 8)
This is the fifth in a series of eight posts detailing tips on deploying to Zend Server. The previous post in the series detailed how to secure your Job Queue job scripts.
Today, I'm sharing some best practices around writing job scripts, particularly around how to indicate execution status.
From the blog
Posted 2014-09-04
Deployment with Zend Server (Part 4 of 8)
This is the fourth in a series of eight posts detailing tips on deploying to Zend Server. The previous post in the series detailed a trick I learned about when to execute a chmod statement during deployment.
Today, I'm sharing a tip about securing your Job Queue job scripts.
From the blog
Posted 2014-09-02
Deployment with Zend Server (Part 3 of 8)
This is the third in a series of eight posts detailing tips on deploying to Zend Server. The previous post in the series detailed creating recurring jobs via Zend Job Queue, à la cronjobs.
Today, I'm sharing a very short deployment script tip learned by experience.
From the blog
Posted 2014-08-28
Deployment with Zend Server (Part 2 of 8)
This is the second in a series of eight posts detailing tips on deploying to Zend Server. The previous post in the series detailed getting started with Zend Server on the AWS marketplace and using zf-deploy to create ZPK packages to deploy to Zend Server.
Today, I'm looking at how to created scheduled/recurring jobs using Zend Server's Job Queue; think of this as application-level cronjobs.
From the blog
Posted 2014-08-26
Deployment with Zend Server (Part 1 of 8)
I manage a number of websites running on Zend Server, Zend's PHP application platform. I've started accumulating a number of patterns and tricks that make the deployments more successful, and which also allow me to do more advanced things such as setting up recurring jobs for the application, clearing page caches, and more.
From the blog
Posted 2014-08-21
Testing Code That Emits Output
Here's the scenario: you have code that will emit headers and content, for instance, a front controller. How do you test this?
The answer is remarkably simple, but non-obvious: namespaces.
From the blog
Posted 2014-06-09
Better Understanding Controllers Through Basic Patterns
Paul M. Jones has started an interesting discussion rethinking the MVC pattern as applied to the web, which he has dubbed Action-Domain-Responder (ADR). If you haven't given it a read yet, click the link and do that; this page will still be sitting here waiting when you return.
I agree with a ton of it — heck, I've contributed to it a fair bit via conversations with Paul. But there's been one thing nagging at me for a bit now, and I was finally able to put it into words recently.
Controllers — Actions in ADR — can be explained as facades.
From the blog
Posted 2014-03-26
Apigility: Using RPC with HAL
A few days ago, we released our first beta of Apigility. We've started our documentation effort now, and one question has arisen a few times that I want to address: How can you use Hypermedia Application Language (HAL) in RPC services?
From the blog
Posted 2013-02-25
RESTful APIs with ZF2, Part 3
In my previous
posts, I covered basics
of JSON hypermedia APIs using Hypermedia Application Language (HAL), and
methods for reporting errors, including API-Problem and vnd.error
.
In this post, I'll be covering documenting your API — techniques you can use to indicate what HTTP operations are allowed, as well as convey the full documentation on what endpoints are available, what they accept, and what you can expect them to return.
While I will continue covering general aspects of RESTful APIs in this post, I will also finally introduce several ZF2-specific techniques.
From the blog
Posted 2013-02-13
RESTful APIs with ZF2, Part 2
In my last post, I covered some background on REST and the Richardson Maturity Model, and some emerging standards around hypermedia APIs in JSON; in particular, I outlined aspects of Hypermedia Application Language (HAL), and how it can be used to define a generic structure for JSON resources.
In this post, I cover an aspect of RESTful APIs that's often overlooked: reporting problems.
From the blog
Posted 2013-02-12
RESTful APIs with ZF2, Part 1
RESTful APIs have been an interest of mine for a couple of years, but due to circumstances, I've not had much chance to work with them in any meaningful fashion until recently.
Rob Allen and I proposed a workshop for PHP Benelux 2013 covering RESTful APIs with ZF2. When it was accepted, it gave me the perfect opportunity to dive in and start putting the various pieces together.
From the blog
Posted 2012-12-30
OpenShift, Cron, and Naked Domains
As an experiment, I migrated my website over to OpenShift yesterday. I've been hosting a pastebin there already, and have found the service to be both straightforward and flexible; it was time to put it to a more thorough test.
In the process, I ran into a number of interesting issues, some of which took quite some time to resolve; this post is both to help inform other potential users of the service, as well as act as a reminder to myself.
From the blog
Posted 2012-12-20
On php-fig and Shared Interfaces
This is a post I've been meaning to write for a long time, and one requested of me personally by Evert Pot during the Dutch PHP Conference in June 2012. It details some observations I have of php-fig, and hopefully will serve as a record of why I'm not directly participating any longer.
I was a founding member of the Framework Interoperability Group, now called "php-fig". I was one of around a dozen folks who sat around a table in 2009 in Chicago during php|tek and started discussions about what we could all do to make it possible to work better together between our projects, and make it simpler for users to pick and choose from our projects in order to build the solutions to their own problems.
The first "standard" that came from this was PSR-0, which promoted a standard class naming convention that uses a 1:1 relationship between the namespace and/or vendor prefix and the directory hierarchy, and the class name and the filename in which it lives. To this day, there are both those who hail this as a great step forward for cooperation, and simultaneously others who feel it's a terrible practice.
And then nothing, for years. But a little over a year ago, there was a new push by a number of folks wanting to do more. Paul Jones did a remarkable job of spearheading the next two standards, which centered around coding style. Again, just like with PSR-0, we had both those feeling it was a huge step forward, and those who loathe the direction.
What was interesting, though, was that once we started seeing some new energy and momentum, it seemed that everyone wanted a say. And we started getting dozens of folks a week asking to be voting members, and new proposal after new proposal. Whether or not somebody likes an existing standard, they want to have backing for a standard they propose.
And this is when we started seeing proposals surface for shared interfaces, first around caching, and now around logging (though the latter is the first up for vote).
From the blog
Posted 2012-12-18
PHP Master Series on Day Camp For Developers
Cal Evans has organized another DayCamp4Developers event, this time entitled "PHP Master Series, Volume 1". I'm honored to be an invited speaker for this first edition, where I'll be presenting my talk, "Designing Beautiful Software".
Why would you want to participate? Well, for one, because you can interact directly with the various speakers during the presentations. Sure, you can likely find the slide decks elsewhere, or possibly even recordings. But if we all do our jobs right, we'll likely raise more questions than answers; if you attend, you'll get a chance to ask some of your questions immediately, and we may even answer them!
On top of that, this is a fantastic lineup of speakers, and, frankly, not a lineup I've ever participated in. In a typical conference, you'd likely see one or two of us, and be lucky if we weren't scheduled against each other; if you attend this week, you'll get to see us all, back-to-back.
What else will you be doing this Friday, anyways, while you wait for the end of the world?
So, do yourself a favor, and register today!
From the blog
Posted 2012-11-17
My ZendCon Beautiful Software Talk
Once again, I spoke at ZendCon this year; in talking with Christian Wenz, we're pretty sure that the two of us and Andi are the only ones who have spoken at all eight events.
Unusually for me, I did not speak on a Zend Framework topic, and had only one regular slot (I also co-presented a Design Patterns tutorial with my team). That slot, however, became one of my favorite talks I've delivered: "Designing Beautiful Software". I've given this talk a couple times before, but I completely rewrote it for this conference in order to better convey my core message: beautiful software is maintainable and extensible; writing software is a craft.
I discovered today that not only was it recorded, but it's been posted on YouTube:
From the blog
Posted 2012-09-19
ZF2 Modules Quickstart (Screencast)
One of the exciting features of the newly released Zend Framework 2 is the new module system.
While ZF1 had modules, they were difficult to manage. All resources for all modules were initialized on each request, and bootstrapping modules was an onerous task. Due to the difficulties, modules were never truly "plug-and-play", and thus no ecosystem ever evolved for sharing modules.
In Zend Framework 2, we've architected the MVC from the ground up to make modular applications as easy as possible. Within ZF2, the MVC simply cares about events and services — and controllers are simply one kind of service. As such, modules are primarily about telling the MVC about services and wiring event listeners.
To give you an example, in this tutorial, I'll show you how to install the Zend Framework 2 skeleton application, and we'll then install a module and see how easy it is to add it to the application and then configure it.
From the blog
Posted 2012-08-17
On Microframeworks
A number of months ago, Ed Finkler started a discussion in the PHP community about "MicroPHP"; to summarize, the movement is about:
- Building small, single-purpose libraries.
- Using small things that work together to solve larger problems.
I think there are some really good ideas that have come out of this, and also a number of questionable practices1.
One piece in particular I've focussed on is the concept of so-called “microframeworks”.
From the blog
Posted 2012-07-30
ZF2's New Controller::init()
In Zend Framework 1, controller's had an init()
method, which was called
after the controller was instantiated. The reason for it was to encourage
developers not to override the constructor, and thus potentially break some of
the functionality (as a number of objects were injected via the constructor).
init()
was useful for doing additional object initialization.
class MyController extends Zend_Controller_Action
{
public function init()
{
// do some stuff!
}
}
But this feature is missing from ZF2; how can we accomplish this sort of pattern?
From the blog
Posted 2012-07-05
ZF2 Forms in Beta5
Forms are a nightmare for web development. They break the concept of separation of concerns:
- They have a display aspect (the actual HTML form)
- They have a validation aspect
- And the two mix, as you need to display validation error messages.
On top of that, the submitted data is often directly related to your domain models, causing more issues:
- Not all elements will have a 1:1 mapping to the domain model — buttons, CSRF protection, CAPTCHAs, etc. usually are application-level concerns, but not domain issues. Names valid for your domain model may not be valid names for HTML entities.
Add to this that the validation logic may be re-usable outside of a forms context, and you've got a rather complex problem.
From the blog
Posted 2012-06-28
On Visibility in OOP
I'm a big proponent of object oriented programming. OOP done right helps ease code maintenance and enables code re-use.
Starting in PHP, OOP enthusiasts got a whole bunch of new tools, and new tools keep coming into the language for us with each minor release. One feature that has had a huge impact on frameworks and libraries has been available since the earliest PHP 5 versions: visibility.
From the blog
Posted 2012-04-30
Why Modules?
I've blogged about getting started with ZF2 modules, as well as about ZF2 modules you can already use. But after fielding some questions recently, I realized I should talk about why modules are important for the ZF2 ecosystem.
From the blog
Posted 2012-04-03
Developing A ZF2 Blog
This post tells a story.
A long time ago, I set out to write my own blog platform. Yes, WordPress is a fine blogging platform, as is Serendipity (aka "s9y", and my previous platform). And yes, I know about Habari. And, for those of you skimming ahead, yes, I'm quite aware of Jekyll, thank you anyways.
Why write something of my own? Well, of course, there's the fact that I'm a developer, and have control issues. Then there's also the fact that a blog is both a simple enough domain to allow easily experimenting with new technology and paradigms, while simultaneously providing a complex enough domain to expose non-trivial issues.
When I started this project, it was a technology-centered endeavor; I wanted to play with document databases such as CouchDB and MongoDB, and with caching technologies like memcached and redis.
Not long after I started, I also realized it was a great playground for me to prototype ideas for ZF2; in fact, the original DI and MVC prototypes lived as branches of my blog. (My repository is still named "zf2sandbox" to this day, though it technically houses just my site.)
Over time, I had a few realizations. First, my actual blog was suffering. I wasn't taking the time to perform security updates, nor even normal upgrades, and was so far behind as to make the process non-trivial, particularly as I had a custom theme, and because I was proxying to my blog via a ZF app in order to facilitate a cohesive site look-and-feel. I needed to either sink time into upgrading, or finish my blog.
My second realization, however, was the more important one: I wanted a platform where I could write how I want to write. I am a keyboard-centric developer and computer user, and while I love the web, I hate typing in its forms. Additionally, my posts often take longer than a typical browser session — which leaves me either losing my work in a GUI admin, or having to write first in my editor of choice, and then cut-and-paste it to the web forms. Finally, I want versions I can easily browse with standard diffing tools.
When it came down to it, my blog content is basically static. Occasionally, I'll update a post, but it's rare. Comments are really the only dynamic aspect of the blog… and what I had with s9y was not cutting it, as I was getting more spam than I could keep up with. New commenting platforms such as Livefyre and Disqus provide more features than most blogging platforms I know, and provide another side benefit: because they are javascript-based, you can simply drop in a small amount of markup into your post once — meaning your pages can be fully static!
Add these thoughts to the rise of static blogging platforms such as the aforementioned Jekyll, and I had a kernel of an idea: take the work I'd done already, and create a static blog generator.
From the blog
Posted 2012-03-05
View Layers, Database Abstraction, Configuration, Oh, My!
Late last week, the Zend Framework community released 2.0.0beta3, the latest iteration of the v2 framework. What have we been busy doing the last couple months? In a nutshell, getting dirty with view layers, database abstraction, and configuration.
From the blog
Posted 2012-02-08
ZF2 Modules You Can Use Today
One key new architectural feature of Zend Framework 2 is its new module infrastructure. The basic idea behind modules is to allow developers to both create and consume re-usable application functionality — anything from packaging common assets such as CSS and JavaScript to providing MVC application classes.
From the blog
Posted 2012-01-18
Call A Spade A Spade
I don't often get political on my blog, or over social media. But those of you who follow me on twitter lately have been treated to a number of tweets and retweets from me about some bills before the US legislative bodies called "SOPA" and "PIPA". Over the last couple days, I realized exactly why I disagree with them, and felt 140 characters is not enough.
From the blog
Posted 2012-01-11
Why Conventions Matter
When I started teaching myself scripting languages, I started with Perl. One Perl motto is "TMTOWTDI" — "There's More Than One Way To Do It," and pronounced "tim-toady." The idea is that there's likely multiple ways to accomplish the very same thing, and the culture of the language encourages finding novel ways to do things.
I've seen this principle used everywhere and in just about every programming situation possible, applied to logical operations, naming conventions, formatting, and even project structure. Everyone has an opinion on these topics, and given free rein to implement as they see fit, it's rare that two developers will come up with the same conventions.
TMTOWTDI is an incredibly freeing and egalitarian principle.
Over the years, however, my love for TMTOWTDI has diminished some. Freeing as it is, is also a driving force behind having coding standards and conventions — because when everyone does it their own way, projects become quickly hard to maintain. Each person finds themselves reformatting code to their own standards, simply so they can read it and follow its flow.
Additionally, TMTOWTDI can actually be a foe of simple, elegant solutions.
Why do I claim this?
From the blog
Posted 2011-12-16
On Error Handling and Closures
The error suppression operator in PHP (@
) is often seen as a necessary evil.
Many, many low-level function will return a value indicating an error, but also
raise an E_NOTICE
or E_WARNING
— things you might be able to recover from,
or conditions where you may want to raise an exception.
So, at times, you find yourself writing code like this:
if (false === ($fh = @fopen($filename, 'r'))) {
throw new RuntimeException(sprintf(
'Could not open file "%s" to read', $filename
));
}
Seems straight-forward enough, right? But it's wrong on so many levels.
From the blog
Posted 2011-11-07
Getting started writing ZF2 modules
During ZendCon this year, we released 2.0.0beta1 of Zend Framework. The key story in the release is the creation of a new MVC layer, and to sweeten the story, the addition of a modular application architecture.
"Modular? What's that mean?" For ZF2, "modular" means that your application is built of one or more "modules". In a lexicon agreed upon during our IRC meetings, a module is a collection of code and other files that solves a specific atomic problem of the application or website.
As an example, consider a typical corporate website in a technical arena. You might have:
- A home page
- Product and other marketing pages
- Some forums
- A corporate blog
- A knowledge base/FAQ area
- Contact forms
These can be divided into discrete modules:
- A "pages" modules for the home page, product, and marketing pages
- A "forum" module
- A "blog" module
- An "faq" or "kb" module
- A "contact" module
Furthermore, if these are developed well and discretely, they can be re-used between different applications!
So, let's dive into ZF2 modules!
From the blog
Posted 2011-09-12
Using the ZF2 EventManager
Earlier this year, I wrote about Aspects, Intercepting Filters, Signal Slots, and Events, in order to compare these similar approaches to handling both asychronous programming as well as handling cross-cutting application concerns in a cohesive way.
I took the research I did for that article, and applied it to what was then a "SignalSlot" implementation within Zend Framework 2, and refactored that work into a new "EventManager" component. This article is intended to get you up and running with it.
From the blog
Posted 2011-08-03
Using DocBlox
Until a few years ago, there were basically two tools you could use to generate API documentation in PHP: phpDocumentor and Doxygen. phpDocumentor was long considered the standard, with Doxygen getting notice when more advanced features such as inheritance diagrams are required. However, phpDocumentor is practically unsupported at this time (though a small group of developers is working on a new version), and Doxygen has never had PHP as its primary concern. As such, a number of new projects are starting to emerge as replacements.
One of these is DocBlox. I am well aware there are several others — and indeed, I've tried several of them. This post is not here to debate the merits or demerits of this or other solutions; the intention is to introduce you to DocBlox so that you can evaluate it yourself.
From the blog
Posted 2011-07-19
Converting DocBook4 to DocBook5
Within the Zend Framework 2 repository,
I recently performed a conversion from DocBook 4 to 5.
The latter is a more modern version of the toolchain, and offers a somewhat
simpler syntax and workflow. For example, you no longer need to track how many
levels deep you are in your chapter sections — you simply use a <section>
tag.
One of the nicer changes is that you do not need to specify a doctype any more;
you simply declare XML namespaces on your root elements and continue merrily on
your way. This actually allows us to remove some actions in our build process,
and makes validation much simpler.
Interestingly, for DocBook5 being available in beta since 2005 and an official standard since 2009, there is very little material on migrating from DocBook 4 to 5.
From the blog
Posted 2011-07-05
Proxies in PHP
A number of programming design patterns look very similar. One of these is the Proxy pattern, which, at first glance, can look like a number of others: Decorator, Flyweight, even plain old object extension. However, it has its own niche, and it can provide some incredible flexibility for a number of programming scenarios.
From the blog
Posted 2011-05-10
Backported ZF2 Autoloaders
In the past six weeks, I've delivered both a webinar and a tutorial on Zend Framework 2 development patterns. The first pattern I've explored is our new suite of autoloaders, which are aimed at both performance and rapid application development — the latter has always been true, as we've followed PEAR standards, but the former has been elusive within the 1.X series.
Interestingly, I've had quite some number of folks ask if they can use the new autoloaders in their Zend Framework 1 development. The short answer is "yes," assuming you're running PHP 5.3 already. If not, however, until today, the answer has been "no."
From the blog
Posted 2011-03-25
Code Generation with Zend\CodeGenerator
Zend Framework has offerred a code generation component since version 1.8, when
we started shipping Zend_Tool
. Zend_CodeGenerator
largely mimics PHP's
Reflection API, but does the opposite: it instead generates code.
Why might you want to generate code?
- You can use it as an assistive form of "copy and paste" for common tasks (as
an example, it's used in
zf.sh
to generate controller classes and action methods). - You might want to generate code from configuration, to remove the "compile" phase of generating objects from configuration values. This is often done to improve performance in situations that rely heavily on configurable values.
Zend\CodeGenerator
in the ZF2 repository is largely ported from Zend Framework
1, but also includes some functionality surrounding namespace usage and imports.
I used it this week when working on some prototypes, and found it useful enough
that I want to share some of what I've learned.
From the blog
Posted 2011-03-21
Dependency Injection: An analogy
I've been working on a proposal for including service locators and dependency injection containers in Zend Framework 2.0, and one issue I've had is trying to explain the basic concept to developers unfamiliar with the concepts — or with pre-conceptions that diverge from the use cases I'm proposing.
In talking with my wife about it a week or two ago, I realized that I needed an analogy she could understand; I was basically using her as my rubber duck. And it turned out to be a great idea, as it gave me some good analogies.
From the blog
Posted 2011-03-15
The Ideas of March
Chris Shiflett has asked the question, why don't people blog anymore? In this age of real-time streams and dead-simple status updates, blogs often feel like the uncared-for step-child or a website; indeed, many folks are trading their blogs for pages that simply track their various lifestreams (tweets, facebook status, flickr images, and more).
While this sort of thing is trendy and interesting, it also sucks:
From the blog
Posted 2011-03-10
Git Subtree Merging Guide
I've been investigating ways to incorporate third-party repositories and
libraries into my Git projects. Subversion's
svn:externals
capabilities are one compelling feature for that particular
VCS, and few, if any, other VCS systems, particularly the DVCS systems, have a
truly viable equivalent. Git submodules
aren't terrible, but they assume you
want the entire repository — whereas SVN allows you to cherry-pick
subdirectories if desired.
Why might I want to link only a subdirectory? Consider a project with this structure:
docs/
api/
manual/
html/
module_specs/
library/
Foo/
ComponentA/
ComponentB/
tests/
Foo/
ComponentA/
ComponentB/
On another project, I want to use ComponentB. With svn:externals
, this is easy:
library/Foo/ComponentB http://repohost/svn/trunk/library/Foo/ComponentB
and now the directory is added and tracked.
With Git, it's a different story. One solution I've found is using
git-subtree, an extension to Git. It
takes a bit more effort to setup than svn:externals
, but offers the benefits
of easily freezing on a specific commit, and squashing all changes into a
single commit.
Jon Whitcraft recently had some questions about how to use it, and I answered him via email. Evidently what I gave him worked for him, as he then requested if he could post my guide — which you can find here.
From the blog
Posted 2011-03-09
PHP Community Conference
Last year, a new conference launched, Brooklyn Beta. The buzz I heard about it from attendees was amazing; words like "inspiring," "intimate," and "energizing" were all used to describe the experience. I found myself wishing I'd made time in my schedule to attend.
Fast forward a few months, and a new conference has been announced, the PHP Community Conference. It has similar goals to Brooklyn Beta: create a conference where we can talk about the language we love so passionately.
From the blog
Posted 2011-03-04
How to Contribute to ZF2
ZF2 development is ramping up. We've been at it for some time now, but mostly taking care of infrastructure: converting to namespaces, re-working our exception strategy, improving our test suites, and improving our autoloading and plugin loading strategies to be more performant and flexible. Today, we're actively working on the MVC milestone, which we expect to be one of the last major pieces necessary for developers to start developing on top of ZF2.
A question I receive often is: "How can I contribute to ZF2?"
Consider this your guide.
From the blog
Posted 2011-02-04
Why PHP Namespaces Matter
You've heard about PHP namespaces by now. Most likely, you've heard about — and likely participated in — the bikeshedding surrounding the selection of the namespace separator.
Regardless of your thoughts on the namespace separator, or how namespaces may or may not work in other languages, I submit to you several reasons for why I think namespaces in PHP are a positive addition to the language.
From the blog
Posted 2011-01-17
Taming SplPriorityQueue
SplPriorityQueue is a fantastic new feature of PHP 5.3. However, in trying to utilize it in a few projects recently, I've run into some behavior that's (a) non-intuitive, and (b) in some cases at least, undesired. In this post, I'll present my solutions.
From the blog
Posted 2011-01-10
Aspects, Filters, and Signals, Oh, My!
Last month, during PHP Advent, gwoo wrote an interesting post on Aspect-Oriented Design, or Aspect Oriented Programming (AOP) as it is more commonly known. The article got me to thinking, and revisiting what I know about AOP, Intercepting Filters, and Signal Slots -- in particular, what use cases I see for them, what the state of current PHP offerings are, and where the future may lie.
But first, some background is probably in order, as this is a jargon-heavy post.
From the blog
Posted 2011-01-06
Making Zend Server Available Via SSL Only
In light of the recent remote PHP exploit, I decided to update a couple servers I manage to ensure they weren't vulnerable. In each case, I had been using hand-compiled PHP builds, but decided that I'm simply too busy lately to be trying to maintain updates — so I decided to install Zend Server. I've been using Zend Server CE on my laptop since before even any initial private betas, and have been pretty happy with it — I only compile now when I need to test specific PHP versions.
One thing I've never been happy about, however, is that by default Zend Server exposes its administration GUI via both HTTP and HTTPS. Considering that the password gives you access to a lot of sensitive configuration, I want it to be encrypted.
From the blog
Posted 2010-12-22
Simple Interfaces and Micro MVCs
My job is great: I get to play with technology and code most days. My job is also hard: how does one balance both functionality and usability in programming interfaces?
I've been working, with Ralph Schindler, on a set of proposals around the Zend Framework 2.0 MVC layer, specifically the "C", or "Controller" portion of the triad. There are a ton of requirements we're trying to juggle, from making the code approachable to newcomers all the way to making the code as extensible as possible for the radical performance tuning developers out there.
From the blog
Posted 2010-12-15
Vim Toolbox, 2010 Edition
I've been using Vim for close to a decade. I've often said that "Unix is my IDE" — because Vim is built in the Unix philosophy, allowing me to pipe input into it, out of it, and every which way I want. It fits very nicely with the Unix philosophy of doing one task well, and allowing redirection. I've found it ideal for web development in general and PHP development specifically — in fact, I've had excellent experiences in every language I've tried my hand at developing in when using Vim.
Vim is also my chosen productivity suite. When I want to write a document, I don't go into OO.o Writer or MS Word or some other word processor; I open up a window and start typing. In most cases, I can either cut and paste my work into other tools, or pipe it to transformation tools. I worry about the content first, and the presentation later… like any good MVC application. ;-)
Like any good tool, you have to invest time in it in order to reap its benefits. My learning has, to date, fallen into three time periods:
- The initial months in which I first learned Vim, via vimtutor and Steve Oualline's Vim book.
- A period in 2006-2007 when I felt the need to make my coding more efficient, and first started playing with exuberant-ctags and omni-completion.
- The last quarter of 2010 (yes, that's now) when I was introduced to a number of new tools via Twitter.
So, this is my Vim Toolbox, 2010 edition.
From the blog
Posted 2010-11-09
Introducing the ZF2 Plugin Broker
In Zend Framework 2.0, we're refactoring in a number of areas in order to increase the consistency of the framework. One area we identified early is how plugins are loaded.
The word "plugins" in Zend Framework applies to a number of items:
- Helpers (view helpers, action helpers)
- Application resources
- Filters and validators (particularly when applied to
Zend_Filter_Input
andZend_Form
) - Adapters
In practically every case, we use a "short name" to name the plugin, in order to allow loading it dynamically. This allows more concise code, as well as the ability to configure the code in order to allow specifying alternate implementations.
From the blog
Posted 2010-10-27
ZendCon 2010!
As I write this, ZendCon begins in less than a week. I have the honor and pleasure to be speaking there again, for the sixth year running.
From the blog
Posted 2010-10-04
Using Action Helpers To Implement Re-Usable Widgets
I had a twitter/IRC exchange yesterday with Andries Seutens
and Nick Belhomme regarding applications that
include widgets within their layout. During the exchange, I told Andriess not to
use the action()
view helper, and both Andriess and Nick then asked how to
implement widgets if they shouldn't use that helper. While I ended up having an
IRC exchange with Nick to give him a general idea on how to accomplish the task,
I decided a longer writeup was in order.
From the blog
Posted 2010-08-17
Autoloading Benchmarks
During the past week, I've been looking at different strategies for autoloading in Zend Framework. I've suspected for some time that our class loading strategy might be one source of performance degradation, and wanted to research some different approaches, and compare performance.
In this post, I'll outline the approaches I've tried, the benchmarking stategy I applied, and the results of benchmarking each approach.
From the blog
Posted 2010-08-16
Applying FilterIterator to Directory Iteration
I'm currently doing research and prototyping for autoloading alternatives in
Zend Framework 2.0. One approach I'm looking at
involves creating explicit class/file maps; these tend to be much faster than
using the include_path
, but do require some additional setup.
My algorithm for generating the maps was absurdly simple:
- Scan the filesystem for PHP files
- If the file does not contain an interface, class, or abstract class, skip it.
- If it does, get its declared namespace and classname
The question was what implementation approach to use.
I'm well aware of RecursiveDirectoryIterator
, and planned to use that.
However, I also had heard of FilterIterator
, and wondered if I could tie that
in somehow. In the end, I could, but the solution was non-obvious.
From the blog
Posted 2010-08-09
Running mod_php and FastCGI side-by-side
Because we're in full throes of Zend Framework 2.0 development, I find myself with a variety of PHP binaries floating around my system from both the PHP 5.2 and 5.3 release series. We're at a point now where I'm wanting to test migrating applications from ZF 1.X to 2.0 to se see what works and what doesn't. But that means I need more than one PHP binary enabled on my server…
I use Zend Server on my development box; it's easy to install, and uses my native Ubuntu update manager to get updates. On Ubuntu, it installs the Debian Apache2 packages, so I get the added bonus of familiarity with the configuration structure.
I installed Zend Server some time ago, so I'm still on a PHP 5.2 mod_php
binary. I have several PHP 5.3 binaries compiled and installed locally for
running unit tests and sample scripts already — so the question was how to keep
my 5.2 mod_php
running while simultaneously allowing the ability to run
selected vhosts in 5.3?
The answer can be summed up in one acronym: FastCGI.
From the blog
Posted 2010-07-01
Creating Zend_Tool Providers
When I was at Symfony Live this past February, I assisted Stefan Koopmanschap in a full-day workshop on integrating Zend Framework in Symfony applications. During that workshop, Stefan demonstrated creating Symfony "tasks". These are classes that tie in to the Symfony command-line tooling — basically allowing you to tie in to the CLI tool in order to create cronjobs, migration scripts, etc.
Of course, Zend Framework has an analogue to Symfony tasks in the Zend_Tool component's "providers". In this post, I'll demonstrate how you can create a simple provider that will return the most recent entry from an RSS or Atom feed.
From the blog
Posted 2010-06-04
State of Zend Framework 2.0
The past few months have kept myself and my team quite busy, as we've turned our attentions from maintenance of the Zend Framework 1.X series to Zend Framework 2.0. I've been fielding questions regularly about ZF2 lately, and felt it was time to talk about the roadmap for ZF2, what we've done so far, and how the community can help.
From the blog
Posted 2010-05-06
Writing Gearman Workers in PHP
I've been hearing about and reading about Gearman for a couple years now, but, due to the nature of my work, it's never really been something I needed to investigate; when you're writing backend code, scalability is something you leave to the end-users, right?
Wrong! But perhaps an explanation is in order.
From the blog
Posted 2010-04-19
PHP Invades Amsterdam; or, the Dutch PHP Conference
For the third year running, I'm pleased to be speaking at the Dutch PHP Conference, held again in Amsterdam this coming 10–12 of June.
From the blog
Posted 2010-04-07
Please Join Me At TEK-X
I'll be speaking this year at TEK-X, this year's incarnation of the php|tek conference, in Chicago in May.
From the blog
Posted 2010-04-06
A Primer for PHP 5.3's New Language Features
For the past month, I've been immersed in PHP 5.3 as I and my team have started work on Zend Framework 2.0. PHP 5.3 offers a slew of new language features, many of which were developed to assist framework and library developers. Most of the time, these features are straight-forward, and you can simply use them; in other cases, however, we've run into behaviors that were unexpected. This post will detail several of these, so you either don't run into the same issues — or can capitalize on some of our discoveries.
From the blog
Posted 2010-03-24
GPG-signing Git Commits
We're working on migrating Zend Framework to Git. One issue we're trying to deal with is enforcing that commits come from CLA signees.
One possibility presented to us was the possibility of utilizing GPG signing of commit messages. Unfortunately, I was able to find little to no information on the 'net about how this might be done, so I started to experiment with some solutions.
The approach I chose utilizes git hooks,
specifically the commit-msg
hook client-side, and the pre-receive
hook
server-side.
From the blog
Posted 2010-03-19
A Simple Resource Injector for ZF Action Controllers
Brandon Savage approached me with an interesting issue regarding ZF bootstrap resources, and accessing them in your action controllers. Basically, he'd like to see any resource initialized by the bootstrap immediately available as simply a public member of his action controller.
So, for instance, if you were using the "DB" resource in your application, your
controller could access it via $this->db
.
From the blog
Posted 2010-03-11
Module Bootstraps in Zend Framework: Do's and Don'ts
I see a number of questions regularly about module bootstraps in Zend Framework, and decided it was time to write a post about them finally.
In Zend Framework 1.8.0, we added Zend_Application
, which is intended to (a)
formalize the bootstrapping process, and (b) make it re-usable. One aspect of
it was to allow bootstrapping of individual application modules — which are
discrete collections of controllers, views, and models.
The most common question I get regarding module bootstraps is:
Why are all module bootstraps run on every request, and not just the one for the requested module?
To answer that question, first I need to provide some background.
From the blog
Posted 2010-03-04
Responding to Different Content Types in RESTful ZF Apps
In previous articles, I've explored building service endpoints and RESTful services with Zend Framework. With RPC-style services, you get to cheat: the protocol dictates the content type (XML-RPC uses XML, JSON-RPC uses JSON, SOAP uses XML, etc.). With REST, however, you have to make choices: what serialization format will you support?
Why not support multiple formats?
There's no reason you can't re-use your RESTful web service to support multiple formats. Zend Framework and PHP have plenty of tools to assist you in responding to different format requests, so don't limit yourself. With a small amount of work, you can make your controllers format agnostic, and ensure that you respond appropriately to different requests.
From the blog
Posted 2010-02-17
Symfony Live 2010
This week, I've been attending Symfony Live in Paris, speaking on integrating Zend Framework with Symfony. The experience has been quite rewarding, and certainly eye-opening for many.
To be honest, I was a little worried about the conference — many see Symfony and ZF as being in competition, and that there would be no cross-pollination. I'm hoping that between Fabien, Stefan, and myself, we helped dispel that myth this week.
From the blog
Posted 2010-02-04
Creating Re-Usable Zend_Application Resource Plugins
In my last article,
I wrote about how to get started with Zend_Application
, including some
information about how to write resource methods, as well as listing available
resource plugins. What happens when you need a re-usable resource for which
there is no existing plugin shipped? Why, write your own, of course!
All plugins in Zend Framework follow a common pattern. Basically, you group plugins under a common directory, with a common class prefix, and then notify the pluggable class of their location.
For this post, let's consider that you may want a resource plugin to do the following:
- Set the view doctype
- Set the default page title and title separator
From the blog
Posted 2010-01-08
Quick Start to Zend_Application_Bootstrap
We added Zend_Application to Zend Framework starting in version 1.8.0. The intent behind the component was to formalize the application bootstrapping process, and provide a simplified, configuration-driven mechanism for it.
Zend_Application
works in conjunction with Zend_Application_Bootstrap
,
which, as you might guess from its name, is what really does the bulk of the
work for bootstrapping your application. It allows you to utilize plugin
bootstrap resources, or define local bootstrap resources as class methods. The
former allow for re-usability, and the latter for application-specific
initialization and configuration.
Additionally, Zend_Application_Bootstrap
provides for dependency tracking
(i.e., if one resource depends on another, you can ensure that that other
resource will be executed first), and acts as a repository for initialized
resources. This means that once a resource has been bootstrapped, you can
retrieve it later from the bootstrap itself.
From the blog
Posted 2009-12-10
Real-time ZF Monitoring via Zend Server
When keeping tabs on your ZF applications, it's often difficult to separate application errors from general PHP errors, and if you aggregate them in the same location as your web server errors, this can become more difficult still.
Additionally, PHP's error reporting doesn't provide a ton of context, even when reporting uncaught exceptions — typically you'll only get a cryptic exception message, and what file and line emitted it.
Zend Server's Monitor extension has some capabilities for providing more context, and does much of this by default: request and environment settings available when the error was logged, the function name and arguments provided, and a full backtrace are available for you to inspect. Additionally, the Monitor extension includes an API that allows you to trigger custom Monitor events, and you can provide additional context when doing so — such as passing objects or arrays that may help provide context when debugging.
From the blog
Posted 2009-11-09
Building RESTful Services with Zend Framework
As a followup to my previous post, I now turn to RESTful web services. I originally encountered the term when attending php|tropics in 2005, where George Schlossnaggle likened it to simple GET and POST requests. Since then, the architectural style — and developer understanding of the architectural style — has improved a bit, and a more solid definition can be made.
From the blog
Posted 2009-10-23
Exposing Service APIs via Zend Framework
The hubbub surrounding "Web 2.0" is around sharing data. In the early iterations, the focus was on "mashups" — consuming existing public APIs in order to mix and match data in unique ways. Now, more often than not, I'm hearing more about exposing services for others to consume. Zend Framework makes this latter trivially easy via its various server classes.
From the blog
Posted 2009-10-12
Speaking at ZendCon 2009
It's probably already a foregone conclusion, but I'm speaking once again at ZendCon this year — one week from today!
From the blog
Posted 2009-10-07
Why UnCons are Important
My good friend, Keith Casey, is once again chairing Zendcon's UnCon. For those who have never attended, it's basically one or more tracks running parallel to the main conference, but with content pitched by attendees — sometimes presented by them, other times presented by others who are knowledgeable in the field.
Why should you care? There are great sessions already selected for the conference featuring some well-known speakers from the PHP world; why would you want to either attend or present at the uncon?
From the blog
Posted 2009-09-22
CodeWorks 2009 Begins
Today is the kickoff for CodeWorks 2009, a remarkable PHP road show hitting seven cities in 14 days. While I'm not joining the tour until Atlanta, I'm proud to be joining up at that stop and presenting a Zend Framework tutorial during the tour.
From the blog
Posted 2009-08-31
Cloning the ZF SVN repository in Git
I've been using Git for around a year now. My interest in it originally was to act as a replacement for SVK, with which I'd had some bad experiences (when things go wrong with svk, they go very wrong). Why was I using a distributed version control system, though?
From the blog
Posted 2009-08-20
Blog Backlog
Several people have pointed out to me recently that I haven't blogged since early May, prior to attending php|tek. Since then, I've built up a huge backlog of blog entries, but had zero time to write any of them.
The backlog and lack of time has an easy explanation: my change of roles from Architect to Project Lead on the Zend Framework team. While the change is a welcome one, it's also been much more demanding on my time than I could have possibly envisioned. Out of the gate, I had to finish up the 1.8 release, and move immediately into planning and execution of the 1.9 release — while learning the ropes of my new position, and continuing some of my previous development duties. Add a couple of conferences (php|tek and DPC) into the mix, and you can begin to see the issues.
From the blog
Posted 2009-08-20
Autoloading Doctrine and Doctrine entities from Zend Framework
A number of people on the mailing list and twitter recently have asked how to autoload Doctrine using Zend Framework's autoloader, as well as how to autoload Doctrine models you've created. Having done a few projects using Doctrine recently, I can actually give an answer.
The short answer: just attach it to Zend_Loader_Autoloader
.
Now for the details.
From the blog
Posted 2009-05-13
Speaking at php|tek
I announced this earlier in the year, but for those that missed it, I'm speaking at php|tek next week.
I'll be co-presenting a workshop entitled Practical SVN for PHP Developers along with the lovely and talented Lorna Jane Mitchell. In a way, it's a continuation of the unconference session we did together at ZendCon08, and will provide much more in-depth information on the subject — including how to create and organize your repositories, branching and tagging strategies, how and when to commit, as well as more basic usage of subversion for day-to-day use.
From the blog
Posted 2009-04-13
Creating composite elements
In my last post on decorators, I had an example that showed rendering a "date of birth" element:
<div class=\"element\">
<?php echo $form->dateOfBirth->renderLabel() ?>
<?php echo $this->formText('dateOfBirth[day]', '', array(
'size' => 2, 'maxlength' => 2)) ?>
/
<?php echo $this->formText('dateOfBirth[month]', '', array(
'size' => 2, 'maxlength' => 2)) ?>
/
<?php echo $this->formText('dateOfBirth[year]', '', array(
'size' => 4, 'maxlength' => 4)) ?>
</div>
This has prompted some questions about how this element might be represented as
a Zend_Form_Element
, as well as how a decorator might be written to
encapsulate this logic. Fortunately, I'd already planned to tackle those very
subjects for this post!
From the blog
Posted 2009-04-10
Speaking at DPC (again!)
I'm thrilled to once again be speaking at the Dutch PHP Conference.
Like last year, I'm giving two sessions; unlike last year, these are going to be more advanced. I noticed last year both in terms of audience participation as well as in speaking with attendees that I'd be able to step it up a notch were I to return.
From the blog
Posted 2009-04-09
Rendering Zend_Form decorators individually
In the previous installment of this series on Zend_Form
decorators, I looked at how you can combine decorators to create complex output. In that write-up, I noted that while you have a ton of flexibility with this approach, it also adds some complexity and overhead. In this article, I will show you how to render decorators individually in order to create custom markup for your form and/or individual elements.
From the blog
Posted 2009-04-07
Zend Framework 1.8 PREVIEW Release
By the time you read this, the Zend Framework team will have released a preview release of 1.8.0. While the final release is scheduled for later this month, this release represents the hard work of many contributors and shows off a variety of powerful new components.
If you're a Zend Framework user, you should give the preview release a spin, to see what it can do:
From the blog
Posted 2009-04-06
From the inside-out: How to layer decorators
This marks the second in an on-going series on Zend_Form
decorators.
You may have noticed in the previous installment that the decorator's render()
method takes a single argument, $content
. This is expected to be a string. render()
will then take this string and decide to either replace it, append to it, or prepend it. This allows you to have a chain of decorators — which allows you to create decorators that render only a subset of the element's metadata, and then layer these decorators to build the full markup for the element.
Let's look at how this works in practice.
From the blog
Posted 2009-04-03
The simplest Zend_Form decorator
I've been seeing ranting and general confusion about Zend_Form decorators (as well as the occasional praises), and thought I'd do a mini-series of blog posts showing how they work.
From the blog
Posted 2009-03-12
Why Vim Plugins for IDEs Fail
I'm an unabashed Vim user. It has been my primary editor for over seven years now, when I switched to it to make it easier to edit files over SSH. At the time, I made myself use it exclusively for a month so that the habits would be ingrained, and took the time to go through vimtutor as well as to order and read Steve Oualline's Vim book. And when I say "exclusively," I mean it — I switched to using Mutt for email at that time, and also started doing all code development, outlining, and more in vim. And after a month, I realized I didn't want to use anything else.
Ironically, I find myself working for a company that sells an Integrated Development Environment (IDE). As a result, I've done some test runs with Eclipse, Zend Studio for Eclipse, and even NetBeans, to see what features they offer and to see if there would be anything compelling that might make me change my mind.
From the blog
Posted 2009-03-10
Syntax Highlighting for Technical Presentations
Being a technical presenter, I've often run up against the issue of how to present code snippets.
The easiest route is to simply cut-and-paste into your presentation software. However, such code is basically unreadable: it's hard to get indentation correct, and the lack of syntax highlighting makes them difficult to read (syntax highlighting helps users understand the purpose of the various language constructs).
From the blog
Posted 2009-03-03
Speaking at PHP Quebec
I'm speaking at PHP Quebec this week. While I live a scant 1.5 hours away from the venue, this is the first I've been to the conference. The snow gods have declared their wrath already, but I plan to thwart them and drive up to Montreal this evening regardless.
I'm giving two talks and participating in a panel discussion this week. The first talk is entitled "Practical Zend Framework Jutsu with Dojo," and, while it may look like a familiar topic of mine by this point, I've spent the last several days reworking the talk entirely, and am very much looking forward to presenting it tomorrow. (My copy of "Presentation Zen" could not have come soon enough! and that's all I'll say about that.)
On Friday, PHP Quebec has introduced a "Framework Bootcamp" track, including sessions by myself, Fabien Potencier of symfony, and Derick Rethans representing eZ Components. My talk that day is entitled "Zend Framework Little Known Gems." While hardly a completely original talk (Aaron Wormus did a "Hidden Gems" series of posts for DevZone a couple years back, and Zend's own Shahar Evron did a similar talk at last fall's IPC), this will be my first time doing a Zend Framework talk on something other than the MVC stack (or how to use components with the MVC stack). Leaving my comfort zone, so to speak.
Towards the end of the day, Fabien, Derick, and myself will be corralled onstage together for a "Framework Comparison".
If you're headed up to PHP Quebec this week, I look forward to meeting you or seeing you again!
From the blog
Posted 2009-01-02
Seven Things - Tagged by Keith Casey
I'm really not sure I understand these "seven things" or "tagged" memes, but I'm going to give it a shot, after Keith Casey did a drive-by tagging of me on New Year's Eve.
So, without further ado, seven things you may not know about me…
From the blog
Posted 2008-12-31
2008: The year in review
That time of year again — wrap-up time. Each year, it seems like it's the busiest ever, and I often wonder if it will ever slow down. As usual, I'm restricting myself to primarily professional activities out of respect for the privacy of my family.
The short, executive summary:
- One trip to Israel
- One trip to The Netherlands
- One trip to California's Bay Area
- One trip to Atlanta, GA
- Three minor releases of Zend Framework
- Seven webinars, six for zend.com and one for Adobe
- Three conferences attended as a speaker, including:
- One six-hour workshop
- One three-hour tutorial (as a co-presenter)
- Four regular sessions
- Two panel sessions (one scheduled, one for an uncon)
- Two uncon sessions (one as a co-presenter)
- One foul-mouthed Pecha Kucha talk
- Ten Burlington, VT PHP User's Group meetings attended; I spoke at many
- One Bug Hunt week organized
- Two books reviewed as a technical editor
- Six articles for DevZone
- 50 blog entries (including this one)
Read on for the gruesome, month-by-month breakdown.
From the blog
Posted 2008-12-30
Model Infrastructure
In the last two entries in this series on models, I covered using forms as input filters and integrating ACLs into models. In this entry, I tackle some potential infrastructure for your models.
The Model is a complex subject. However, it is often boiled down to either a single model class or a full object relational mapping (ORM). I personally have never been much of a fan of ORMs as they tie models to the underlying database structure; I don't always use a database, nor do I want to rely on an ORM solution too heavily on the off-chance that I later need to refactor to use services or another type of persistence store. On the other hand, the model as a single class is typically too simplistic.
From the blog
Posted 2008-12-24
Applying ACLs to Models
In my last post, I discussed using Zend_Form as a combination input filter/value object within your models. In this post, I'll discuss using Access Control Lists (ACLs) as part of your modelling strategy.
ACLs are used to indicate who has access to do what on a given resource. In the paradigm I will put forward, your resource is your model, and the what are the various methods of the model. If you finesse a bit, you'll have "user" objects that act as your who.
Just like with forms, you want to put your ACLs as close to your domain logic as possible; in fact, ACLs are part of your domain.
From the blog
Posted 2008-12-22
Using Zend_Form in Your Models
A number of blog posts have sprung up lately in the Zend Framework community discussing the Model in the Model-View-Controller pattern. Zend Framework has never had a concrete Model class or interface; our stand has been that models are specific to the application, and only the developer can really know what would best suit it.
Many other frameworks tie the Model to data access — typically via the ActiveRecord pattern or a Table Data Gateway — which completely ignores the fact that this is tying the Model to the method by which it is persisted. What happens later if you start using memcached? or migrate to an SOA architecture? What if, from the very beginning, your data is coming from a web service? What if you do use a database, but your business logic relies on associations between tables?
While the aforementioned posts do an admirable job of discussing the various issues, they don't necessarily give any concrete approaches a developer can use when creating their models. As such, this will be the first in a series of posts aiming to provide some concrete patterns and techniques you can use when creating your models. The examples will primarily be drawing from Zend Framework components, but should apply equally well to a variety of other frameworks.
From the blog
Posted 2008-12-15
A Simple PHP Publish-Subscribe System
I've been playing a lot with Dojo lately, and have been very impressed by its elegant publish-subscribe system. Basically, any object can publish an event, and any other object can subscribe to it. This creates an incredibly flexible notification architecture that's completely opt-in.
The system has elements of Aspect Oriented Programming (AOP), as well as the Observer pattern. Its power, however, is in the fact that an individual object does not need to implement any specific interface in order to act as either a Subject or an Observer; the system is globally available.
Being a developer who recognizes good ideas when he sees them, of course I decided to port the idea to PHP. You can see the results on github.
From the blog
Posted 2008-12-12
Autocompletion with Zend Framework and Dojo
I've fielded several questions about setting up an autocompleter with Zend Framework and Dojo, and decided it was time to create a HOWTO on the subject, particularly as there are some nuances you need to pay attention to.
From the blog
Posted 2008-12-02
Tidings of the Season
Just about every day, I have an idea for a blog post, and most days, by the end of the day, I just don't have the time or energy to actually write anything up. The inner writer in me screams, "no excuses!" while the aging adult in me whispers, "time for bed, dear."
So, to keep my hand in the game, here are a few things running through my head, or that I'm working on, or that I'll be doing soon.
From the blog
Posted 2008-11-17
Zend Framework 1.7.0 Released
Today, we released Zend Framework 1.7.0. This release features AMF support, JQuery support, and Twitter support, among numerous other offerings.
For this particular release, we tried very hard to leverage the community. The majority of new features present in 1.7.0 are from community proposals, or were primarily driven by community contributors. For me, this represents a milestone: ZF is now at a stage where fewer and fewer core components are necessary, and the community is able to build off it and add extra value to the project.
From the blog
Posted 2008-10-21
Vimgrep and Vim Project
Chris Hartjes today was on a quest for a "find in project" feature for Vim. "Find in Project" was a feature of Textmate that he'd grown accustomed to and was having trouble finding an equivalent for.
The funny thing is that Textmate is a newcomer, and, of course, vim has had such a feature for years. The thing to remember with vim, of course, is its unix roots; typically if you know the unix command for doing something, you can find what you need in vim. In this case, the key is the vimgrep plugin, which ships in the standard vim distribution.
From the blog
Posted 2008-09-27
Pastebin app updates
I've been getting a lot of interest in my Pastebin demo app — partly by those wanting to play with Dojo+ZF, partly by those just interested in the application.
I'm constantly trying to improve the application. I've done one webinar and one UnCon session showcasing it, and will be presenting it at Dojo Develper Day in Boston this Monday as well as at php|works later this fall, and want to keep the materials up-to-date and freely available. To this end, I've created a Github repository so you can track the latest developments, as well as pull custom tarballs:
All patches and feedback are welcome!
From the blog
Posted 2008-09-25
ZendCon08 Wrapup
I'm a bit late on my ZendCon'08 wrapup; the conference left me both exhausted and with a backlog of email and work that has consumed me since it ended. However, this, too, is good, as it has given me time to reflect… and to finally get my slides up on SlideShare.
ZendCon was alternately exhausting, rewarding, educational, fruitful, infurating, and ultimately wonderful. I've been to every single ZendCon so far — I started at Zend a scant month before the inaugural event — and have spoken at each. My first time speaking was a fluke; David Sklar had just started at Ning and had to back out of his "Configuring PHP" tutorial session. Mike Naberezny and I were drafted to take it over, and we had N+1 attendees, where N was the number of speakers. Since that inauspicious beginning, I've gradually taken on more sessions and stuck around to participate in the conference more. I can honestly say that this was the biggest, busiest, and most community focussed ZendCon I can remember.
From the blog
Posted 2008-09-11
Setting up your Zend_Test test suites
Now that Zend_Test has shipped, developers are of course asking, "How do I setup my test suite?" Fortunately, after some discussion with my colleagues and a little experimenting on my one, I can answer that now.
From the blog
Posted 2008-09-09
Pastebin app and conference updates
I have a number of updates and followups, and decided to post them in a single entry.
First off, you may now view my Dojo Webinar online (requires login and registration at zend.com). Attendance was phenomenal, and I've had some really good feedback. If you want to see it live, I'm giving the talk (with revisions!) at the ZendCon UnConference, at Dojo Developer Day Boston later this month, and at php|works in November. I hope to be able to show new functionality at each presentation.
Second, I've completed what I'm calling version 1.0.0 of the pastebin application I demo'd in the webinar. The PHP code is fully unit tested (though I haven't yet delved into using DOH! to test the JS), and incorporates a number of best practices and tips that Pete Higgins from Dojo was kind enough to provide to me. When using a custom build (and I provide a profile for building one), it simply flies.
The pastebin application showcases a number of features besides Dojo:
Zend_Test_PHPUnit
was used to test the application, and Zend_Wildfire
's
FireBug logger and DB profiler are used to provide profiling and debug
information.
Finally, ZendCon is next week! I'll be around, but already have a packed schedule (1 tutorial, 2 regular sessions, an UnCon session, a meet-the-developers session… and that's just what I know about!). I look forward to meeting ZF users and developers, though, so feel free to grab me and introduce yourself.
From the blog
Posted 2008-09-05
Proper Layer files when using Dojo with Zend Framework
During my Dojo and ZF webinar on Wednesday, Pete Higgins of Dojo fame noted that I could do something different and better on one of my slides.
This particular item had to do with how I was consuming custom Dojo build layers within my code. I contacted him afterwards to find out what he suggested, and did a little playing of my own, and discovered some more Dojo and javascript beauty in the process.
From the blog
Posted 2008-09-04
Speaking at php|works
I'm pleased to announce I've been selected to speak at php|works in Atlanta this November.
I'll be presenting my talk on Dojo and Zend Framework, demonstrating how to quickly and easily create rich and dynamic UIs using the various integration points with Dojo functionality provided by Zend Framework.
Looking forward to seeing you in Atlanta in November!
From the blog
Posted 2008-08-29
ZF+Dojo Webinar
I'm giving a webinar on Zend Framework and Dojo Integration this coming Wednesday, 3 Sept 2008.
I'm particularly excited about this webinar, as I've been developing a sample pastebin application to show off a number of features; the webinar will feature some screencasts showing the new code in action, and promises to be much more dynamic than my typical "bullet point and code" presentations.
I'm also going to show some techniques to use when developing with ZF+Dojo, including how to create custom builds once you're ready to deploy your application (and why you want to do so).
From the blog
Posted 2008-08-28
Using dijit.Editor with Zend Framework
We're getting ready to release Zend Framework 1.6.0. However, one important
Dijit had to be omitted from the release as I was not able to get it working in
time: dijit.Editor
.
This dijit is important as it provides an out-of-the-box WYSIWYG editor that you can use with your forms. Unfortunately, actually using it with forms is pretty tricky — Dojo actually ends up storing content outside the form, which means you need to create a handler that pulls the content into a hidden element when saving.
I have created an implementation, however, that you can start using now, and
I'm posting it below. It includes both a view helper for displaying it, as well
as a form element for use with Zend_Form
.
From the blog
Posted 2008-08-27
Speaking at ZendCon 2008
I'll be speaking at ZendCon again this year, and have a four-course meal of sessions to deliver:
-
Best Practices of PHP Development: Mike Naberezny and I are teaming up for the fourth year running to deliver a tutorial session. While the session topic stays the same, he and I have each been developing a number of new practices over the past year that we look forward to presenting, including new work with PHPUnit for functional testing of your applications.
-
Getting Started with Zend Framework: This will build off our Quick Start, providing background on ZF as well as the basic tools and information needed to get your first ZF application up and running. I also hope to demonstrate how the current preview of
Zend_Tool
can simplify this dramatically. -
Zend_Layout and Zend_Form: This session will show off features of
Zend_Layout
andZend_Form
. (Note: the subject matter may change.) -
UnCon: Rich UIs and Easy XHR with Dojo and Zend Framework: For those unable to attend my webinar next week, or who simply want to see this in person, I'll be presenting my Dojo and Zend Framework talk during an UnCon session. I have developed a simple app to showcase various features of the Dojo/ZF integration, and to show how easy it is to quickly develop and then scale applications that have great, dynamic interfaces.
Looking forward to seeing you in California in September!
From the blog
Posted 2008-08-11
Zend Framework 1.6.0 Preview, or, PHP 4 is Dead
PHP 4 officially died Friday. I started programming PHP with release candidates of 4.0.0 — which simultaneously introduced me to the GNU C compiler and toolset. My first official job using PHP was at a shop that was using PHP 3, and considering the costs of upgrading to PHP 4 — which clearly offerred many benefits over its predecessor. I switched to PHP 5 as soon as the first official release was made four years ago — the pains of reference handling with objects, the introduction of a unified constructor, first-class support for overloading, and SimpleXML won me over immediately, and I've never looked back. Goodbye, PHP 4; long live PHP!
I'm celebrating with the second release candidate of Zend Framework 1.6.0, which should drop today. There are a ton of new features available that I'm really excited about. I'm not going to go into implementation details here, but instead catalogue some of the larger and more interesting changes that are part of the release.
From the blog
Posted 2008-06-30
Testing Zend Framework MVC Applications
Since I originally started hacking on the Zend Framework MVC in the fall of 2006, I've been touting the fact that you can test ZF MVC projects by utilizing the Request and Response objects; indeed, this is what I actually did to test the Front Controller and Dispatcher. However, until recently, there was never an easy way to do so in your userland projects; the default request and response objects make it difficult to easily and quickly setup tests, and the methods introduced into the front controller to make it testable are largely undocumented.
So, one of my ongoing projects the past few months has been to create an infrastructure for functional testing of ZF projects using PHPUnit. This past weekend, I made the final commits that make this functionality feature complete.
The new functionality provides several facets:
- Stub test case classes for the HTTP versions of our Request and Response objects, containing methods for setting up the request environment (including setting GET, POST, and COOKIE parameters, HTTP request headers, etc).
-
Zend_Dom_Query
, a class for using CSS selectors (and XPath) to query (X)HTML and XML documents. - PHPUnit constraints that consume
Zend_Dom_Query
and the Response object to make their comparisons. - A specialized PHPUnit test case that contains functionality for bootstrapping an MVC application, dispatching requests, and a variety of assertions that utilize the above constraints and objects.
From the blog
Posted 2008-06-30
Migrating OOP Libraries and Frameworks to PHP 5.3
With PHP 5.3 coming up on the horizon, I'm of course looking forward to using namespaces. Let's be honest, who wants to write the following line?
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
when the more succinct:
$viewRenderer = HelperBroker::getStaticHelper('viewRenderer');
could be used? (Assuming you've executed 'use Zend::Controller::Action;'
somewhere earlier…)
However, while namespaces will hopefully lead to more readable code, particularly code in libraries and frameworks, PHP developers will finally need to start thinking about sane standards for abstract classes and interfaces.
From the blog
Posted 2008-06-20
phpwomen at DPC08
So, one thing I forgot to mention in my DPC08 wrapup was my involvement with the phpwomen booth. Lig emailed me some months in advance asking if I'd be an official "booth babe" while at the conference — basically wearing a T-shirt to show my support of the movement, and answering any questions that others might have regarding it. While I haven't been particularly active with phpwomen, I of course agreed.
From the blog
Posted 2008-06-20
DPC08 Wrapup
Last Friday and Saturday I spent at the Dutch PHP Conference, hosted by Ibuildings. Unfortunately, I had very little time to blog while there. I'd prepared my outlines and basic slides before heading to the conference, but had a large number of screenshots and images to prepare that kept me up until the wee hours of the morning each day. In addition, the conference was extremely well organized — which meant that any time not spent speaking was spent interacting with attendees or other speakers — never a bad thing!
From the blog
Posted 2008-05-27
Zend Framework/Dojo Integration QA Slides
We had our Zend Framework/Dojo integration QA today. Aside from some connectivity issues at the beginning of the presentation, things went smoothly, and there were some good questions.
A number of people reported missing the slides or that the slides were not advancing. I'm posting them here; they will also be available on the Zend.com webinars page later this week.
Update: For those who want to view online, you can now do so at SlideShare.
From the blog
Posted 2008-05-22
ZF Subversion Reorganization
If you've found that your SVN checkouts or svn:externals
of Zend Framework are not working currently, then you missed the announcements on fw-general
and #zftalk
; I've just completed a Subversion Reorganization that is part of our new proposal process and 'Extras' offering. Please follow the link for details on how to update your installs.
From the blog
Posted 2008-05-21
Zend Framework Dojo Integration
I'm pleased to announce that Zend Framework will be partnering with Dojo Toolkit to deliver out-of-the-box Ajax and rich user interfaces for sites developed in Zend Framework.
First off, for those ZF users who are using other Javascript toolkits: Zend Framework will continue to be basically JS toolkit agnostic. You will still be able to use whatever toolkit you want with ZF applications. ZF will simply be shipping Dojo so that users have a toolkit by default. Several points of integration have been defined, and my hope is that these can be used as a blueprint for community contributions relating to other javascript frameworks. In the meantime, developers choosing to use Dojo will have a rich set of components and integration points to work with.
The integration points we have defined for our initial release are as follows:
From the blog
Posted 2008-05-18
Speaking at the Dutch PHP Conference
I've known for some time, but was reluctant to blog about it until the plane tickets were purchased and in hand: I've been invited to speak at the Dutch PHP Conference this coming June:
I'll be presenting two separate sessions: an all day tutorial on 13 June 2008 covering Zend Framework, and a regular session on 14 June 2008 covering Best Practices for PHP development, which will focus on how to utilize Zend Framework coding standards and methodologies to help deliver efficient, high quality code for your organization.
I'm looking forward to meeting old and new friends alike at the conference!
From the blog
Posted 2008-05-16
Server Upgrades... lost entries...
My good friend, Rob, hosts my site for me, in return for helping with server maintenance. After being on Gentoo for the past three years, though, we decided it was time to switch to something a little easier to maintain, so last night we wiped the system partitions and installed Ubuntu server.
I'll say this: the setup is much faster! However, we had a few gotchas that surprised us — it didn't setup our RAID array out-of-the-box, which led to a good hour of frustration as we tried to verify that the install wouldn't wipe it, and then to verify that we could re-assemble it. (We succeeded.) Additionally, we second-guessed a few things we shouldn't have, which led to needing to back out and reconfigure. But what was over a 12 hour install with Gentoo we accomplished in a matter of a few hours with Ubuntu server — so it was a huge success that way.
Unfortunately, our mysqldump of all databases… wasn't, a fact we discovered only after importing it into the new system. I ended up losing my blog database and PEAR channel database. Fortunately, the PEAR channel has not changed at all in the past year, so we had an old backup that worked, and I had a snapshot of my blog database from three weeks ago I was able to use. As a result, there are a few missing entries, but for the most part, all works. If you commented on one of those missing entries, my apologies.
Now that the install is done, I'm also finalizing some design changes to my blog — it's time to leave the black and white for more colorful grounds. Look for a revamp in the coming weeks!
From the blog
Posted 2008-05-05
Form Decorators Tutorial posted
As a continuing part of my MVC series, I've posted a new article on Form Decorators up on the DevZone.
I'm hoping this will be the definitive guide to using form decorators. I cover the design decisions behind them, basics of operation, how to customize output by mixing and matching standard decorators, and how to create your own custom decorators. Among the examples are how to create a table-based layout for your forms (instead of the dynamic list layout used by default), and how to use a View Script as your form decorator in order to have full control over your form layout.
So, if you've been playing with Zend_Form
and having trouble wrapping your
head around decorators, give it a read!
From the blog
Posted 2008-04-28
Zend Framework Q&A Session
With 1.0 and 1.5 of Zend Framework now released, there are a lot of questions flying around -- what will we do next, what components to expect, what are some of the best practices, etc. So, we're going to have an open Question and Answer Session webinar, with all of us on the internal team.
If you have a question you want answered, please be kind enough to submit your question in advance, so we have time to actually think about it (though you can always broadside us during the webinar).
Sign up in advance so you don't miss out!
From the blog
Posted 2008-04-28
View Helpers Tutorial on DevZone
I have another tutorial in my Zend Framework MVC series up on DevZone today, this time on View Helpers. If you're curious on how to create view helpers, override the standard view helpers, or how some of the standard view helpers such as partials and placeholders work, give it a read!
From the blog
Posted 2008-04-14
ZF Plugins Tutorial on DevZone
I'm doing a series of articles on various Zend Framework MVC topics for the Zend Developer Zone. Last week, I covered Action Helpers. This week, I cover Front Controller Plugins. If you've ever been mystified by or curious about this subject, head on over and give it a read!
From the blog
Posted 2008-04-07
Action Helpers in ZF
I've posted a new article on Action Helpers in Zend Framework's MVC on the Zend Developer Zone. If you've ever wanted more information on these, follow the link.
From the blog
Posted 2008-04-04
DHH on PHP
Somebody on Twitter pointed this out, and I thought I'd spread the word: DHH of Rails fame has posted a nice, short, and very interesting thought on "The immediacy of PHP".
I've been delving a little into Rails lately myself, and what I find is: use the right tool for the job. For green-field, self-hosted projects, Rails is not a bad choice, and offers a very easy way to get your application up and running quickly. But due to the fact that PHP was built for the web, there are any number of tasks that are simpler and faster to accomplish using it. Evaluate your needs carefully, and choose the tool that best addresses them.
It's nice to see leaders of projects like Rails having this same attitude. It's a breath of fresh air in the competitive market of web development frameworks.
From the blog
Posted 2008-04-03
Zend Framework 1.5 Podcast
Cal has released a new PHP Abstract podcast today on the Zend Developer Zone, an interview with Wil Sinclair, the project manager for Zend Framework, and Brad Cottel, Zend's product Evangelist. In it, they talk quite a bit about the work I've done on Zend Form, and also a lot about the proposal process.
If you're interested in the new 1.5 features, or how the proposal process works and who contributes to the community, give it a listen!
From the blog
Posted 2008-03-28
Dojo 1.1.0 Released
Dojo announced today the availability of 1.1.0.
I've been toying with Dojo off-and-on for almost a year now. It's the most framework-y of the various JS toolkits I've tried, and I particularly appreciate its modularity. (That said, it can lead to a lot of HTTP requests to your site if you don't create a targetted bundle with the modules you need.)
The 1.1.0 release has me pretty excited, as it finally is doing something most
other JS frameworks have been doing for some time: its XHR requests now send
the X-Requested-With: XMLHttpRequest
header, which allows it to conform to
the isXmlHttpRequest()
method in Zend Framework's request object. This makes
it much easier to provide a standard mechanism in your server-side code for
detecting AJAX requests, allowing context switching to be automated.
From the blog
Posted 2008-03-28
Login and Authentication with Zend Framework
Update: this article is now available in French, courtesy of Frédéric Blanc.
I've fielded a number of questions from people wanting to know how to handle authentication and identity persistence in Zend Framework. The typical issue is that they're unsure how to combine:
- An authentication adapter
- A login form
- A controller for login/logout actions
- Checking for an authenticated user in subsequent requests
It's not terribly difficult, but it does require knowing how the various pieces
of the MVC fit together, and how to use Zend_Auth
. Let's take a look.
From the blog
Posted 2008-03-22
Vim Productivity Tips for PHP Developers
I use Vim for all my editing needs — TODO lists, email, presentation outlines, coding in any language… everything. So, I thought I'd start sharing some of my vim habits and tools with others, particularly those that pertain to using Vim with PHP.
From the blog
Posted 2008-03-18
Using Zend_View Placeholders to Your Advantage
Somebody asked for some examples of how I use the headLink()
, headScript()
,
and other placeholder helpers, so I thought I'd take a crack at that today.
First off, let's look at what these helpers do. Each are concrete instances of a placeholder. In Zend Framework, placeholders are used for a number of purposes:
- Doctype awareness
- Aggregation and formatting of aggregated content
- Capturing content
- Persistence of content between view scripts and layout scripts
Let's look at these in detail.
From the blog
Posted 2008-03-16
Zend Framework 1.5 is on its way!
As many know, Zend Framework 1.5.0 is almost ready for release… heck, it might even be released by the time you read this. There are a ton of new features worth looking into, but I'll list some of my own favorites here - the ones I've been either working on or using.
From the blog
Posted 2008-03-08
Submitting Bug Reports
Full disclosure: I am employed by Zend to program Zend Framework. That said, the following is all my opinion, and is based on my experiences with Zend Framework, as well as answering questions on a variety of mailing lists and with other OSS projects (PEAR, Solar, and Cgiapp in particular).
One of my biggest pet peeves in the OSS world is vague bug/issue reports and feature requests. I cannot count the number of times I've seen a report similar to the following:
<Feature X>
doesn't work; you need to fix it now!
If such a report comes in on an issue tracker, it's invariably marked critical and high priority.
What bothers me about it? Simply this: it gives those responsible for maintaining Feature X absolutely no information to work on: what result they received, what was expected, or how exactly they were using the feature. The reviewer now has to go into one or more cycles with the reporter fishing for that information — wasting everyone's time and energy.
Only slightly better are these reports:
<Feature X>
doesn't work — I keep getting<Result X>
from it, which is incorrect.
At least this tells the reviewers what they reporter is receiving… but it doesn't tell them how they got there, or what they're expecting.
So, the following should be your mantra when reporting issues or making feature requests:
- What is the minimum code necessary to reproduce the issue or show the desired API?
- What is the expected result?
- What is the actual result?
From the blog
Posted 2008-03-03
Zend_Form Webinar Wednesday
Just an FYI for anyone interested: I'll be performing a webinar for this week's Zend Wednesday Webinar series on Zend_Form. You can get details on the webinar and how to register for it at the Zend_Form webinar information page.
I'll be covering the design of Zend_Form
, the basic usage and various classes
and plugins available, and internationalization of your forms. Please join me
Wednesday at noon EST!
From the blog
Posted 2008-02-08
Zend_Form Advanced Features
I've been working on Zend_Form for the past few weeks, and it's nearing release readiness. There are a number of features that Cal didn't cover in his DevZone coverage (in part because some of them weren't yet complete) that I'd like to showcase, including:
- Internationalization
- Element grouping for display and logistical purposes
- Array support
This post will serve primarily as a high-level overview of some of these features; if you're looking for more in-depth coverage, please review the unit tests. :-)
From the blog
Posted 2008-02-07
Backwards Compatibility
Ivo already pointed this out, but I want to point it out again: Boy Baukema writes a very nice entry regarding backwards compatibility on the ibuildings.nl corporate blog.
Backwards compatibility (BC) is a tricky thing to support, even when you strive hard to, as Boy puts it, "think hard about your API" prior to release. Somebody will always come along and point out ways it could have been done better or ways it could be improved. I've had to wrestle with these issues a ton since joining the Zend Framework team, and while it often feels like the wrong thing to do to tell somebody, "too little, too late" when they have genuinely good feedback for you, its often in the best interest of the many users already using a component.
I had the pleasure of meeting Boy last year when visiting the ibuildings.nl offices, and he's got a good head on his shoulders. He does a nice job outlining the issues and a number of approaches to BC; if you develop a project for public consumption, you should definitely head over and read what he has to say.
From the blog
Posted 2008-01-30
Burlington PHP Tonight
The Burlington PHP User Group is having another meeting tonight at 5:30pm at Brown & Jenkins Coffee Roasters. From the announcement:
Bradley Holt will be giving a presentation on developing a web application using Zend Framework. Bradley Holt is founder and web developer for Found Line, a local design and development studio which has used Zend Framework in several recent projects. He also works as a software developer for a local non-profit. Before starting Found Line he worked as computer trainer teaching a variety of subjects including Java/JSP, ASP.NET, and PHP
Visit the meeting page for details on location and RSVPs. If you're in the Burlington, VT, area, we'd love to see you there!
From the blog
Posted 2008-01-25
Apache HOSTNAME on Clusters
In an effort to debug issues on a cluster, I was trying to determine which machine on the cluster was causing the issue. My idea was that I could insert a header token identifying the server.
My first idea was to add the directive Header add X-Server-Ip "%{SERVER\_ADDR}e
in my httpd.conf
. However, due to the nature of our load
balancer, Apache was somehow resolving this to the load balancer IP address on
all machines of the cluster — which was really, really not useful.
I finally stumbled on a good solution, however: you can set environment
variables in apachectl
, and then pass them into the Apache environment using the
PassEnv
directive from mod_env
; once that's done, you can use the environment
variable anywhere.
In my apachectl
, I added the line export HOSTNAME=\
hostname``. Then, in my
httpd.conf
, I added first the line PassEnv HOSTNAME
, followed by the
directive Header add X-Server-Name "%{HOSTNAME}e"
. Voilá! I now had the
hostname in the header, which gave me the information I needed for debugging.
From the blog
Posted 2008-01-01
2007 Retrospective
2007 was a busy year, both personally and professionally. I won't go into the personal too much, because, well, it's personal, and some of the details are simply inappropriate for blogging material.
Here's the short version:
- One trip to Belgium and The Netherlands.
- Two trips to Israel.
- Two trips to Atlanta, GA (not counting the return trip from Europe, when I was stranded for a day due to storms in the Northeast).
- Three different user groups attended, with three presentations.
- One major Zend Framework release
- One PEAR release.
- One podcast.
- One webinar.
- One book published.
- One conference attended.
What follows is my month-by-month breakdown:
From the blog
Posted 2007-12-20
Sqlite Version Mismatch
I ran into an issue recently in testing a site where PDO_SQLITE
was claiming
that it could not read my PDO database files. The only recent change I'd had was
that I'd installed a new version of PHP, and hence a new version of PDO_SQLITE
.
Searching the web (we're not supposed to say googling or googled anymore,
remember ;-)), I found that the issue was that the version of sqlite compiled
into my PHP install was not compatible with the version I used to create the
databases in the first place. Never mind that they're only a micro version or
two different.
So, I was left with a conundrum: I needed to create files compatible with my
PDO_SQLITE
install, but my CLI sqlite tool was incompatible. And if I used
PDO_SQLITE
to create the db file, I'd lose my data, right?
Wrong. And here's what you can do should you find yourself in the same situation sometime.
From the blog
Posted 2007-12-19
Zend_Layout and Zend_View Enhanced components now in core
I'm pleased to announce that the Zend_View Enhanced and Zend_Layout components are now in the Zend Framework core. With these two components, you can now create some truly complex views for your application with relative ease.
The two components tackle several view related tasks:
- Layouts, or Two Step Views
- Partials (view fragment scripts with their own variable scope)
- Placeholders (store data and/or markup for later retrieval)
- Actions (dispatch a controller action)
From the blog
Posted 2007-12-02
Burlington PHP Users Group, December
I've been considering for a good six months trying to organize a PHP Users Group for the Burlington, VT, area. When we first moved to Vermont, I was surprised (and excited) by the number of PHP shops (which at the time I saw as job potential, as I was looking for work), and actually walked my resume around to a half-dozen or so. The area has a ton of PHP developers, and it only makes sense to have a UG where we can exchange tips and tricks of the trade.
Then, about six weeks ago, I mentioned this to my friend Rob. He did what I should have done all along, and googled for an existing group — and found one!
The Burlington, VT PHP Users Group has been around since November of 2005 on Google Groups, but we're having our inaugural meeting this coming Wednesday, 5 December 2007. I'll be speaking at this first meeting on Zend Framework's MVC components
If you're in the Burlington area this Wednesday, you should stop by. For more details, visit the event page, and don't forget to RSVP.
From the blog
Posted 2007-10-30
PHP Anthology, 2nd Edition is out
Well, it's now official: The PHP Anthology, 2nd Edition is finally out, and, as you'll see if you follow the link, I'm listed as an author on it. :-) It's a pleasant surprise to see it out — I finished my chapters back in January, and had almost forgotten about it.
From the blog
Posted 2007-10-11
ZendCon is over at last
ZendCon '07 is finally over, the dust has settled, and I finally find myself with some time alone… practically the first I've had since Sunday. The week was fantastic, and I had many good conversations and brainstorming sessions. Oh, and I ended up giving three different sessions, so it's time for links to slides and materials:
- Best Practices of PHP Development. Sebastian, Mike, and I presented a full-day tutorial on PHP development best practices, focussing primarily on testing and testing strategies, but also covering coding standards, usage of SCM tools, and deployment. There were a ton of questions from the attendees, and Sebastian even whipped out some extra slides at the end showing new and little-known features of PHPUnit. Basically, reading the slides won't really indicate what we covered, but is more of a general outline. It was an honor and pleasure to work with Sebastian and Mike on this, and I hope we can do it again in the future some time.
- Zend Framework MVC Quick Start. This was basically the same session I did in my webinar a couple weeks ago, with a few corrections and a small demonstration. Cal put me on directly following Terry Chay, in the largest of the four session rooms — the one where all the keynotes occurred — talk about intimidating! Amazingly, the session was really well attended — others I talked to estimate between 100 and 150 people showed up. The most amazing part, though, was that when I asked how many people knew what 'MVC' was, I don't think there was a single person who didn't raise their hand — definitely a sign of how well accepted the pattern now is in PHP.
- AJAX-Enabling Your Zend Framework Controllers. I did this talk for the Unconference, mainly because its a topic I've been interested in and wanted to present. In it, I detailed how to ajax-enable an application through some easy tricks with Action and View Helpers and using JS to decorate your existing application. The reference app I used was a pastebin, and I've got code for both Dojo and Prototype flavors available:
The two highlight keynote speakers, for me, were definitely Joel Spolsky and Cory Doctorow. Neither spoke about PHP, but both spoke about topics that PHP developers should take to heart. Perhaps I'll elaborate on those in another post.
Another bonus for me was the number of old and new friends alike I got to see — I had many good conversations with Paul M. Jones, Nate Abele, Ivo Jansch, and Ralph Schindler, and opportunities to finally meet fellow co-author Lig Turmelle, Ben Ramsey, Chris Shifflet (dude, we've been to four conferences together, and never yet met!), and many, many others. I was also overwhelmed by the number of Zend Framework users who sought me out either to ask me questions or simply thank me and the others on the team for the project; I'm deeply honored that I can work on a project that affects so many developers.
And now for some down time to recuperate…
From the blog
Posted 2007-10-02
oh, yeah, zendcon...
I don't know why I haven't blogged this sooner, but, yes, I'll be speaking once again at ZendCon:
I'll be presenting a number of times:
- On Monday, I join Sebastian Bergmann and Mike Naberezny in a full-day tutorial session on PHP Development Best Practices and Unit Testing. This expands on what Mike and I did last year, and will more heavily emphasize the role of testing in the development process — arguably the most important best practice you can adopt.
- On Tuesday monrning, I'll present a Zend Framework MVC Quick Start. This talk is based on a webinar I recently gave for Zend, and covers the various pieces of the MVC layer in Zend Framework.
- Tuesday evening, I'll present an Unconference session on Ajax-enabling your Zend Framework controllers. I don't know yet if I'll need the whole hour, but I can probably fill it up with some examples of decorating your apps with AJAX.
Looking forward to seeing you all there!
From the blog
Posted 2007-09-26
Zend Framework MVC Webinar posted
Last Wednesday, I presented a webinar for Zend entitled "MVC applications with Zend Framework". We had more than 50 attendees, most of whom stayed on the whole time. For those of you who attended, thanks for the great questions and comments.
If you would like to view the webinar, download the slides, or download the example code (a hello world app), visit the Zend.com Webinar page and look for the presentation; as of today, it's the first one on the list, but that will change as more webinars are presented.
From the blog
Posted 2007-09-14
NYPHP Zend Framework Presentation
This past Wednesday, Zend's Chief Marketing Officer, Mark de Visser, and myself joined the NYPHP group for a special event meeting. Mark presented information on Zend's development stack and toolset (which I entirely missed, as I was still in transit), and I came in to give an overview of Zend Framework.
There were some great questions, and nice discussions following the event. If you live in New York and do PHP for a living, and haven't attended, you should; if you're ever visiting the area, see if you can attend a meeting!
Here are the slides.
They're done using S5, a browser-based
slideshow system. Simply unzip and double-click on index.html
to start viewing.
From the blog
Posted 2007-07-05
File_Fortune refactored
Over the past few evenings, I've refactored
File_Fortune to
have it implement Iterator
, Countable
, and ArrayAccess
— basically allowing it
to act like an array for most intents and purposes. As a result, I've eliminated
the need for the File_Fortune_Writer
package, and greatly simplified the
usage.
(Note: sure, File_Fortune
may not be that big of a deal, but over 1000
downloads in the past two years indicates somebody is using it. Plus, it
powers the random quotes on the family website. :-) )
As some examples:
require_once 'File/Fortune.php';
// Initialize and point it to a directory of fortunes
$fortunes = new File_Fortune('/path/to/fortunedir');
// Retrieve a random fortune
// (works with either a directory or a single fortune file)
echo $fortunes->getRandom();
// Set to a specific fortune file:
$fortunes->setFile('myfortunes');
// Loop through and print all fortunes
foreach ($fortunes as $fortune) {
echo str_repeat('-', 72), "\n", $fortune, "\n\n";
}
// Hmmm.. let's change one:
$fortunes[7] = "I never really liked that fortune anyways.";
// No need to explicitly save, as it's done during __destruct(),
// but if you really want to:
$fortunes->save();
// Let's add a new fortune:
$fortunes->add('This is a shiny new fortune!');
// and now we'll verify it exists:
$index = count($fortunes) - 1;
echo $fortunes[$index];
All-in-all, it's a much better interface. Lesson learned: when porting code from other languages, it pays to take some time and determine if there might be a better API in your own.
In upcoming releases, I hope to modify the backend to use PHP's Streams API instead of direct file access, and also to allow providing a list of fortune files explicitly. After that, I should be ready for the initial stable release.
Update (2007-07-10): fixed parse error in examples
From the blog
Posted 2007-05-20
Globals, continued
Update: Sara has pointed out a flaw in my last case. The file
loadFileWithGlobals.php
was incorrectly loading the wrong file — it should
be loading withGlobals2.php
(updated now). When it does, access to baz2
works as it should.
As I note to in my comment, however, I stand by my original rant: relying on globals for your applications is a bad practice, as it makes them difficult to integrate with other applications later. Developers using your application should not need to hunt down exactly when a global is first declared and explicitly push it into the global scope in order to get that application to integrate with others. Use other means, such as singletons or registries, to persist configuration within your applications.
In my last entry, I evidently greatly simplified the issue to the point that my example actually didn't display the behaviour I had observed. I'm going to show a more detailed example that shows exactly the behaviour that was causing issues for me.
First off, this has specifically to do with including files from within functions or class methods that then call on other files that define values in the global scope. In the original example, I show an action controller method that includes the serendipity bootstrap file, which in turn loads a configuration file that sets a multi-dimensional array variable in the global scope. Without first defining the variable in the global scope, this method of running serendipity fails.
Now, for the examples.
From the blog
Posted 2007-05-19
PHP globals for the OOP developer
Update: I evidently simplified the issue too much, and have had several
people rightly comment on the bogosity of the issue. However, there are still
situations where $GLOBALS
does not act as expected, and I outline these in
my next entry.
In my previous entry, I ranted about the use of globals in popular PHP applications, and how they make embedding said applications difficult. I develop using object-oriented practices, and can honestly say I can't recall ever having slung a global variable around in my own code. Globals seem hackish to me, and as a result, trying to get applications that use them to behave correctly has been a challenge.
One of the applications I had in mind was Serendipity, the software that powers this blog. I was attempting to create a Zend Framework action controller that wraps my s9y instance so that I can do things such as apply ACLs from my website to selected entries, as well as pull the sitewide skeleton out from s9y so that I only have to maintain one version of it (I had one version for s9y, and another for my own content featured on the site (resume, contact form, etc.).
I tried importing the various config files into my action method prior to
invoking the actual s9y bootstrap, but no dice. I also tried modifying the s9y
config files to use the notation $GLOBALS['serendipity']
around the
serendipity configuration variables (s9y uses a single multi-dimensional array
for all configuration options). This didn't work, either; s9y functions that
called global $serendipity
were still getting a null value.
So, I did a little closer reading in the manual section on predefined
variables, I discovered
something interesting in the description of $GLOBALS
(emphasis mine):
Contains a reference to every variable which is currently available within the global scope of the script.
Interestingly, the section on variable scope didn't make this distinction at
all. Basically, if the variable you reference via $GLOBALS
does not already
exist, assigning it does nothing. It doesn't even raise a notice. It just
silently goes ahead, leaving you thinking you set a new global variable, but in
fact, you cannot assign new globals via $GLOBALS
; you can only modify
existing variables in the global scope.
So, I got around the issue by putting this in my front controller bootstrap:
$serendipity = null;
After that, I was able to create a wrapper action controller for s9y very easily:
/** Zend_Controller_Action */
require_once 'Zend/Controller/Action.php';
/**
* Serendipity integration
*
* @uses Zend_Controller_Action
*/
class S9y_IndexController extends Zend_Controller_Action
{
public function init()
{
// New ViewRenderer helper in ZF incubator; telling it not
// to autorender a view script when done
$this->_helper->viewRenderer->initView(null, null, array('noRender' => true));
}
public function indexAction()
{
global $serendipity;
chdir($_SERVER['DOCUMENT_ROOT'] . '/path/to/s9y');
include './index.php';
chdir($_SERVER['DOCUMENT_ROOT']);
}
}
Note that I don't do any output buffering; this is because the ZF dispatcher takes care of that for me. All I need to do is execute the s9y bootstrap.
So, the lesson to learn from all this: if you need to wrap an application that uses globals, find out what all of them are, and declare them in the global namespace — just setting them to null is enough — in your application bootstrap.
From the blog
Posted 2007-05-07
Start Writing Embeddable Applications
Clay Loveless wrote last year an article entitled Stop Writing Loner Applications in which he ranted about all the monolithic applications that act like they're the only kid on the block when it comes to user authentication. Basically, if you want to create a site that utilizes several third-party, off-the-shelf PHP apps (say, a forum, a blog, and a wiki), getting a shared authentication to work between them can be more than a little painful.
I've hit a similar problem repeatedly the past couple months: most of these apps simply are not embeddable, at least not without modifying the source.
"Why embed?" you ask. Simple: if I'm creating a site that has one or two of these applications, but also my (or my company's) own custom functionality, I may want to ensure that certain elements are present on all pages, or that I can control some of the content in all pages: a unified header and footer, ability to inject statistic tracking javascript, etc.
The predominant attitudes are either, "Don't embed our app, embed your app in ours," or "Just modify the templates." Neither of these solutions is acceptable.
From the blog
Posted 2007-03-05
BostonPHP Framework Presentations
Last Wednesday evening, I had the honor of presenting Zend Framework to BostonPHP, as part of an ongoing series they're holding on PHP frameworks; Horde was also represented as part of the evening's fare. It was the first time I've attended a UG, so I got the double whammy of that and being a presenter. Oh, make it a triple whammy — Boston is a 3+ hour drive from the Burlington, VT area I now call home.
All in all, the presentations went quite well. It was particularly fun to see what my friend Chuck Hagenbuch has been up to with Horde; his description and demonstration of RDO, or "Rampage Data Objects" was very cool (I really like the idea of "Horde on the Rampage" -- it's a very funny image for me), as was his working demonstration of using WebDAV to pull results via PHP in the Mac Finder.
A lot of people are interested in and working regularly with Zend Framework, at
least based on the questions I was receiving. Attendees ranged from the "what
does Zend do" category to the "We're standardizing on Zend Framework and use
Zend products throughout our stack" category. The bulk of the comments I
received were either of the flavor "I really like what I'm seeing" or wondering
how mature/stable Zend_Db
is. Unfortunately, at the time I was preparing the
slides, there were many features in Zend_Db
that can cause headaches, and I
took some time to point these out; however most of these are soon to be
history, due to the work of Bill Karwin and Simon Mundy, who are pushing to get
a stable, usable DB abstraction layer out the door for ZF 1.0.
During the joint question and answer session, I started getting some particularly tough, pointed questions from one member of the group. I wasn't getting particularly rattled, but the moderator, Seth, decided to intervene and introduce me to my interlocutor — none other than Nate Abele of the CakePHP project. In the end, he joined Chuck and myself at the front of the room, and we had a nice panel discussing how the various frameworks handle different issues.
If you're ever in the Boston area, check to see if BostonPHP is having a meeting; it's a fun group.
My slides are now available; I've revised them slightly to fix some syntactical errors I noticed during the presentation, but otherwise they're what I presented. You may also want to check out the podcast.
From the blog
Posted 2007-02-05
Extending Singletons
This morning, I was wondering about how to extend a singleton class such that
you could retrieve the new class when retrieving the singleton later. In
particular, Zend_Controller_Front
is a singleton, but what if I want to
extend it later? A number of plugins in the Zend Framework, particularly view
helpers and routing functionality, make use of the singleton; would I need to
alter all of these later so I could make use of the new subclass?
For instance, try the following code:
class My_Controller_Front extends Zend_Controller_Front
{}
$front = My_Controller_Front::getInstance();
You'll get an instance of Zend_Controller_Front
. But if you do the following:
class My_Controller_Front extends Zend_Controller_Front
{
protected static $_instance;
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
}
$front = My_Controller_Front::getInstance();
You'll now get an instance of My_Controller_Front
. However, since
$_instance
is private in Zend_Controller_Front
, calling
Zend_Controller_Front::getInstance()
will still return a
Zend_Controller_Front
instance — not good.
However, if I redefine Zend_Controller_Front::$_instance
as protected, and
have the following:
class My_Controller_Front extends Zend_Controller_Front
{
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
}
$front = My_Controller_Front::getInstance();
Then the any time I call getInstance()
on either My_Controller_Front
or
Zend_Controller_Front
, I get a My_Controller_Front
instance!
So, the takeaway is: if you think a singleton object could ever benefit from extension, define the static property holding the instance as protected, and then, in any extending class, override the method retrieving the instance.
From the blog
Posted 2007-01-31
exuberant ctags with PHP in Vim
One reason I've heard PHP developers use for adopting an IDE when developing is the ability to click on a class or function name and jump to the declaration. Sounds like magic, and it's definitely something I've desired.
One way I get around it is by adopting PEAR coding standards for naming my
classes. Since they define a one-to-one mapping of class name to the file
system (substitute the underscore character (_
) with the directory
separator), I can usually very quickly and easily open a class file,
particularly if I start in the base directory of the project install.
Today, however, I found exuberant ctags, a library which can be used to generate an index file mapping language objects to source files and the line in the source file where they are declared. Contrary to its name, it's not just for the C language; it currently supports 33 different programming languages, including PHP.
I decided to try it out on the Zend Framework core library today. At first run, it was pretty useful. However, it was only mapping classes, and, in addition, only those defined with the single word 'class' — abstract classes and interfaces were entirely left out. So, I looked into the documentation to see if I could change the behaviour.
And, being a Unix program, of course I could. First off, you can add functions to the items it indexes with a simple flag. Additionally, you can use POSIX regular expressions to refine what it searches.
I whipped up the following script to create my tags index:
###!/bin/bash
cd /path/to/framework/library
exec ctags-exuberant -f ~/.vim/mytags/framework \
-h \".php\" -R \
--exclude=\"\.svn\" \
--totals=yes \
--tag-relative=yes \
--PHP-kinds=+cf \
--regex-PHP='/abstract class ([^ ]*)//c/' \
--regex-PHP='/interface ([^ ]*)//c/' \
--regex-PHP='/(public |static |abstract |protected |private )+function ([^ (]*)//f/'
This script creates the tag index in the file $HOME/.vim/mytags/framework
. It
scans for PHP files recursively through the tree, excluding any files found in
a .svn
directory (I'm using a checkout from the subversion repository). The
file paths in the index are created relative to the tags file; this was
important, because if this wasn't provided, vim was unable to jump to the file,
as it couldn't find it. --PHP-kinds=+cf
tells it to index classes and
functions. Next, I've got three regular expressions. The first tells it to
match classes beginning with 'abstract class' as classes. The second tells it
to match interfaces as classes. The last is so that PHP 5 methods, which begin
with a visibility operator, to be matched as functions.
Once the index file is generated (it takes less than a second), all you need to
do in vim is tell it to load it: :set tags=~/.vim/mytags/framework
. At this
point, you can do all sorts of fun stuff. Place the cursor on a class name or
method name, anywhere in it, and hit Ctrl-]
, and you'll jump to the file and
line of its declaration; Ctrl-T
then takes you back. If you change the
invocation to Ctrl-W ]
, it will split the current window and open the
declaration in the new pane. (If you're familiar with how help works with Vim,
this should seem pretty familiar.)
One more reason to stick with Vim for your PHP editing needs. :-)
From the blog
Posted 2007-01-31
PHP decoding of Javascript encodeURIComponent values
Recently, I was having some issues with a site that was attempting to use UTF-8 in order to support multiple languages. Basically, you could enter UTF-8 characters — for instance, characters with umlauts — but they weren't going through to the web services or database correctly. After more debugging, I discovered that when I turned off javascript on the site, and used the degradable interface to submit the form via plain old HTTP, everything worked fine — which meant the issue was with how we were sending the data via XHR.
We were using Prototype, and in particular, POSTing
data back to our site — which meant that the UI designer was using
Form.serialize()
to encode the data for transmission. This in turn uses the
javascript function encodeURIComponent()
to do its dirty work.
I tried a ton of things in PHP to decode this to UTF-8, before stumbling on a solution written in Perl. Basically, the solution uses a regular expression to grab urlencoded hex values out of a string, and then does a double conversion on the value, first to decimal and then to a character. The PHP version looks like this:
$value = preg_replace('/%([0-9a-f]{2})/ie', \"chr(hexdec('\1'))\", $value);
We have a method in our code to detect if the incoming request is via XHR. In
that logic, once XHR is detected, I then pass $_POST
through the following
function:
function utf8Urldecode($value)
{
if (is_array($value)) {
foreach ($key => $val) {
$value[$key] = utf8Urldecode($val);
}
} else {
$value = preg_replace('/%([0-9a-f]{2})/ie', 'chr(hexdec($1))', (string) $value);
}
return $value;
}
This casts all UTF-8 urlencoded values in the $_POST
array back to UTF-8, and
from there we can continue processing as normal.
Man, but I can't wait until PHP 6 comes out and fixes these unicode issues…
From the blog
Posted 2007-01-18
Overloading arrays in PHP 5.2.0
Update: I ran into issues with the ArrayObject
solution, as there was a bug in PHP 5.2.0 (now fixed) with its interaction with empty()
and isset()
when used with the ARRAY_AS_PROPS
flag. I tried a number of fixes, but eventually my friend Mike pointed out something I'd missed: as of PHP 5.1, setting undefined public properties no longer raises an E_STRICT
notice. Knowing this, you can now do the following without raising any errors:
class Foo
{
public function __set($key, $value)
{
$this->$key = $value;
}
}
$foo = new Foo();
$foo->bar = array();
$foo->bar[] = 42;
This is a much simpler solution, performs better, and solves all the issues I was presented. Thanks, Mike!
From the blog
Posted 2007-01-05
svn:externals
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/
-
In the top of your project trunk, execute the following:
$ svn propedit svn:externals .
-
This will open an editor session. In the file opened by your editor, each line indicates a different external svn repo to pull. The first segment of the line is the directory where you want the pull to exist. The last segment is the svn repo URL to pull. You can have an optional middle argument indicating the revision to use. Some examples:
-
Pull framework repo from head:
framework http://framework.zend.com/svn/framework/trunk
- Pull framework repo from revision 2616:
framework -r2616 http://framework.zend.com/svn/framework/trunk
-
-
After saving and exiting, update the repo:
$ svn up
-
Commit changes:
$ svn commit
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!
From the blog
Posted 2006-12-28
Getting XDebug working with PHPUnit for code coverage reports
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:
-
Enable the extension using
zend_extension = /full/path/to/xdebug.so
, not asextension = xdebug.so
, in yourphp.ini
-
Use the setting
xdebug.default_enable = Off
in yourphp.ini
. -
If compiling using pecl or pear, make sure it compiles against the correct PHP; if not, hand compile it using:
$ /path/to/phpize $ ./configure --with-php-config=/path/to/php-config $ make $ make install
For the detailed narrative, read on.
From the blog
Posted 2006-12-07
MVC changes in Zend Framework
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…
From the blog
Posted 2006-11-01
PHP Best Practices
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.
From the blog
Posted 2006-10-15
ZendCon: Best Practices Session
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:
-
Programming Practices
- Coding Standards
- Test Driven Development and Unit Testing
- Project Documentation
-
Tools and Processes
- Software Configuration Management (SCM)
- Collaboration tips and tools
- Deployment
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!
From the blog
Posted 2006-10-15
Zend_XmlRpc_Server
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.
From the blog
Posted 2006-10-09
PHP 5's Reflection API
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.
From the blog
Posted 2006-09-19
Vim 7 code completion
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!
From the blog
Posted 2006-06-23
Benchmarking dynamic function/method calls
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.
From the blog
Posted 2006-06-17
Serendipity upgrade
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!
From the blog
Posted 2006-06-06
Cgiapp2 Tutorial 2: Pluggable Applications
This is the second in a series of Cgiapp2 Tutorials. In this tutorial, I cover creating what I call 'Pluggable Applications', applications that can be distributed and customized to work with other sites.
From the blog
Posted 2006-06-06
The light has not set on PHP
I ran across a blog post entitled "Why the Light Has Gone Out on LAMP" earlier today, and felt compelled to respond.
First, a rant: somehow, this article got posted on Slashdot. I've never heard of the guy who posted it, and some quick googling shows that he's a pythoner. He's simply fueling the language wars, and the slashdot post opened up a huge debate that need not have occurred. I think it was irresponsible of the Slashdot editors to post it.
In the post, the author makes an analogy of using PHP + MySQL as the equivalent of using BASIC, and then uses a quote that claims BASIC "has become the leading cause of brain-damage in proto-hackers."
I'm sorry, but using a language doesn't cause brain damage. And there are many levels to programming. And using Python, Ruby, C, C++, Java, etc., does not automatically make you a better programmer than those using one of "those other languages". You can write crap code in any language. You can also write great code in just about any language.
Programming takes practice; programming well takes a lot of practice. You get better at it by learning more about programming practices, and applying them to your language. Part of programming is also learning when a particular language is suited to a task, and when it isn't. Python works for the web, but it's not particularly suited to it; similarly, you can write web servers in PHP, but that doesn't mean you should.
Stop the language wars already! Stop writing incendiary pieces about a language you don't use regularly or never gained particular proficiency in, and code already!
From the blog
Posted 2006-06-05
Cgiapp2 Tutorial 1: Switch Template Plugins at Will
This is the first in a short series of tutorials showcasing some of the new features of Cgiapp2. In this tutorial, you will see how easy it is to switch template engines in Cgiapp2-based applications.
From the blog
Posted 2006-06-05
Phly Darcs Repository online
A darcs repository browser is now online for the Phly channel.
If you're not familiar with darcs, it's a revision control system, similar to GNU Arch and git; changes are kept as patch sets, and repositories are branched simply by checking them out. This makes darcs repositories very flexible, and incredibly easy to implement. Static binaries are available for most systems, which makes it easy to install on systems to which you have no administrator rights.
A perl CGI script is shipped with darcs, and provides a web-based repository viewer. It utilizes darcs' --xml-output
switch to create XML, which is then transformed using XSLT. However, there are some issues with the script; it is somewhat difficult to customize, and makes many assumptions about your system (location of configuration files, repositories, etc.). To make it more flexible, I ported it to PHP, using Cgiapp2 and its XSLT template plugin and Phly_Config.
I have released this PHP darcs repository browser as Phly_Darcs, which contains both a Model and Controller, as well as example XSLT view templates. It is currently in beta as I'm still developing PHPUnit2 tests for some of the model functionality, as well as debating the ability to add write capabilities (to authenticated users only, of course).
Update: fixed links to internal pages to use absolute urls.
From the blog
Posted 2006-06-04
Cgiapp2 2.0.0 FINAL Released
After several months of testing and some additional work, I've finally released the first stable version of Cgiapp2.
It is available at both the Cgiapp site as well as via my Phly PEAR channel.
There were a ton of changes while creating the Cgiapp2 branch. From the release notes:
The 2.x series of Cgiapp completes a PHP5 port of Cgiapp2. PHP5 compatibility changes include visibility operators for all properties and methods, declaration of many methods as static and/or final, and the use of exceptions for catching run mode errors. Most notably, though, is the fact that Cgiapp2 is now an abstract class, with one abstract method, setup(); this enforces the fact that you must subclass Cgiapp2 in order to create your application.
New features include:
Callback hook system. Cgiapp2 is now an observer subject, and has hooks at several locations within the application. Additionally, it provides a method for registering new hooks in your applications. The callback hook system replaces the plugin system introduced in Cgiapp 1.7.0.
Template engines are now relegated to plugin classes, and should implement the Cgiapp2_Plugin_Template_Interface. Shipped template engines include Smarty, Savant2, Savant3, and XSLT.
Improved and more extensive error handling, which has been expanded to exceptions as well. Cgiapp2_Exception and Cgiapp2_Error are both observable subjects, with interface classes for implementing observers. This allows the developer to tie into exceptions and errors and perform actions when triggered (Log and Mail observers are implemented for each).
Cgiapp2_FrontController class. This is a simple front controller that dispatches to public static methods in registered classes. Included is a 'page' controller for handling static pages.
I have included migration notes, for those migrating from the 1.x series of Cgiapp; there is very little that you need to do, but some PHP5 changes necessitate some compatability breakages, and the new callback hook architecture and the ability to separate the template engines into plugins introduced some slight changes as well.
In testing the release, I have been writing some apps that take advantage of some of the new features, and I will be writing some tutorials in the coming weeks.
From the blog
Posted 2006-06-04
Always check the version before release
Last week, I had someone bring to my attention that the SPL's Countable
interface was actually first released in PHP 5.1.0… which means I needed to update the PHP dependency on Phly_Hash. I also needed to do so on Phly_Config as it depends on Phly_Hash
. I released 1.1.1 versions of each yesterday; the only change in each is the PHP version dependency.
From the blog
Posted 2006-05-22
Phly_Struct? no, Phly_Hash...
After some discussion with Paul and Mike, I was convinced that 'Struct' was a bad name for Phly_Struct
; structs are rarely if ever iterable, and one key feature of Phly_Struct
is its iterable nature.
The question is: what to name it? Associative arrays go by a variety of names in different languages. In Perl, they're 'hashes'; Ruby and Javascript, 'collections'; Python, 'dictionaries'. I ruled out Phly_Dictionary
immediately, as (a) I don't want it to be confused with online dictionaries, and (b), it's too long. The term 'Collection' also feels too long (although I write things like Cgiapp2_ErrorException_Observer_Interface
, so I don't know why length should be such an issue), as well as unfamiliar to many PHP developers. Hash can imply cryptographic algorithms, but, overall, is short and used often enough in PHP circles that it makes sense to me.
So, I've renamed Phly_Struct
to Phly_Hash, and updated Phly_Config
to use the new package as its dependency. In addition, I've had it implement Countable
, so you can do things like:
$idxCount = count($struct);
Go to the channel page for instructions on adding Phly to your PEAR channels list, and grab the new package with pear install -a phly/Phly_Hash
, or pear upgrade -a phly/Phly_Config
.
From the blog
Posted 2006-05-19
Introducing Phly_Struct and Phly_Config
I often find myself needing a configuration module of some sort — for storing application parameters, bootstrapping, template variables, what have you. I typically will either:
- Create a PHP file that creates and returns an array, and suck that in via include, or
- Create an INI file and suck it in via parse_ini_file, or
- Create an XML file and suck it in via SimpleXML.
The first method gives great flexibility of structure and types, but isn't portable to other languages (well, not easily; you could turn it into JSON, or serialize it, etc). The second method (INI files) is handy because the syntax is so concise, and can translate to other projects in other languages easily if necessary; however, you can only easily go two levels deep (using [sections] in the file). The third method is very portable, and allows nested structures — but doesn't allow usage of many specific PHP types.
I find, however, that each has their place. The problem, however, is: once I bring them into my project, how can I access them? Better yet, would there be a way to bring in configurations of many types and still access them all in the same way?
Not happy with solutions out there, I did the only logical thing: I reinvented the wheel, and added some new tread of my own.
From the blog
Posted 2006-05-16
mbstring comes to the rescue
I've been working with SimpleXML a fair amount lately, and have run into an issue a number of times with character encodings. Basically, if a string has a mixture of UTF-8 and non-UTF-8 characters, SimpleXML barfs, claiming the "String could not be parsed as XML."
I tried a number of solutions, hoping actually to automate it via mbstring INI settings; these schemes all failed. iconv didn't work properly. The only thing that did work was to convert the encoding to latin1 — but this wreaked havoc with actual UTF-8 characters.
Then, through a series of trial-and-error, all-or-nothing shots, I stumbled on a simple solution. Basically, I needed to take two steps:
- Detect the current encoding of the string
- Convert that encoding to UTF-8
which is accomplished with:
$enc = mb_detect_encoding($xml);
$xml = mb_convert_encoding($xml, 'UTF-8', $enc);
The conversion is performed even if the detected encoding is UTF-8; the conversion ensures that all characters in the string are properly encoded when done.
It's a non-intuitive solution, but it works! QED.
From the blog
Posted 2006-05-16
PHP Library Channel
I've been working on Cgiapp in the past few months, in particular to introduce one possibility for a Front Controller class. To test out ideas, I've decided to port areas of my personal site to Cgiapp2 using the Front Controller. Being the programmer I am, I quickly ran into some areas where I needed some reusable code — principally for authentication and input handling.
I've been exposed to a ton of good code via PEAR, Solar, eZ components, and Zend Framework. However, I have several criteria I need met:
- I want PHP5 code. I'm coding in PHP5, I should be able to use PHP5 libraries, not PHP4 libraries that work in PHP5 but don't take advantage of any of its features.
- I prefer few dependencies, particularly lock-in with existing frameworks. If I want to swap out a storage container from one library and use one from another, I should be free to do so without having to write wrappers so they'll fit with the framework I've chosen. Flexibility is key.
- Stable API. I don't want to have to change my code every few weeks or months until the code is stable.
- I should be able to understand the internals quickly.
So what did I choose? To reinvent the wheel, of course!
To that end, I've opened a new PEAR channel that I'm calling PHLY, the PHp LibrarY, named after my blog. The name implies soaring, freedom, and perhaps a little silliness.
It is designed with the following intentions:
- Loosely coupled; dependencies should be few, and no base class should be necessary.
- Extendible; all classes should be easily extendible. This may be via observers, interfaces, adapters, etc. The base class should solve 80% of usage, and allow extensions to the class to fill in the remainder.
- Designed for PHP5 and up; all classes should make use of PHP5's features.
- Documented; all classes should minimally have excellent API-level documentation, with use cases in the class docblock.
- Tested; all classes should have unit tests accompanying them.
- Open source and commercial friendly; all classes should use a commercial-friendly open source license. The BSD license is one such example.
Please feel free to use this code however you will. Comments, feedback, and submissions are always welcome.
From the blog
Posted 2006-05-02
Cgiapp 1.9.0 released
I released Cgiapp 1.9.0 into the wild last night. The main difference between 1.8.0 and 1.9.0 is that I completely removed the plugin system. I hadn't had any users reporting that they were using it, and, in point of fact, the overloading mechanism I was using was causing some obscure issues, particularly in the behaviour of cgiapp_postrun()
.
As usual, you can find more information and links to downloads at the Cgiapp site.
From the blog
Posted 2006-04-30
What is Cgiapp?
After some conversations with Paul and Mike, in recent months I realized that while I often announce new releases of Cgiapp, I rarely explain what it is or why I develop it.
I got into trouble on the PEAR list when I tried to propose it for inclusion in that project, when I made the mistake of describing it as a framework. (This was before frameworks became all the rage on the PHP scene; PEAR developers, evidently, will not review anything that could possibly be construed or interpreted as a framework, even if it isn't.) I mistakenly called Cgiapp a framework once when considering proposing it to PEAR. But if it's not a framework, what is Cgiapp? Stated simply:
Cgiapp is the Controller of a Model-View-Controller (MVC) pattern. It can be either a front controller or an application controller, though it's typically used as the latter.
From the blog
Posted 2006-04-28
Telcos are Attacking the Internet
I generally try to stay out of politics on this blog, but this time something has to be said, as it affects anyone who uses the internet, at least in the US.
Basically, a number of telcos and cable providers are talking about charging internet content providers — the places you browse to on the internet, places like Google, Yahoo!, Amazon, etc. — fees to ensure bandwidth to their sites. Their argument is that these content providers are getting a 'free ride' on their lines, and generating a lot of traffic themselves, and should thus be paying for the cost of bandwidth.
This is patently ridiculous. Content providers already have to pay for their bandwidth — they, too, have ISPs or agreements with telcos in place, either explicitly or via their hosting providers. Sure, some of them, particularly search engines, send out robots in order to index or find content, but, again, they're paying for the bandwidth those robots generate. Additionally, people using the internet are typically paying for bandwidth as well, through their relationship with their ISP. What this amounts to is the telcos getting paid not just by each person to whom they provide internet access, but every end point on the internet, at least those within the US.
What this is really about is telcos wanting more money, and wanting to push their own content. As an example, let's say your ISP is AOL. AOL is part of Time Warner, and thus has ties to those media sources. Now, those media sources may put pressure on AOL to reduce bandwidth to sites operated by ABC, CBS, NBC, FOX, Disney, PBS, etc. This might mean that your kid can no longer visit the Sesame Street website reliably, because AOL has reduced the amount of bandwidth allowed to that service — but any media site in the TWC would get optimal access, so they could get to Cartoon Network. Not to slam Cartoon Network (I love it), but would you rather have your kid visiting cartoonnetwork.com or pbskids.org? Basically, content providers would not need to compete based on the value of their content, but on who they can get to subscribe to their service.
Here's another idea: your ISP is MSN. You want to use Google… but MSN has limited the bandwidth to Google because it's a competitor, and won't accept any amount of money to increase that bandwidth. They do the same with Yahoo! So, now you're limited to MSN search, because that's the only one that responds reliably — regardless of whether or not you like their search results. By doing so, they've just artificially inflated the value of their search engine — without needing to compete based on merit.
Additionally, let's say Barnes and Noble has paid MSN to ensure good bandwidth, but part of that agreement is a non-compete clause. Now you find your connections to Amazon timing out, meaning that you can't even see which book provider has the better price on the book you want; you're stuck looking and buying from B&N.
Now, let's look at something a little more close to home for those of us developing web applications. There have been a number of success stories the last few years: MySpace, Digg, and Flickr all come to mind. Would these endeavors have been as successful had they needed to pay multiple times for bandwidth, once to their ISP and once each to each telco charging for content providers? Indeed, some of these are still free services — how would they ever have been able to pay the extra amounts to the telcos in the first place?
So, basically, the only winners here are the telcos.
Considering how ludicrous this scheme is, one must be thinking, isn't the US Government going to step in and regulate against such behaviour? The answer, sadly, is no. The GOP doesn't like regulation, and so they want market forces to decide. Sadly, what this will likely do is force a number of content providers to offshore their internet operations — which is likely to have some pretty negative effects on the economy.
The decision isn't final — efforts can still be made to prevent it (the above link references a Senate committee meeting; there's been no vote on it). Call your representatives today and give them an earful. Tell them it's not just about regulation of the industry, but about fair competition in the market. Allowing the telcos to extort money from content providers will only reduce the US' economic chances in the world, and stifle innovation and choice.
From the blog
Posted 2006-04-08
Automating PHPUnit2 with SPL
I don't blog much any more. Much of what I work on any more is for my employer, Zend, and I don't feel at liberty to talk about it (and some of it is indeed confidential). However, I can say that I've been programming heavily on PHP5 the past few months, and had a chance to do some pretty fun stuff. Among the new things I've been able to play with are SPL and PHPUnit — and, recently, together.
From the blog
Posted 2006-03-27
PHP error reporting for Perl users
On perlmonks today, a user was needing to maintain a PHP app, and wanted to know what the PHP equivalent of perl -wc script.pl
was — specifically, they wanted to know how to run a PHP script from the commandline and have it display any warnings (ala perl's strict and warnings pragmas).
Unfortunately, there's not as simple a way to do this in PHP as in perl. Basically, you need to do the following:
-
To display errors:
- In your
php.ini
file, setdisplay_errors = On
, or - In your script, add the line
ini_set('display_errors', true);
- In your
-
To show notices, warnings, errors, deprecation notices:
- In your
php.ini
file, seterror_reporting = E_ALL | E_STRICT
, or - In your script, add the line
error_reporting(E_ALL | E_STRICT);
- In your
Alternatively, you can create a file with the lines:
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', true);
and then set the php.ini
setting auto_prepend_file
to the path to that file.
NOTE: do not do any of the above on a production system! PHP's error messages often reveal a lot about your applications, including file layout and potential vectors of attack. Turn display_errors
off on production machines, set your error_reporting
somewhat lower, and log_errors
to a file so you can keep track of what's going on on your production system.
The second part of the question was how to run a PHP script on the command line. This is incredibly simple: php myscript.php
. No different than any other scripting language.
You can get some good information by using some of the switches, though. -l
turns the PHP interpreter into a linter, and can let you know if your code is well-formed (which doesn't necessarily preclude runtime or parse errors). -f
will run the script through the parser, which can give you even more information. I typically bind these actions to keys in vim so I can check my work as I go.
If you plan on running your code solely on the commandline, add a shebang to the first line of your script: #!/path/to/php
. Then make the script executable, and you're good to go. This is handy for cronjobs, or batch processing scripts.
All of this information is readily available in the PHP manual, and the commandline options are always available by passing the --help
switch to the PHP executable. So, start testing your scripts already!
From the blog
Posted 2006-02-19
Cgiapp dual releases
Today, I have released two versions of Cgiapp into the wild, Cgiapp 1.8.0 and Cgiapp2 2.0.0rc1.
Cgiapp 1.8.0 is a performance release. I did a complete code audit of the class, and did a number of changes to improve performance and fix some previously erratic behaviours. Additionally, I tested under both PHP4 and PHP5 to make sure that behaviour is the same in both environments.
However, Cgiapp 1.8.0 markes the last feature release of Cgiapp. I am deprecating the branch in favor of Cgiapp2.
Cgiapp2 is a PHP5-only version of Cgiapp. Some of the changes:
-
Cgiapp2
is an abstract class, with the abstract methodsetup()
. Now it is truly non-instantiable! - Cgiapp2 makes extensive use of visibility operators. Key methods have been marked final, some methods are now protected, others static. See the changelog for more information.
- Cgiapp2 is now
E_STRICT
compliant. - Cgiapp2 implements the CGI::Application 4.x series callback hook system. This is basically an observer pattern, allowing developers to register callbacks that execute at different locations in the runtime.
- Cgiapp2 adds some extensive error and exception handling classes, including observable errors and exceptions.
- I created a template interface. If implemented, a template engine can be plugged into the architecture at will — at the superclass, application class, and instance script level, allowing developers to mix-and-match template engines or choose whichever matches their taste, without having to rewrite application code. Three template plugins are included:
Cgiapp and Cgiapp2 are available at Sourceforge.
Keep reading for more information on the evolution of Cgiapp2.
From the blog
Posted 2006-01-05
XP + Cygwin + coLinux == Productivity
I wrote earlier of my experiences using Windows XP, a move I've considered somewhat unfortunate but necessary. I've added a couple more tools to my toolbox since that have made the environment even better.
From the blog
Posted 2005-11-30
Cgiapp 1.7.1 Released
I was able to roll a long-needed (and by some, long awaited) bugfix release of Cgiapp this morning. Cgiapp 1.7.1 corrects the following issues:
-
Cgiapp5::run()
was corrected to callquery()
instead ofcgiapp_get_query()
(which caused a fatal error) -
Cgiapp::__call()
andCgiapp5::__call()
now report the name of the method called in errors when unable to find matching actions for that method.
As usual, downloads are available on my site as well as via SourceForge.
Update: The link on my site for downloading Cgiapp has been broken; I've now fixed it.
From the blog
Posted 2005-11-08
Simple Caching for PHP
I ran across an article on "How to build a simple caching system, with PHP" on PHPit today. Overall, it's a fairly decent article, and uses some good principles (using the output buffer to capture content, using a callback to grab the captured content). There are a few minor improvements I'd make, however.
From the blog
Posted 2005-10-18
Zend PHP Expo Presentation
Mike and I have just finished our talk on "Setting Up PHP". The number of attendees was N + 1, where N is the number of speakers… which was to be expected, as we were presenting opposite a session on web services, Shiflett's PHP Security talk, and a crash course on the ZCE. However, it's undoubtedly the best presentation missed by attendees. :-)
From the blog
Posted 2005-10-16
Review: php|architect's Guide to PHP Security
I flew in to San Jose today to visit Zend, and later attend the Zend/PHP Conference and Expo (two days left… register now if you haven't, and have the time to attend; the conference sessions promise to be very interesting).
During the flight, I had plenty of time to go through Ilia's Guide to PHP Security, which I'd ordered several weeks ago, but hadn't had time to read since.
From the blog
Posted 2005-10-13
Zend Conference
Around the time I was hired by Zend, I was asked, along with Mike Naberezny, to fill in for a tutorial session entitled 'Setting up PHP' for the upcoming Zend/PHP Conference and Expo. The basic premise of the session is to give a step-by-step tutorial on how to setup and configure PHP for various scenarios, such as development, testing, and production.
Mike and I have been working in parallel developing ideas and outlines for the session, and I'm fairly excited to have the opportunity. However, if you're attending the conference and, in particular, this session, I'd love to hear any input you might have — any tricks you'd love to learn, configuration settings you don't understand, use cases you might need. Leave a comment!
From the blog
Posted 2005-09-21
Transitions
Life is in transition for me now. Two weeks ago, we got to bring our handsome baby boy home, and I haven't been sleeping much since (though more than Jen). On top of the sleep deprivation, however, comes more exciting news: I've been hired as a PHP Developer by Zend Technologies!
I was approached by Daniel Kushner in late July regarding another position at Zend, and was flown out at the beginning of August. While I felt the interview went well, I harbored some doubts; work got fairly busy shortly thereafter, and then, of course, Liam was born, and the interview went completely out of my head. Until about three days after Liam's birthday, when Daniel contacted me again about the PHP Developer position.
Work started yesterday, and I was flown to Zend's offices in Cupertino, CA, for orientation and to sit down with both Daniel and others to prepare for the projects on which I will be working. Thankfully, the job will not require that I move, and I will be working out of the 'home office' in Vermont when I return later this week.
The decision to leave NGA was difficult, but the opportunity to work with Zend is just too good to miss. I am honored to be selected by them, and hope this is the beginning of many good things to come.
From the blog
Posted 2005-09-07
File_SMBPasswd woes
I've been cobbling together a system at work for the last couple months to allow a single place for changing all network passwords. This includes a variety of database sources, as well as passwd files and smbpasswd files. I've been making use of PEAR's File_Passwd and File_SMBPasswd, and they've greatly simplified the task of updating passwords for those types of systems. However, I've encountered some issues that I never would have expected.
I have the web user in a group called 'samba', and I have the smbpasswd file owned by root:samba. I then set the smbpasswd file to be group +rw. Simple, right? The web user should then be able to update the smbpasswd file without a problem, right? Wrong.
I kept getting errors, and on investigation continually found that the smbpasswd file permissions had reverted to 0600 — i.e., only the root user could access it. I tried using 'chattr -i' on the off-chance that the file had been made immutable (which didn't make sense, as I was able to see the permissions change). No luck.
Based on observations of when the permissions reverted, it appears that the various SMB processes will reset the permissions! An example is when someone attempts to mount a resource from the server; this accesses the smbpasswd file to perform authentication — and at this point the file permissions change. I can find no documentation to support this; these are simply my observations.
So, to get around the behaviour, I created a script that will set the file permissions to what I want them, and then gave sudo privileges to the samba group for that script. This script is then called via system() in the update script just before processing.
It's a hack, and could be made more secure, but it works.
From the blog
Posted 2005-07-28
Form madness
Those who follow my blog may remember an earlier entry on form validation. I looked into some of the possible solutions those who commented provided, but other than Solar_Form, each was either trying to generate HTML, or not generating HTML was considered a plugin type of behaviour (i.e., the HTML generation was the norm, and not generating HTML typically added layers). Discouraged, I continued plugging away on my own solution which was incorporating Solar_Valid for validations, adding some filtering, adding the ability to load definitions from a file, and adding the ability to use callbacks for either filters or validation rules.
I got some code together, tried it out, and felt that either something was missing, or I was doing something a little wrong. I posted the code source, and asked Paul Jones for feedback.
After some initial flurries of emails with Paul asking for more detail, me providing it, Paul asking questions, me attempting to answer… Paul had me look at the source for Solar_Form. In doing so, I discovered what he was suspecting, namely, that we were trying to build something similar. Rather than continue on parallel courses, I decided to jump in and help in this aspect of the Solar project.
From the blog
Posted 2005-07-14
File_Fortune 0.9.0 Released
File_Fortune has been released via PEAR.
Changes since the proposal include the addition of a static method for retrieving a random fortune from a list of files, the addition of a DocBook tutorial listing several usage examples, renaming the exception classes to conform to PEAR CS, some minor bugfixes, and some streamlining of the package definition.
Included in the release is an example script, phpFortune, that can be used on the command line to get random fortunes from one or more fortune files. Usage is:
$ phpFortune fortunes
$ phpFortune fortunes simpsons hitchhiker
$ phpFortune
Enjoy!
From the blog
Posted 2005-07-14
File_Fortune accepted to PEAR
What a way to start the day — I had an email from PEPR letting me know that my File_Fortune proposal had been accepted!
File_Fortune
is a PHP OOP interface to reading and writing fortune files. It
is loosely based on the perl module Fortune.pm, but modified significantly to
better work with PHP file access methods, as well as to add writing capability.
I will be uploading my initial release shortly, probably as a beta or RC.
So, go fetch those Simpsons, Hitchhiker's Guide, and Star Wars fortune cookie databases and prepare to add random quotes to your site!
From the blog
Posted 2005-07-10
Thoughts on form validation
I've been doing a lot of thinking on form validation recently. Among other things, I want to be using a standard set of tools for validating form input at work; I'm also rewriting the family website in PHP, and want to have consistency there as well. Finally, I truly buy into Chris Shiflett's top two security practices: filter input, escape output. Validation should always be done, and should be done rigorously; don't allow anything more than is necessary to get the work done.
I flirted briefly in the past month with
HTML_QuickForm. Being an
observer on the CGI::Application
mailing lists, HQF looks like PHP's answer to
perl's
Data::FormValidator.
HQF has a high frequency of posts on the php-pear-general lists. A lot of
people seem happy with it. I decided to try it out as an example plugin for
Cgiapp for the latest release.
My problem is that I want to be able to define form validation in a file outside my script. The reason for this is that as I extend and reuse classes, I often find that I can use the same general run-modes for a method… just so long as the form validation logic is separate. This allows me, for instance, to decide that in one application instance I will require fields A-M, but in another, I only need A-E (or vice versa). But it requires no changes to the actual application logic, as the validations are kept separately, and I have the application instance indicate which validation file to utilize.
From the blog
Posted 2005-07-06
Notes on PEAR_Exception
I've been doing some thinking on exceptions, and
PEAR_Exception
in particular. You may want to skip ahead to read about how to use
PEAR_Exception
, as well as some of my thoughts on the class on first use. If
you want the background, read on.
I've created a package proposal on PEAR for a package called File_Fortune, an OOP interface to reading and writing fortune files. I've been using a perl module for this on the family website for years, and now that I'm starting work on the PHP conversion, I thought I'd start with the building blocks.
In creating the proposal, I started with a PHP5-only version, though I found
that I wasn't using much in PHP5 beyond the public
/private
/protected
/static
keywords. For error handling, I decided to try out
PEAR_ErrorStack, as I'd been
hearing buzz about it being the new "preferred" method for error handling in
PEAR. (Honestly, after using it, I'm not too happy with it; throwing
PEAR_Error
s was much easier, and easier to manipulate as well — but that's a
subject for another post — and exceptions were easier still, though more
typing.)
The first comment I got on the proposal was the question: "Why PHP5?" (Paul wasn't too surprised by that reaction.) I thought about it, and decided it wasn't really all that necessary, beyond the fact that I'd need to take some extra steps to be able to actually test a PHP4 version. So, I did a PHP4 version.
Well, then some chatter happened, and a number of developers said, "Why not
PHP5?" So, I went back to PHP5. And then somebody else said, "Use
PEAR_Exception
." So, I started playing with that, and we finally get to the
subject of this post.
From the blog
Posted 2005-06-28
ZCE - Results are in!
Got the official notification: I passed the Zend PHP Certification Exam, and can now report I'm a Zend Certified Engineer (ZCE)!
Thanks go to my bosses at NGA for giving me the opportunity to attend php|Tropics, to Marco Tabini for offering the ZCE exam as part of the php|Tropics conference fee, and to my wife, Jen, and daughter, Maeve, for putting up with me while I studied… and being good sports about having to stay home while I went to Cancun. Hopefully next time I can take you along!
From the blog
Posted 2005-06-14
PHP Application Documentation
Paul Jones has written an interesting piece about documentation in the PEAR project, in which he argues very convincingly for using wikis for end user documentation.
I actually think that last point bears repeating: using wikis for end user documentation. I talked to Paul about this issue at php|Tropics, and both of us use phpDocumentor quite religiously. However, API documentation is very different from end user documentation. And the issue with documentation at the PEAR project has to do with the fact that there are many projects with little or no end user documentation — which often makes it difficult for a developer to determine how a module might be used.
The often-cited barrier for this is that end user documentation on the PEAR website must be done in DocBook format.
From the blog
Posted 2005-06-05
Search APIs
Twice in the past week I found myself needing to create or alter database search functionality in some APIs for work. In doing this work, I discovered some techniques that make this process much easier. In line with The Pragmatic Programmer, I found myself exploring the DRY principle (Don't Repeat Yourself), and looking into code generation (this time, SQL) — basically to exploit my inherent laziness and to make my job easier.
I thought I'd share some of the principles I've discovered for myself as I haven't read much information on the subject. Some of this may be rudimentary for some readers or those who work with more advanced abstraction layers (I suspect DB_DataObject may do much of this), but hopefully the information can be a useful reference for others (myself included).
From the blog
Posted 2005-05-26
Planet PHP
I recently had an email exchange with chregu of Planet PHP regarding Planet PHP's blog selection. I've been subscribing to its RSS feed for over a year now, but was uncertain how blogs were selected — was it based on popularity of the developer, projects the developer works on (for instance, PEAR), etc. I felt that it was time for this information to be made public; it helps inform the readership why they're reading what they're reading.
And my exchange with him resulted in his Planet PHP FAQ blog entry, which hopefully someday will become a static page on the site. Additionally, I found out how new blogs get added, and am proud to announce I'm now in the lineup!
(Of course, the timing could not really be worse, come to think of it. I'm moving my family in to town this weekend (from our house in the Green Mountains of Vermont), and I need to make arrangements for hosting weierophinney.net in the interim while we wait for phone and DSL service — which won't be up for at least another week :-( I'm sure I'll figure out something… stay tuned!)
Update: corrected link to Planet PHP FAQ.
From the blog
Posted 2005-05-22
PEAR and DocBook documentation
Sean Coates has posted a rant and a blog entry regarding DocBook and the various proposals on PEAR related to using a wiki for package documentation.
A little background is probably in order. Many PEAR developers feel that DocBook is needlessly difficult and provides a barrier to writing good documentation for PEAR projects; this is actually the most often-cited reason for lack of documentation for a PEAR package. Many actually create wikis that they then link to in a minimal DocBook tutorial as "full documentation".
One proposed remedy is to create a PEAR wiki for each PEAR package. A scheduled process would then transform the wiki markup to DocBook, HTML, PDF, whatever.
What Sean rants about is simply this: wiki markup is meant to be simple, and much code documentation would require specialized wiki markup. Additionally, DocBook is already meant to do the transformations required; it is a structured language that is meant to be processed into a variety of output formats.
While I agree with Sean's ideas in essence, I still feel that DocBook is a real
pain to work with. PhpDocumentor offers some real
convenience when documenting code: doc blocks can contain HTML, some simple
inline elements like {@link}
— and they make documenting a snap. But I just fail
to understand why, when providing tutorials, a switch to DocBook is necessary.
Whenever I use it, I find that I have to retool a set of tutorials I have, or
somebody else has, already written in order to get formatting correct, and that
I have to switch my thinking altogether to accomodate a new set of rules and
logic.
Yes, DocBook is simply XML with a documented schema. However, I've never enjoyed
XML. I find it too pedantic, I don't like having to escape out CDATA
sequences
in order to render HTML (and code, and XML, etc.), I don't like having to learn
new DTDs for every project, and more. I feel for configuration, unless you have
nested elements, there's no reason to use XML whatsoever. And when it comes to
documentation, why use anything other than HTML? Since HTML is a subset of SGML
(as is XML), there's no reason it can't be transformed to other formats itself —
and for the majority of PHP developers, HTML is a known, while XML/DocBook may
or may not be.
Whether or not DocBook is hard can be debated from here to eternity. The fact of the matter is that it is perceived as being hard to learn, and thus many PEAR developers are simply choosing not to bother. Why not give them a tool they can use easily? Maybe then the amount and quality of documentation on PEAR will improve.
From the blog
Posted 2005-05-20
Cgiapp 1.7.0 released
I'm getting ready to move in another week, and thought it was time to push a new release out the door… before life descends into utter chaos.
Cgiapp 1.7.0 adds a plugin architecture (which has been present in the perl version since last autumn). Plugins register with the class, and, once registered, their methods may be called from your Cgiapp-based class as if they were part of it through the magic of overloading. This allows for a standard library of utilities to be written — such as form validation (a sample class for this has been provided utilizing HTML_QuickForm), authentication, error logging, etc.
Additionally, I created a Cgiapp5
class that inherits from and extends Cgiapp.
Along with it is a CgiappErrorException
class that can handle PHP errors and
rethrow them as exceptions. Combined, the two create some very elegant run mode
error handling that simply isn't possible in PHP4.
Visit the Cgiapp website for more information on Cgiapp; if you want to try it, download it.
From the blog
Posted 2005-05-20
php|Tropics recap
php|Tropics last week was excellent, and I'm not even sure where to begin for a recap. I started journaling while there, but found I simply did not have enough time (or bandwidth — my one complaint about the conference) to keep up.
The trip down was hellish. I'd lost my birth certificate, and was turned away at the ticket counter due to improper documentation. I was able to reschedule for several hours later, and had just enough time to go home, look futilely for my birth certificate, and then run down to the town clerk office in Bolton to get a certified and notarized letter proving my voter registration. Which got me on the plane, but I still ended up having to sign a notarized affidavit of citizenship before my final flight from Houston could take off.
The resort where the conference was held is called Moon Palace Resort, and is one of a string of five or more 'Palace' resorts on the Mexican Riviera below Cancun. The place is huge — there are two lobby areas, and each serves what looks like a couple thousand rooms. You can't help but get exercise while there, because there's simply so much ground to cover.
Marco Tabini gave the keynote, and kept it short and sweet. To my mind, he covered one primary point: the PHP job market sucks for pay. As he put it, why does an assembly line worker at Ford get paid $35/hour, while the average PHP developer is paid $15/hour? This is not to belittle the assembly line worker, but more to ask the question of whether or not a PHP developer is inherently less skilled. Marco feels that the way to boost PHP wages is to produce a standard educational corpus and licensing program — and educate employers as to why someone who has taken them deserves to be paid more. (I'm still not sure how I feel about his conclusions, but they're certainly food for thought — as I'm not being paid much more than the PHP average.)
Rob and I skipped out on the first two sessions. To our mind, we weren't as interested in them as other sessions, and we weren't going to have much free time while there. We put on the swim trunks and took a stroll through the pool. Yes, a stroll. I wish I could find a map that shows just how long and serpentine the pool there is; you can easily get a good workout just going for a stroll in the pool.
And strolling is thirsty business, so we strolled over to a swim-up bar. Now, one excellent thing about the location is that the resort is an "all-inclusive" resort — meaning that all food and drink is included in the price. So, we ordered margaritas, since it was noon where we live. They were okay, a little weak… and Rob noted that the bartender wasn't using anything off the top shelf. "What do you think we need to do to get him to use the Sauza?" asked Rob, to which I replied, "I think you just ask for it." So, next round, "Margaritas con Sauza, por favor."
And so it goes.
Strolling also included the beach, a wonderful expanse of white sand overlooking the azure water of the Caribbean. I spent a lot of time just sitting under coconut trees staring out over the sea; I can see how tempting it would be to retire on the Caribbean.
We started attending sessions that afternoon, and only missed one more over the course of the conference. I did get some excellent information from a number of sessions — but one thing in particular I got out of the conference as a whole is how far advanced is the setup Rob and I have put together at NGA. Our web cluster is almost as good as it gets without pouring money into commercial databases and support (though Ilia Alshanetsky's web acceleration session gave me a ton of information on tuning the relations between php, apache, and the OS); we've standardized on PEAR and are using it well; we're filtering data reasonably well (though we can always do better); etc. I often feel like I'm behind the curve when it comes to our technology, so the conference was a welcome boost to the ego.
On day 2, I ran into Paul Jones, with whom I've emailed once or twice, and on whose blog I've commented several times. We immediately started hanging out, and talking shop. Which began the other important aspect of the conference: the social networking.
In day-to-day practice, I really only get to talk code and program with one other person, Rob. This is fine, but it leads to a narrow exposure. Going to the conference gave me a chance to go over code and coding philosophy with a larger variety of people — my peer group, if you will. I got to see that, if you're not working for a large corporation, you do the same shit I do every day — programming, installing and tuning servers, help desk issues, everything; coding in PHP is only one aspect of your busy life. It was actually refreshing to see that I'm not alone.
A group of six of us got together that second evening, and ate out at one of the 'restaurants' (there are several eateries at the resort; not really restaurants, 'cause you don't have to pay, and they're all buffets) overlooking the Caribbean. As we were talking, we commented on how the networking amongst each other was probably the best part of the conference — and how it would be nice if the speakers would deign to join us.
Ask and ye shall receive. Later that evening, as we stood around the 'swing bar' (a little tiki bar with swings instead of bar stools, out on an island of the large, serpentine pool), we were gradually joined by speakers, including Marcus Boerger, Wez Furlong, Derick Rethans, and Lukas Smith. We had some great discussions that started devolving in indirect proportion to the amount we drank (well, not really devolving, but certainly migrating to other non-coding topics…)
Unfortunately, Rob and I had to cut out around 11:30, as we were taking the Zend Certification Exam at 8 the following morning. I quit drinking between 9:30 and 10… Rob had not, so he got to do the exam with a hangover. All in all, I found the exam less difficult than the study guide, but certainly full of tricks meant to foil you.
The final evening had a similar conclusion to the night before, only with even more participants, including Jason Sweat and Ilia. This time there were no exams to follow, and we stayed up until 1:30 (and later for some people).
Looking back, I see I wrote very little about the actual conference — which seems odd, as it was the central event. There were certainly some excellent presentations, and a lot of great material — much of it I have not been able to find elsewhere. Hopefully I'll find some time to blog about it in the coming weeks.
I didn't take many pictures, and I need to get a gallery going anyways. Rob, however, took a ton of pictures and put them up on his site each day. You can view them at his gallery; I'll put direct links to the individual galleries later.
So, if you get a chance, attend the next PHP conference you can possibly afford, and spend as much time as possible getting to know your fellow PHP code monkeys; the benefits are, to use an oft-used marketing phrase, priceless.
From the blog
Posted 2005-05-07
HTML_QuickForm with Smarty Quickstart
I've been wanting to play with
HTML_QuickForm for quite some
time, but the documentation has looked rather sparse and scary regarding the use
of HTML_QuickForm
with Smarty. Since I've been busy
at work, and I haven't wanted to take the time to learn a new library, I've
simply been putting it off.
Last night, I browsed through the package documentation, and noticed a link to an HTML_QuickForm Getting Started Guide by Keith Edmunds. I was pleased to discover that he also has a guide to using Smarty with HTML_QuickForm. I got started with these tutorials, and found them excellent. I found myself wanting a little more meat afterwards, and found that I could now turn to the PEAR docs and actually make sense of it all.
While I think Mr. Edmunds tutorials are great for starters, I found that there were a few pointers I could have used right off the bat. I present them here for you.
From the blog
Posted 2005-05-06
Cgiapp - 2 Releases
I've made two releases of Cgiapp this week, 1.6.2 and 1.6.3.
1.6.2 was tested in a PHP 4.3.4 environment, and features several bugfixes that
give PHP4 compatibility. 1.6.3 fixes a change in load_tmpl()
that broke
backwards compatibility.
As usual, Cgiapp is available on the SourceForge website, as is a complete Changelog and documentation.
From the blog
Posted 2005-04-28
Cgiapp Plugin Development
I've been working on the Cgiapp roadmap, and particularly on the plugin architecture. I'd been operating under the assumption that I'd have to make a PHP5-specific release (Cgiapp2) to allow this feature. However, it turns out I'm wrong.
From the blog
Posted 2005-04-24
Cgiapp 1.6.1 released
A user noted in a comment to my blog on the 1.6.0 release that I'd included a
public
keyword in the s_param()
method declaration… which caused
compilation to fail in PHP4. So, quick on the heels of that release, I've
released 1.6.1 to correct this issue. Downloads are available at the
Cgiapp website.
From the blog
Posted 2005-04-22
Cgiapp 1.6.0 Released
Cgiapp 1.6.0, "Wart Removal", has been released!
This release does not add any new methods, but adds quite a lot in terms of functionality:
-
phpt tests. I finished writing a suite of unit tests using the phpt
framework popularized by the PHP-QA project and PEAR. This process helped me
find some obscure bugs in the class, as well as some… well, downright ugly
code, and to fix these areas. (To be honest, most of the 'ugly' code was a
result of being too literal when porting from perl and not using more standard
PHP functionality.) Among the bugs fixed:
-
s_delete()
now works properly.param()
ands_param()
now behave gracefully when given bad data (as do a number of other methods) -
_send_headers()
and theheader_*()
suite now function as documented. - All methods now react gracefully to bad input.
-
-
Error handling.
carp()
andcroak()
no longer echo directly to the output stream (and, in the case ofcroak()
, die); they usetrigger_error()
. This will allow developers to usecarp()
andcroak()
as part of their regular arsenal of PHP errors — including allowing PHP error handling. Additionally, mostcroak()
calls in the class were changed tocarp()
as they were not truly fatal errors. -
PEAR packaging. Cgiapp can now be installed using PEAR's installer. Simply
download the package and type
pear install Cgiapp-1.6.0.tgz
to get Cgiapp installed sitewide on your system!
As usual, Cgiapp is available at the Cgiapp website.
From the blog
Posted 2005-04-20
phpt Tutorial
As promised in my earlier entry from today, here's my quick-and-dirty tutorial on unit testing in PHP using phpt.
First off, phpt test files, from what I can see, were created as part of the PHP-QA effort. While I cannot find a link within the PHP-QA site, they have a page detailing phpt test files, and this page shows all the sections of a phpt test file, though they do not necessarily show examples of each.
Also, you might find this International PHP Magazine article informative; in it Aaron Wormus gives a brief tutorial on them, as well as some ways to use phpt tests with PHPUnit.
Finally, before I jump in, I want to note: I am not an expert on unit testing. However, the idea behind unit tests is straightforward: keep your code simple and modular, and test each little bit (or module) for all types of input and output. If the code you're testing is a function or class method, test all permutations of arguments that could be passed to it, and all possible return values.
Okay, let's jump in!
From the blog
Posted 2005-04-20
PHP Unit Tests: and the winner is: phpt
I've been tinkering with Unit Testing for around a year now, and have tried using PHP Unit as well as Simple Test. It was while following the Simple Test tutorial that I finally grokked the idea of unit testing, and so that has been my favored class for testing.
However, I find writing the tests tedious. In Simple Test, as in PHP Unit, you need to create a class that sets up the testing harness, and then you create a method for each test you wish to run, and so on… I found it incredibly time consuming. Additionally, I found the test harness often felt like a foreign way of testing my code; I was setting up a structure I would never use my code in, typically. All in all, I only test when I have extra time (which is rare) or when I'm really having trouble nailing down bugs (and the unit tests often don't help me find them).
Recently, I've been hearing some buzz over on the PEAR lists and the blogs of some of its developers about 'phpt' tests. From what I hear, phpt tests sound very similar to how one tests in perl (though I've never written perl tests, I've at least glanced through them). However, until recently, I haven't seen any documentation on them, and installing PEAR packages via pear doesn't install tests.
We got a copy of PHP5 Power Programming a few weeks ago, and in the section on preparing a PEAR package was a brief section on phpt tests. The section was small, and when I looked at it, my immediate thought was, "it can't be that simple, can it?"
So, I decided to try it out with Cgiapp. A few minutes later, I had some working tests for my static methods. "Hmmm," I thought, "That was easy. Let's try some more."
Turns out they're kind of addictive to geeks like me. In a matter of a few hours, I'd knocked out tests for over half the functionality, and disccovered, to my chagrine and joy, a number of bugs and bad coding practices… which I promptly corrected so I could get that magical 'PASS' from the test harness.
In the process of writing the tests, my understanding of the tool evolved quite a bit, and by the end, I had the knack for it down. I'll blog later about some of the ways I made them easier to use for myself — and how I made them more useful for debugging purposes.
From the blog
Posted 2005-04-17
Abstract Classes
I just had to add a note over on PHP.net regarding abstract classes and methods: Object Abstraction.
I'm working on Cgiapp2, which is a PHP5-only implementation of Cgiapp that is built to utilize PHP5's new object model as well as exceptions. One thing I decided to do, initially, was to make it an abstract class, and to mark the overridable methods as abstract as well.
In testing, I started getting some strange errors. Basically, it was saying in my class extension that an abstract method existed, and thus the class should be marked as abstract, and, finally, that this means it wouldn't run.
What was so odd is that the method didn't exist in the extension at all.
So, I overrode the method in the extension… and voila! Everything worked fine.
The lesson to take away from this is quite simple: if the method does not need to be present in the overriding class, don't mark it as abstract. Only mark a method as abstract if:
- The method is required in the class implementation, and
- The extending class should be responsible for implementing said method
Now I need to update my source tree…. :-(
From the blog
Posted 2005-04-11
PEAR, Channels, and Frameworks
Greg Beaver writes in his blog about PEAR, the new PEAR channels, and some issues he sees with PEAR and its developers. Greg is responsible for the latest version of PEAR and the PEAR installer — and for the development of PEAR channels. The particular link referenced above makes reference to a thread on the PEAR-dev mailing list… that I originated, when asking whether or not Cgiapp might be a good fit for PEAR.
From the blog
Posted 2005-04-02
PHP, Cgiapp, and extensibility
At work this week, Rob was doing some monitoring of our bandwidth usage. We have SNMP on each of our servers now, and he uses MRTG to create bandwidth usage graphs that are updated every five minutes or so. He's been monitoring since late last year.
Before January, we had two systems going. The first, legacy, system hosted the majority of the content from garden.org, and was done using Tango 2000, a web application server that ran on top of IIS and Windows NT 4. I say 'ran', because Tango 2000 was the last version to ship; the company that made it stopped supporting it a year later. This meant we could not upgrade our server's OS to Windows 2000 or 2003, nor could we switch to a more secure web server, etc. It was a time bomb waiting to happen.
The second system is a basic LAMP system — Linux + Apache + MySQL + PHP. Rob began migrating applications to it shortly after he started at NGA 3 years ago, one application at a time. Mostly, new applications were placed on it, though in May 2003, he and the other programmer who was there at the time started migrating old applications to the techology. Part of the reason I was hired was to continue this migration.
The migration was time consuming, and plenty of other projects often got in the way. However, starting last July, we made a big push to get it all ported over — before the old WinNT server fails on us. In January, we were able to rollout the new garden.org, which runs on this new technology.
A big reason we were able to finish is because of Cgiapp. I originally ported it to PHP last year around this time, and knew that while I wanted to develop new applications using it, I wasn't so sure I could sell Rob on it.
Amazingly, it didn't take much to convince him. We had already started using Smarty for templates just before this, and were also using OOP in new development. Cgiapp just helped unify these technologies and to provide a nice, standard framework with which to program.
This last can not be emphasized enough. We started developing all applications in three places: an API for data access, a Cgiapp-based application, and our templates. Either one of us could pick up development of an application from the other without having to spend a day or two familiarizing ourselves with the idiosyncracies of what the other had decided was the programming paradigm of the day. Sure, we still have our own programming styles, but the framework makes it easy to debug or extend each others programs painlessly.
Now, back to the bandwidth reports: Rob has noticed that our bandwidth usage has been growing steadily on the new server since we switched garden.org over — a 45 degree line. At one point this week, our outgoing bandwidth was almost 3 T1s — and we were having no performance issues whatsoever. This simply would not have been possible on the old system — nor without Cgiapp. We've managed to produce both a hardware architecture and a programming framework that has proved immensely scalable — which will in turn save the organization money.
I love open source! How else can you create such high-performing software without paying through the nose for it?
From the blog
Posted 2005-03-25
s9y + s4y = phly
So, I did a little experimentation, and I was able to seamlessly integrate Serendipity into my existing website via Smarty, some CSS, and changing just a couple of links!
The result is the website you're currently reading!
This means I can now offer trackbacks, comments, RSS feeds, and all the other stuff a modern blog should offer… and with minimum fuss and with a lot of standards and security. I wish everything I did was this easy.
From the blog
Posted 2005-03-24
Zippity Zoo Zah...
I've been wanting to improve — no, rewrite — my blogging software for a month
or more now. The more work I've done at work, the more efficiently I've felt I
could handle it. I've learned a lot of ins and outs with Cgiapp
and Cgiapp
superclasses, and figured out how to tie things together much better. However,
I've also noticed, in reading and analyzing blogs, that there are a lot of
standards that I just don't know enough about or simply don't have the time to
implement ("the more work I've done…" has been something like 70 hour weeks
recently). Things like trackbacks, and RSS/Atom feeds, and comment
moderation/blacklisting, etc. I certainly have the skills, but do I have the
time? Not really. I still have a goal of writing some lightweight blogging
software using Cgiapp
. However, for now, that's on hold so I can focus on
family, myself, and the next round of Cgiapp
improvements. In the meantime,
i've been seeing a lot of stuff about Serendipity, and I
thought I'd give it a try. Here are the results! It was super fast to setup,
and I hope to import all my old entries from my own system to it, once I can
see how entries are stored in the DB. So, you can now keep track of me via
RSS… Read away! Update: I'm liking S9y even more: it uses
Smarty for templating, which means I'm able to modify
it to look like it was always seamlessly in my site!
From the blog
Posted 2005-03-20
php|Tropics
Well, it's official: My IT Manager convinced those in the upper echelons (well, considering it's a non-profit with only around 20 employees, that meant the president and the CFO) that (1) he and I need to attend a PHP conference, (2) due to the amount of work we've been putting in to bring money into the organization, cost shouldn't be too much of a deciding factor, and (3) php|Tropics isn't too expensive, especially considering the sessions involved cover some of the very issues we've been struggling with the past few months (PHP/MySQL/Apache and clusters, PHP5 OOP, PHP Security, test-driven development, Smarty, and more).
So, we're going to Cancun in May!
This is incredibly exciting! I've never been to Mexico, nor even a resort, so I'll finally get to find out what my wife and friends have been talking about all these years. Plus, the conference is top-notch — many of the presenters are well-known in the PHP community, and have blogs I've been following for the past year. (I only wish that Chris Shiflett's PHP Security series wasn't running head-to-head with the PHP5 OOP Extensions and PHP 5 Patterns sessions; I suspect Rob and I will have to do a divide-and-conquer that day.)
Drop me a line if you'll be attending — I'm looking forward to meeting other PHP junkies!
From the blog
Posted 2005-02-19
New Cgiapp Site
I've been extremely busy at work, and will continue to be through the end of March. I realized this past week that I'd set a goal of having a SourceForge website up and running for Cgiapp by the end of January — and it's now mid-February. Originally, I was going to backport some of my libraries from PHP5 to PHP4 so I could do so… and I think that was beginning to daunt me a little.
Fortunately, I ran across a quick-and-dirty content management solution yesterday called Gunther. It does templating in Smarty, and uses a wiki-esque syntax for markup — though page editing is limited to admin users only (something I was looking for). I decided to try it out, and within an hour or so had a working site ready to upload.
Cgiapp's new site can be found at cgiapp.sourceforge.net.
UPDATE
Shortly after I wrote this original post, I figured out what the strength of Gunther was — and why I no longer needed it. Gunther was basically taking content entered from a form and then inserting that content (after some processing for wiki-like syntax) into a Smarty template. Which meant that I could do the same thing with Cgiapp and Text_Wiki. Within an hour, I wrote an application module in Cgiapp that did just that, and am proud to say that the Cgiapp website is 100% Cgiapp.
From the blog
Posted 2005-01-14
Cgiapp 1.5.3 released
1.5.3 fixes an issue introduced by 1.5.2 that creates a performance hit whenever the run mode is being determined by function name or CGI parameter. More details on the Cgiapp download page.
From the blog
Posted 2005-01-14
Cgiapp 1.5.2 released
At work, we've been developing a new platform for our website, based entirely on Cgiapp. This week we released the first stage of it: garden.org and assoc.garden.org. These should stand as good testament to Cgiapp's robustness!
With all that development, and also with some communication from other Cgiapp users, I've made some changes to Cgiapp, and release version 1.5.2 this evening.
1.5.2 is mainly security and bugfixes. Error handling was somewhat broken in
1.5.1 — it wouldn't restore the original error handler gracefully. This is now
corrected. Additionally, I've made run()
use the array returned by query()
—
consisting of the $_GET
and $_POST
arrays — in determining the run mode.
Finally, I've modified the behaviour of how run()
determines the current run
mode: if the mode parameter is a method or function name, it cannot be a
Cgiapp method or a PHP internal function. This allows more flexibility on
the part of the programmer in determining the mode param — words like 'run' and
'do' can now be used without causing massive problems (using 'run' would cause a
race condition in the past).
As usual, Cgiapp is available in the downloads area. Grab your tarball today!
From the blog
Posted 2004-12-31
Smarty $_SERVER vars
I don't know why I never bothered to look this up, but I didn't. One thing I
typically do in my parent Cgiapp classes is to pass $_SERVER['SCRIPT_NAME']
to the template. I just found out — through the pear-general newsgroup — that
this is unnecessary: use $smarty.server.KEY_NAME
to access any $_SERVER
vars
your template might need.
From the blog
Posted 2004-11-04
Cgiapp mentioned in php|architect!
A new Cgiapp user reported they had stumbled across the project in php|architect! It's in the current, October 2004 issue, in the News section, prominently displayed in the upper right corner of the page. The announcement blurb is straight from my freshmeat project page for version 1.4. Cgiapp is carving a name for itself!
From the blog
Posted 2004-11-04
Cgiapp 1.5.1 released
At work this week, I discovered a bug with how I was calling
set_error_handler()
in Cgiapp's run()
method. Evidently passing a reference
in a PHP callback causes issues! So, I corrected that.
I also made a minor, one-character change to query()
to make it explicitly
return a reference to the $_CGIAPP_REQUEST
property array.
You can see full details at the Cgiapp download page.
From the blog
Posted 2004-10-28
Cgiapp 1.5 released
Cgiapp 1.5 has been released; you may now download it.
This release fixes a subtle bug I hadn't encountered before; namely, when a
method name or function name is passed as an argument to mode_param()
, run()
was receiving the requested run mode… and then attempting to process that as the
mode param. The behaviour is now fixed, and is actually simpler than the
previous (non-working) behaviour.
Also, on reading Chris Shiflet's paper on PHP security, I
decided to reinstate the query()
method. I had been using $_REQUEST
to check
for a run mode parameter; because this combines the $_GET
, $_POST
, and
$_COOKIE
arrays, it's considered a bit of a security risk. query()
now
creates a combined array of $_GET
and $_POST
variable ($_POST
taking
precedence over $_GET
) and stores them in the property $_CGIAPP_REQUEST
; it
returns a reference to that property. run()
uses that property to determine
the run mode now.
Enjoy!
From the blog
Posted 2004-10-22
When array_key_exists just doesn't work
I've been playing with parameter testing in my various Cgiapp classes, and one test that seemed pretty slick was the following:
if (!array_key_exists('some_string', $_REQUEST)) {
// some error
}
Seems pretty straight-forward: $_REQUEST
is an associative array, and I want
to test for the existence of a key in it. Sure, I could use isset()
, but it
seemed… ugly, and verbose, and a waste of keystrokes, particularly when I'm
using the param()
method:
if (!isset($_REQUEST[$this->param('some_param')])) {
// some error
}
However, I ran into a pitfall: when it comes to array_key_exists()
,
$_REQUEST
isn't exactly an array. I think what's going on is that $_REQUEST
is actually a superset of several other arrays — $_POST
, $_GET
, and
$_COOKIE
— and isset()
has some logic to descend amongst the various keys,
while array_key_exists()
can only work on a single level.
Whatever the explanation, I ended up reverting a bunch of code. :-(
From the blog
Posted 2004-10-12
PHP_SELF versus SCRIPT_NAME
I've standardized my PHP programming to use the environment variable
SCRIPT_NAME
when I want my script to refer to itself in links and form
actions. I've known that PHP_SELF
has the same information, but I was more
familiar with the name SCRIPT_NAME
from using it in perl, and liked the feel
of it more as it seems to describe the resource better (PHP_SELF
could stand
for the path to the PHP executable if I were to go by the name only).
However, I just noticed a post on the php.general newsgroup where somebody asked
what the difference was between them. Semantically, there isn't any; they should
contain the same information. However, historically and technically speaking,
there is. SCRIPT_NAME
is defined in the CGI 1.1 specification, and is thus a
standard. However, not all web servers actually implement it, and thus it
isn't necessarily portable. PHP_SELF
, on the other hand, is implemented
directly by PHP, and as long as you're programming in PHP, will always be
present.
Guess I have some grep and sed in my future as I change a bunch of scripts…
From the blog
Posted 2004-10-08
PHP: Continue processing after script aborts
Occasionally, I've needed to process a lot of information from a script, but I don't want to worry about PHP timing out or the user aborting the script (by clicking on another link or closing the window). Initially, I investigated register_shutdown_function() for this; it will fire off a process once the page finishes loading. Unfortunately, the process is still a part of the current connection, so it can be aborted in the same way as any other script (i.e., by hitting stop, closing the browser, going to a new link, etc.).
However, there's another setting initialized via a function that can override this behaviour — i.e., let the script continue running after the abort. This is ignore_user_abort(). By setting this to true, your script will continue running after the fact.
This sort of thing would be especially good for bulk uploads where the upload needs to be processed — say, for instance, a group of images or email addresses.
From the blog
Posted 2004-10-07
Practical PHP Programming
In the past two days, I've seen two references to Practical PHP Programming, an online book that serves both as an introduction to programming with PHP5 and MySQL as well as a good advanced reference with many good tips.
This evening, I was browsing through the Performance chapter (chapter 18), and
found a number of cool things, both for PHP and MySQL. Many were common sense
things that I've been doing for a while, but which I've also seen and shaken my
head at in code I've seen from others (calculating loop invariables at every
iteration, not using variables passed to a function, not returning a value from
a function, not using a return value from a function). Others were new and gave
me pause for thought (string concatenation with the '.' operator is expensive,
especially when done more than once in an operation; echo
can take a comma
separated list).
Some PHP myths were also dispelled, some of which I've been wondering about for awhile. For instance, the amount of comments and whitespace in PHP are not a factor in performance (and PHP caching systems will often strip them out anyways); double quotes are not more expensive than single quotes unless variable interpolation occurs.
It also has some good advice for SQL optimization, and, more importantly, MySQL
server optimization. For instance, the author suggests running OPTIMIZE TABLE table;
on any table that has been added/updated/deleted from to any large
extent since creation; this will defrag the table and give it better
performance. Use CHAR()
versus VARCHAR()
; VARCHAR()
saves on space, but
MySQL has to calculate how much space was used each time it queries in order to
determine where the next field or record starts. However, if you have any
variable length fields, you may as well use as many as you need — or split off
variable length fields (such as a TEXT()
field) into a different table in
order to speed up searching. When performing JOIN
s, compare on numeric fields
instead of character fields, and always JOIN
on rows that are indexed.
I haven't read the entire book, but glancing through the TOC, there are some potential downfalls to its content:
- It doesn't cover PhpDoc It doesn't appear to cover unit testing Limited
- coverage of templating solutions (though they are mentioned) Limited usage of
- PEAR. The author does mention PEAR a number of times, and
often indicates that use of certain PEAR modules is preferable to using the
corresponding low-level PHP calls (e.g.,
Mail
andMail_MIME
,DB
), but in the examples rarely uses them. - PHP-HTML-PHP… The examples I browsed all created self-contained scripts that did all HTML output. While I can appreciate this to a degree, I'd still like to see a book that shows OOP development in PHP and which creates re-usable web components in doing so. For instance, instead of creating a message board script, create a message board class that can be called from anywhere with metadata specifying the database and templates to use.
All told, there's plenty of meat in this book — I wish it were in dead tree format already so I could browse through it at my leisure, instead of in front of the computer.
From the blog
Posted 2004-09-21
Cgiapp Roadmap
I've had a few people contact me indicating interest in Cgiapp, and I've noticed
a number of subscribers to the freshmeat project I've setup. In addition, we're
using the library extensively at the
National Gardening Association in developing our new
site (the current site is using a mixture of ASP and Tango, with several newer
applications using PHP). I've also been monitoring the CGI::Application
mailing list. As a result of all this activity, I've decided I need to develop a
roadmap for Cgiapp.
Currently, planned changes include:
-
Version 1.x series:
- Adding a Smarty registration for
stripslashes
(the Smarty "function" call will besslashes
). -
param()
bugfix: currently, callingparam()
with no arguments simply gives you a list of parameters registered with the method, but not their values; this will be fixed. -
error_mode()
method. TheCGI::Application
ML brought up and implemented the idea of anerror_mode()
method to register anerror_mode
with the object (similar torun_modes()
). While non-essential, it would offer a standard, built-in hook for error handling. -
$PATH_INFO
traversing. Again, on theCGI::App
ML, a request was brought up for built-in support for using$PATH_INFO
to determine the run mode. Basically, you would pass a parameter indicating which location in the$PATH_INFO
string holds the run mode. - DocBook tutorials. I feel that too much information is given in the class-level documentation, and that usage tutorials need to be written. Since I'm documenting with PhpDoc and targetting PEAR, moving tutorials into DocBook is a logical step.
- Adding a Smarty registration for
-
Version 2.x series:
Yes, a Cgiapp2 is in the future. There are a few changes that are either necessitating (a) PHP5, or (b) API changes. In keeping with PEAR guidelines, I'll rename the module Cgiapp2 so as not to break applications designed for Cgiapp.
Changes expected include:
-
Inherit from PEAR. This will allow for some built in error handling, among other things. I suspect that this will tie in with the
error_mode()
, and may also deprecatecroak()
andcarp()
. -
Changes to
tmpl_path()
andload_tmpl()
. In the perl version, you would instantiate a template usingload_tmpl()
, assign your variables to it, and then do yourfetch()
on it. So, this:$this->tmpl_assign('var1', 'val1'); $body = $this->load_tmpl('template.html');
Becomes this:
$tmpl = $this->load_tmpl(); $tmpl->assign('var1', 'val1'); $body = $tmpl->fetch('template.html');
OR
$tmpl = $this->load_tmpl('template.html'); $tmpl->assign('var1', 'val1'); $body = $tmpl->fetch();
(Both examples assume use of Smarty.) I want to revert to this behaviour for several reasons:
-
Portability with perl. This is one area in which the PHP and perl versions differ greatly; going to the perl way makes porting classes between the two languages simpler.
-
Decoupling. The current set of template methods create an object as a parameter of the application object — which is fine, unless the template object instantiator returns an object of a different kind.
Cons:
-
Smarty can use the same object to fill multiple templates, and the current methods make use of this. By assigning the template object locally to each method, this could be lost. HOWEVER… an easy work-around would be for
load_tmpl()
to create the object and store it an a parameter; subsequent calls would return the same object reference. The difficulty then would be ifload_tmpl()
assumed a template name would be passed. However, even inCGI::App
, you decide on a template engine and design for that engine; there is never an assumption that template engines should be swappable. -
Existing Cgiapp1 applications would need to be rewritten.
-
-
-
Plugin Architecture: The
CGI::App
ML has produced a::Plugin
namespace that utilizes a common plugin architecture. The way it is done in perl is through some magic of namespaces and export routines… both of which are, notably, missing from PHP.However, I think I may know a workaround for this, if I use PHP5: the magic
__call()
overloader method.My idea is to have plugin classes register methods that should be accessible by a Cgiapp-based class a special key in the
$_GLOBALS
array. Then, the__call()
method would check the key for registered methods; if one is found matching a method requested, that method is called (usingcall_user_func()
), with the Cgiapp-based object reference as the first reference. Voilá! instant plugins!Why do this? A library of 'standard' plugins could then be created, such as:
- A form validation plugin
- Alternate template engines as plugins (instead of overriding the
tmpl_*
methods) - An authorization plugin
Since the 'exported' methods would have access to the Cgiapp object, they could even register objects or parameters with it.
-
If you have any requests or comments on the roadmap, please feel free to contact me.
From the blog
Posted 2004-09-20
New site is up!
The new weierophinney.net/matthew/ site is now up and running!
The site has been many months in planning, and about a month or so in actual coding. I have written the site in, instead of flatfiles, PHP, so as to:
- Allow easier updating (it includes its own content management system)
- Include a blog for my web development and IT interests
- Allow site searching (everything is an article or download)
I've written it using a strict MVC model, which means that I have libraries for accessing and manipulating the database; all displays are template driven (meaning I can create them with plain-old HTML); and I can create customizable applications out of various controller libraries. I've called this concoction Dragonfly.
There will be more developments coming — sitewide search comes to mind, as well as RSS feeds for the blog and downloads.
Stay Tuned!
From the blog
Posted 2004-09-04
PHP and Template Engines
On PhpPatterns, I recently read an article on Template Engines in PHP. It got my ire up, as it said (my interpretation):
- "template engines are a bad idea"
- "templating using PHP natively can be a good idea"
- "template engines… are not worth the text their written in"
Okay, so that's actually direct quotes from the article. I took issue with it, immediately — I use Smarty for everything I do, and the decision to do so was not done lightly. I have in fact been advocating the use of template engines in one language or another for several years with the various positions in which I've been employed; I think they are an essential tool for projects larger than a few pages. Why?
- Mixing of languages causes inefficiency. When I'm programming, it's incredibly inefficient to be writing in up to four different languages: PHP or Perl, X/HTML, CSS, and Javascript. Switching between them while in the same file is cumbersome and confusing, and trying to find HTML entities buried within quoting can be a nightmare, even when done in heredocs. Separating the languages into different files seems not only natural, but essential.
- Views contain their own logic. In an MVC pattern, the final web page View may be dependent on data passed to it via the Controller; however, this doesn't mean that I want the full functionality of a language like PHP or Perl to do that. I should only be doing simple logic or looping constructs — and a full scripting language is overkill. (I do recognize, however, that template engines such as Smarty are written using PHP, so the language is being invoked regardless. What I speak of here is the language used to compose the template.)
- Abstraction and Security. The fewer internals that are divulged on the template page, the better. For security purposes, I may not want clients able to know how data got to the page, only what data is available to them. In addition, if this data is abstracted enough, any number of backends could be connected to the page to produce output.
So, reading the aforementioned article really got my hackles up. However, it got me thinking, as well. One issue raised is that PHP can be used as your templating language. While I can understand why this might be desirable — everything from load issues to flexibility — I also feel that this doesn't give enough abstraction.
Using PHP seems to me to be inefficient on two fundamental levels, based on my understanding of The Pragmatic Programmer:
- Domain Langauge. The Pragmatic Programmer suggests that subsets of a language should be used, or wholly new mini-languages developed, that speak to the domain at hand. As an example, you might want to use a sharp tool to open a can; an axe would be overkill, but a knife might work nicely. Using PHP to describe a template is like using an axe to open a can; it'll do the job, but it may also make a mess of it all, simply because it's too much sharp edge for the job.
- Metadata. Metadata is data about data; to my thinking, templates describe the data they are communicating; the compiled template actually contains the data. In this regard, again, putting PHP into the script is overkill as doing so gives more than just some hints as to what the data is.
The author of the article also makes a case for teaching web designers PHP — that the language is sufficiently easy to pick up that they typically will be able to learn it as easily, if not more easily, than a template language. I agree to a degree… But my experience has shown that web designers typically struggle with HTML, let alone PHP. (Note: my experience in this regard is not huge, and I'm sure that this is an exaggeration.) I find that it's typically easiest for me to give an example template, explain what the funny, non-HTML stuff can do, and let them go from there. Using this approach, they do not need to learn anything new — they simply work with placeholders.
Still, I think the author raises some fine points. I wish he'd bothered to do more research into why people choose template engines and the benefits that arise from using them before simply outright slamming them. Of course, the article is also a bit dated; it was written over two years ago, and much has changed in the world of PHP and many of its template engines. I'm curious as to whether they would feel the same way today.
Me? My mind is made up — the benefits, in my circumstances, far outweigh any costs associated. I'll be using template engines, and Smarty in particular, for years to come.
From the blog
Posted 2004-03-30
Cgiapp: A PHP Class
After working on some OO classes yesterday for an application backend I'm
developing for work, I decided I needed to create a BREAD
class to make this
simpler. You know, Browse-Read-Edit-Add-Delete.
At first, I figured I'd build off of what I'd done yesterday. But then I got to
thinking (ah, thinking, my curse). I ran into the BREAD
concept originally
when investigating CGI::Application
; a number of individuals had developed
CGI::Apps
that provided this functionality. I'd discarded them usually because
they provided more functionality than I needed or because they introduced more
complexity than I was willing to tackle right then.
But once my thoughts had gone to BREAD
and CGI::App
, I started thinking how
nice it would be to have CGI::Application
for PHP. And then I thought, why
not? What prevents me from porting it? I have the source…
So, today I stayed home with Maeve, who, on the tail end of an illness,
evidently ran herself down when at daycare yesterday, and stayed home sleeping
most of the day. So, while she was resting, I sat down with a printout of the
non-POD code of CGI::App
and hammered out what I needed to do. Then, when she
fell asleep for a nap, I typed it all out and started testing. And, I'm proud to
say, it works. For an example, visit
my development site to see a
very simple, templated application in action.
From the blog
Posted 2004-03-28
POD for PHP
I was lamenting at work the other day that now that I've discovered OO and templating with PHP, the only major feature missing for me is a way to easily document my programs. I'm a big fan of perl's POD, and use it fairly extensively, even for simple scripts — it's a way to provide a quick manual without needing to worry too much about how to format it.
So, it hit me on the way home Friday night: what prevents me from using POD in multiline comments of PHP scripts? I thought I'd give it a try when I got home.
First I googled for 'POD for PHP', and found a link to perlmongers where somebody recounted seeing that exact thing done, and how nicely it worked.
Then I tried it… and it indeed worked. So, basically, I've got all the tools I love from perl in PHP, one of which is borrowed directly from the language!
From the blog
Posted 2004-03-28
Scrap that. We're gonna' use PHP
I've been researching and coding for a couple months now with the decision that
I'd rewrite the family website/portal using mod_perl
with CGI::Application
.
I still like the idea, but a couple things recently have made me rethink it.
For starters, the perl DBI is a bit of a pain to program. At work, I've become very accustomed to using PEAR's DB library, and while it's in many ways derived from perl's DBI, it's much simpler to use.
Then there's the whole HTML::Template
debacle. There's several ways in which
to write the templates, but they don't all work in all situations, and, it seems
they're a bit limited. We've started using PHP's Smarty at work, and it's much
more intuitive, a wee bit more consistent, and almost infinitely more
extendable. I could go the Template::Toolkit
route for perl, but that's almost
like learning another whole language.
Then, there's the way objects work in perl versus PHP. I've discovered that PHP objects are very easy and very extendable. I wouldn't have found them half as easy, however, if I hadn't already been doing object oriented programming in perl. One major difference, however, is how easy it is to create new attributes on the fly, and the syntax is much easier and cleaner.
Add to that the fact that if you want to dynamically require modules in perl,
you have to go through some significant, often unsurmountable, hoops. So you
can't easily have dynamic objects of dynamically defined classes. In PHP,
though, you can require_once
or include_once
at any time without even
thinking.
The final straw, however, was when I did my first OO application in PHP this
past week. I hammered it out in a matter of an hour or so. Then I rewrote it to
incorporate Smarty in around an hour. And it all worked easily. Then I wrote a
form-handling libary in just over two hours that worked immediately — and made
it possible for me to write a several screen application in a matter of an hour,
complete with form, form validation, and database calls. Doing the same with
CGI::Application
took me hours, if not days.
So, my idea is this: port CGI::Application
to PHP. I love the concept of
CGI::App
— it's exactly how I want to program, and I think it's solid.
However, by porting it to PHP, I automatically have session and cookie support,
and database support is only a few lines of code away when I use PEAR; I'll add
Smarty as the template toolkit of choice, but make it easy to override the
template methods to utilize . I get a nice MVC-style application template, but
one that makes developing quickie applications truly a snap.
This falls under the "right-tool-for-the-job" category; perl, while a wonderful language, and with a large tradition as a CGI language, was not developed for the web as PHP was. PHP just makes more sense in this instance. And I won't be abandoning perl by any stretch; I still use it daily at work and at home for solving any number of tasks from automated backups to checking server availability to keeping my ethernet connection alive. But I have real strengths as a PHP developer, and it would be a shame not to use those strengths with our home website.
From the blog
Posted 2004-03-19
PHP Class Tips
We're starting to use OO in our PHP at work. I discovered when I started using it why I'd been having problems wrapping my head around some of the applications I've been programming lately: I've become accustomed in Perl to using an OO framework. Suddenly, programming in PHP was much easier.
There's a few things that are different, however. It appears that you cannot pass objects in object attributes, and then reference them like thus:
$object->db>query($sql)
PHP doesn't like that kind of syntax (at least not in versions 4.x). Instead, you have to pass a reference to the object in the attribute, then set a temporary variable to that reference whenever you wish to use it:
$object->db =& $db;
...
$db = $object->db;
$res = $db->query($sql);
What if you want to inherit from another class and extend one of the methods? In
other words, you want to use the method from the parent class, but you want to
do some additional items with it? Simple: use parent
:
function method1()
{
/* do some pre-processing */
parent::method1(); // Do the parent's version of the method
/* do some more stuff here */
}
Update:
Actually, you can reference objects when they are attributes of another object; you just have to define the references in the correct order:
$db =& DB::connect('dsn');
$this->db =& $db;
...
$res = $this->db->query($sql);
I've tested the above syntax with both PEAR's DB and with Smarty, and it works without issue.
From the blog
Posted 2004-01-23
IT hiring principles
I was just reading an article about the Dean campaign's IT infrastructure, and there's an interesting quote from their IT manager, Harish Rao:
"I believe in three principles", he said. "First I always make sure I hire people I can trust 100%. Second, I always try to hire people who are smarter than I am. Third, I give them the independence to do as they see fit as long as they communicate about it to their other team members. We've had a lot of growing pains, a lot of issues; but we've been able to deal with them because we have a high level of trust, skill and communication."
I know for myself that when I (1) don't feel trusted, and/or (2) am not given independence to do what I see as necessary to do my job, I don't communicate with my superiors about my actions, and I also get lazy about my job because I don't feel my work is valued.
Fortunately, I feel that in my current work situation, my employers followed the same principles as Rao, and I've felt more productive and appreciated than I've felt in any previous job.
From the blog
Posted 2004-01-22
PHP standards ruminations
I've been thinking about trying to standardize the PHP code we do at work. Rob and I follow similar styles, but there are some definite differences. It would make delving into eachother's code much easier if we both followed some basic, agreed upon, guidelines.
One thing I've been thinking about is function declarations. I find that I'm often retooling a function to make it more general, and in doing so either need to decrease or increase the number of arguments to it. This, of course, breaks compatability.
So I propose that we have all functions take two arguments: $data
and $db
. $data
is a hash which can then be extract
'd via PHP. To change the number of arguments, you can simply set defaults for arguments or return meaningful errors for missing arguments.
Another thought going through my mind deals with the fact that we reuse many of our applications across our various sites, and also export some of them. I think we should try and code the applications as functional libraries or classes, and then place them somewhere in PHP's include path. We can then have a "demo" area that shows how to use the libraries/classes (i.e., example scripts), and to utilize a given application, we need simply include it like: include 'apps/eventCalendar/calendar.inc';
. This gives us maximum portability, and also forces us to code concisely and document vigorously.
I was also reading on php.general tonight, and noticed some questions about PHP standards. Several people contend that PEAR is becoming the de facto standard, as it's the de facto extension library. In addition, because it is becoming a standard, there's also a standard for documenting projects, and this is phpdocumenter. The relevant links are:
Search tips
- Use
#{some tag}
ortag:{some tag}
to filter by tag; using this more than once will find results that match all tags. - Use
year:{year}
to filter by year. If you use this multiple times, the last one wins. - Use
begin:{year-month-day}
to restrict to results beginning on that day. Last one wins. - Use
end:{year-month-day}
to restrict to results ending on that day. Last one wins.