Archive for the 'PHP' Category

Zend_Console_Process

Posted April 27, 2008, 9:11pm In: Zend Framework, PHP

Rarely do I get excited about a Zend proposal - and I definitely don’t post about the ones in progress on my blog. However, Zend_Console_Process deserves some attention.

If you’re at all familiar with pcntl this is for you. Pcntl allows you to control processes from within PHP (essentially allowing you to run threaded PHP code; fake “real” threading, at least). Zend_Console_Process is a Zend style interface to create threaded PHP applications in a usable manner.

If you take a gander at Ben’s first example, you’ll see the advantages:

Now, there’s been some interesting discussion on the mailing list already. For instance:

… Calling this “Threading” is a major misnomer. Threading would imply it has access to the same address space and descriptor table. That is not the case if this uses fork…

-Michael

Good point; so don’t take anything you read on the ZF site (actually, anywhere on the internet for that matter) as divine writ.

Like I said in my last post, it’s all about choosing the right technology. If you need to resize a couple dozen images, this will do you fine. If you need to build a video trans-coding server that can handle hundreds of videos at a time, well… perhaps it is time to choose a different language to do your heavy lifting. The fact that it doesn’t work on windows is a large hit to the adoption of Zend_Console_Process, but in my humble opinion, it is the most interesting proposal to come into review status since Zend_Service_Amazon_S3.

Handling Large(5GB+) File Uploads

Posted April 24, 2008, 9:25pm In: PHP, Development

A couple days ago I met with a potential client who posed an interesting challenge. He wanted to upload very large files (upwards of 6GB-7GB) to his server using PHP. I told him it was possible, but I don’t recommend it. There’s a few reasons why.

One of the biggest problems I have with most web applications is file uploads. As a developer, I rarely need to upload anything larger than, say, 100MB - this covers a lot of code files, libraries and so forth. Generally, in an OOP world, if a file is larger than a couple megabytes you’re probably doing something wrong anyways.

But, I’m a developer. I work with people on a daily basis that aren’t developers. Hi-res photos, PSDs, even digital media files such as AVIs & MOVs, are something that should be considered when building an application. A complicated PSD, for instance, can easily grow upwards of two gigabytes.

And therein lies the problem.

Let’s face it, PHP, for all its glory, is quite simply, not the best language for uploading files. This is a three pronged problem. The first is PHP, which I’ll elaborate on. The second is HTTP. HTTP is just not suitable for receiving large files; don’t get me wrong, it’s possible, but I question the wisdom. The third is actually client based - it takes time to upload a file, and most people I know (especially non-web savvy folk) get irritated when it doesn’t work immediately.

Let’s take, for instance, what most people do to get around the upload problem by overriding the PHP default limit. Formerly, you could set these variables using ini_set() and ini_restore(), but some of the overrides are no longer available through these methods. You can use a php.ini file, set the options directly but chances are you do something like this, via an .htaccess file.

Make no mistake, this is bad, and a potential security hole. Why? Because someone could easily setup a denial of service attack and bring your servers to its knees.

Addressing the Problem

Okay, so now that I’ve said that uploading files as big as we’re talking is a bad idea, what’s the solution?

First, address the HTTP problem. We’ve got several options, but something I found a few years ago is very promising. Take the challenge outside PHP.

Meet Tramline (http://infrae.com/products/tramline), an upload and download accelerator that plugs into Apache. Using mod_python, it provides a direct means to bypass PHP altogether and hook into Apache. A bit more security tweaking and it is an acceptable solution. There’s more alternatives too. Curl, WebDAV, Java, Streams, Python and Perl to name a few.

At this point, it is fair to say that one should choose the right tools for the right job. This is also true with the client upload problem. It is completely unacceptable to use a file control, have the user hit submit and expect them to wait there for five minutes or more. That said, there are alternatives. SWFUpload, YUI Uploader and various other Javascript methods as well, and with a bit of tweaking I’m sure they could be modified to utilize a service.

6GB-7GB? Easy. Just don’t stick to your PHP guns.

I’m interested to hear how other folks have handled large file uploads.

Drag & Drop Form Options with Zend Framework & Mootools

Posted January 31, 2008, 10:04am In: Zend Framework, SQL, Javascript, PHP

Recently I was working on a project that required the ability to define custom meta-data; this included categories and products, but also included a pre-determined list of countries and cities, etc.

Unfortunately, this hasn’t been tested on the latest version of the Zend Framework so it’s likely you’ll need to update your code accordingly.

We’re using version 1.2dev of MooTools

First, let’s create the controller:

I’ll skip the creation of fields and get right into the editing; I assume you’ve already added an index action and view. Our purpose is to effectively manage and modify field options, provide the ability to sort, edit and delete them, while preserving data related to the individual fields. For clarity, I will not use the view helpers for Form Elements.

Create your form and save it into your view, in my case edit-fields.php. I’ll leave it up to you to style and set form actions etc.

Then, pre-pend your javascript:

Now, before we get ahead of ourselves and worry about finding the fields, let’s the information and fields themselves - edit editFieldsAction() in your controller with the following:

Now let’s create our factory, in my case it’s MyFactory.php.

MyDomainObject::FetchCategory() validates that the requested categoryId exists. Then, the values assigned to that category. We could use $record->fetchValues() from within the rowClass instead of $obj->fetchValues($record->id), but it would more than likely just be an alias back to the factory.

Now, let’s open edit-fields.php again and add the following PHP between the UL.

An improvement to this would be to add an observer to all hyperlinks identified by class=”red”, but for simplicity, let’s leave that out. Now, our view should look something like this:

Assuming everything works, what should happen now is the list should pre-populate with previously created configuration options, we should be able to add, edit and delete those, and $_POST will override $this->options. Let’s start saving!

Edit editFieldsAction() to add some new functionality:

Now, back inside MyFactory:

It’s extra important that you pay attention to the usage of “ON DUPLICATE KEY UPDATE” - this is why we don’t have to do any fancy dancing. Additionally, we find the difference from $postArray versus what exists in the database to ensure that we delete anything that the user doesn’t want any more.

Additional steps might include the deletion of our user data when a config_value is deleted, either modifying the code itself or using the database.

Personal Programming Faux Pas & Standards

Posted August 1, 2007, 2:53pm In: PHP

At risk of starting a holy war, I’ve noticed myself cringing every time I look at a block of code that isn’t formatted, or consists of slow functions… I decided to write a brief list of my pet peeves. Feel free to add!

Formatting

I prefer to use tabs (\t) rather than spaces to indent my code. Nested loops, decision blocks et cetera should all be indented with one tab per indent. Software such as the Zend Framework requires four spaces. This is completely up to you.

Optimization: Loops

One of the biggest issues I have with my fellow developers is not paying attention to optimization within loops. Consider, for instance, this example:

Always try to optimize your loops if operations are going on at the comparing part, since this part is executed every time the loop is parsed through. For assignments a descriptive name should be chosen. A correct example might be:

Now, take it one step further:

This is a minor detail, but pre-decrement (and increment) operators are faster than post-decrement (and increment). Post requires the compiler to create a duplicate of the variable and copy the updated value back at the end, while a pre-operation can be done in-place immediately.

Optimization: in_array();

Avoid using in_array() on huge arrays. Make an effort not place them into loops, especially if the array being evaluated consists of more than 30 or so entries. in_array() can be very CPU intensive. Instead, try using isset() on the arrays keys instead. A call to isset($myArray[$var]) is a lot faster than in_array($var, array_keys($myArray)).

Space your tokens

I loathe trying to sift through code I can’t read; it should read like the English language (yaknow, top to bottom, left to right?) Always leave one space between the tokens. Don’t put spaces just after an opening bracket or before a closing bracket. Don’t put spaces just before a comma or a semicolon. Again, just my personal preference, but I’m used to browbeating my subordinates. It’s the only way they know me as the Omnipotent Dark Lord.

Operator precedence

There is an exact precedence to all the operators in PHP, but I don’t recommend trying to guess them all. Use brackets to force the precedence of an comparison or equation so you know what it does.

Ternary Operators

Try not to sacrifice readability by saving yourself a few keystrokes. Ternary operators should generally be used for comparison, not complex logic.

Code Formating: If/Else

Braces must always be used. Braces always go on their own line. The closing brace should also always be at the same column as the corresponding opening brace.

Switch Statements

Switch statements are extremely useful, but can get a fair bit long. Akin to in-line braces, do not indent breaks.

In Closing…

These are just my personal opinions, based on my own ideologies. Everyone has their own preference on how code should look, but I do recommend paying special attention to the optimization tips.

Suggestions, comments and death threats always welcome!

Zend Framework and YAML config files

Posted July 13, 2007, 8:41am In: Zend Framework, PHP

Shahar has a post about using Zend_Config and YAML.

http://prematureoptimization.org/blog/archives/39/

<3 __autoload

Posted February 21, 2007, 9:03am In: Zend Framework, PHP

When developing with the Zend Framework, it’s been my experience that the majority of our class files have a myriad of require statements before the class declaration. There are cases where these requires are not needed.

PHP 5.2.1 brings us all sorts of new goodies, one of them being the method spl_autoload_register(), part of the Standard PHP Library. When we tie this in with Zend::loadClass(), we can load our class files as needed.

Though there is some question about problems with application servers and things like bytecode caching, this gives us the added benefit of enforcing consistency in class naming - with consistency comes predictability, and saves us from having to RTFM, or double check our directory structure every time to find the proper file.

Though I am using this autoload method, I want to make sure that it is not slowing my applications down - there is quite some heated discussion on using auto-magical methods versus carefully crafted include statements. I’ll be paying very close attention to my dispatch times, and time will tell if I continue using this method.

Prototype + Zend = Good times

Posted January 18, 2007, 3:56pm In: Zend Framework, Javascript, PHP

So a quick update;

Prototype, the Javascript Library we know and love, has a new homepage at http://prototypejs.org/

And the Zend Framework has a brand new version out after last nights code freeze at http://framework.zend.com/