Category: "PHP"

Why I consider (MVC) Smarty templating inefficient

Most PHP developers (and other web developpers too) seem to evolve on a similar path which goes like this:

Step 1: take HTML pages an add PHP tags into them.

Step 2: Realize that on a large scale this is getting very hard to maintain.

Step 3: Learn about the MVC (Model View Controller) paradigm and begin to think it's cool.

Step 4: Use Smarty or another templating engine like that.

The way most of those templating engines work is basically this:
a) Do a ton of PHP processing in the framework and fill in variables.
b) Call smarty and let it fill in variables in a template.
c) Send the output.

The issue here is that during steps a and b, nothing is sent back to the user. The user is just waiting for a response. Sadly enough, steps a and b will take a lot of precessing time. So the user will wait quite a long time before he gets any feedback on his action.

Even worse, when the application gets bigger, step a will take even more time!
And the more complex page you request, the more time you'll be left in the dark...

This is why I don't like all those mainstream templating engines. I want to send output back to the user as soon as possible. I want to send the page header at the begining of step a. And as soon as something has been processed and is ready for display, I want to send it out.

The global processing time will be approximately the same, but if the user sees content begining to display immediately, instead of all the content displaying at once 2 seconds after clicking, he will get the (false but humanely useful) impression that the application is faster. (Please do not say AJAX here, it is so not my point :P)

I'm not saying MVC is a bad paradigm, I'm saying most implementations of MVC are flawed, and Smarty is the most common example of this in PHP. Because they do the M & C stuff and then they do the V (view) stuff at the end. In my opinion they definitely need to interleave all this a lot more.

In evoCore (b2evolution's framework) our approach is to have the Controller really control the processing flow. In other words: for every block of information the View wants to display, the Control will process data from the Model and immediately pass it to the View in order to display the result block by block.

Of course, this has drawbacks: you won't be able to change the block order of the output if it's hard coded into the Controller. But really, that's okay to some extent. Who really needs to move the global header and the global footer for example? This is what we use for the back-office.

However, for the front-office, we want more customization, and we want people to be able to rearrange blocks in any order. In this case we have a little more complex processing, where the View actually calls the controller everytime it needs to display something.

Anyway, in any situation, my point is: the View should not be handled last.

PHP Variable names, Member names, Class names

I have just extended my PHP coding standard guidelines with these rules about variable naming:

  • Remember this is PHP, not Microsoft Visual C++. There is actually little value in naming variables something like strFullTitle . Something like full_title is definitely enough and much easier to read!

  • As an exception to the previous rule, we'll preferably prefix private or protected member variables of a class with an underscore as in _full_title. This serves as an easy reminder that the variable is not designed to be called in any other ways as in $this->_full_title .
  • Class names should start with a capital, as in Book .
  • Variable names should be all lowercase, as in $title = 'A brand new day'; except when they are object references as in:

    $a_Book = & new Book( 'A brand new day' );
  • When naming object references, always end their name with the name of the class as in $a_Book or $another_Book instead of Book_to_read for example. This allows to easily search & find all calls to a given method of a given class. You could for exampel easily search on this string: "Book->get_title(" .

Another lousy PHP/MySQL /charset issue...

We had this quite interesting situation at work today: I export an UTF-8 MySQL database into an UTF_8 SQL file. I *binary* FTP the file over to him. He plays the SQL in PHPmyAdmin all configured for UTF-8. He then checks the data in PHPmyAdmin: special chars display right under an UTF-8 page encoding. He checks under the command line: the DB contents seem to be UTF-8 encoded too...

Now he goes to our app, pulls out some data... and gets a special chars mess... although the html page is displayed as UTF-8. If we force the display to Latin-1, the special chars display correctly again.

The reason for this is that there is actuallly a charset translation taking place between the mysql client (which is PHP here) and the mysql server.

We found we could fix this by editing my.cnf and specifying the following:

# The default character set that will be used when a new schema or table is
# created and no character set is defined
default-character-set=utf8

...instead of the latin-1 he had there for some obscure reason.

However, there must be a more explicit way to have PHP retrieve the mysql data as UTF-8, even though we could not find that in mysql_connect() or somethig alike.

Guess, we'll have to investigate the PhpMyAdmin code and see how those guys do it. Btw, this reminds me of a conference by Rasmus Lerdorf where he said the code for PhpMyAdmin was pretty clean and should be studied. Yep, we definitely gotta do that! ;)

Using PHP 4.3.8 with MySQL 4.1

Running an app under PHP 4.3.8 and trying to connect to a MySQL 4.1 database can be pretty frustrating. By default it gives you a message like this:

"Client does not support authentication protocol requested by server; consider upgrading MySQL client".

The problem is that by default PHP's MySQL module is compiled with an older MySQL client library. MySQL has a manual page about this.

I use the OLD_PASSWORD method. I connect to MySQL under root with MySQL Query Browser and I issue the following command:

set password for 'demouser' = old_password('demopass');

PHP Output buffering and ob_handlers

PHP has some nice features to do output buffering. You just call ob_start() and anything you output (except headers) does not actually get set back to the webserver (and thus the browser) until you decide it. As the manual puts it "This can be useful in several different situations, especially if you need to send headers to the browser after your script has began outputting data."

One particular use of this feature is to pass an "ob_handler" callback function as an argument to ob_start(). This is supposed to let you do "kewl" post-processing operations like: gzip compression, adding an ETag, adding content-length of your whole output.

Crap!

There are only two situations where ob_handlers are useful:

  • When your webserver can't take care of this for you. But you know, you should really consider switching to Apache, which already has modules to handle all that, and even better: unlike PHP ob_handlers, it can do gzip compression progressively without waiting for the whole page to have generated! :crazy:
  • When you are in desperate need for marketing arguments to write a book on ~` Advanced PHP '~ ! >:XX