Updates

Life goes on.

I’ve been working on Nifty this weekend. Seemed like a good idea, because I’m updating a lot of stuff on the intranet at work, building on the 1.2 branch, and I need a couple of new features. So I made a 1.3 branch.

Some really nifty features so far:

  • Pages aren’t limited to one level anymore. You can have a page at /index, one at /start/rss, and one at /intranet/projects/newsfeeds/rss. The system translates the call into an index.php?__path=nnn statement, and resolves the class names and commands automatically. Which means you should be able to build much more complex applications.
  • Modules are no more. They’ve been replaced with components. You can now build entire forms and web-page components completely standalone, and insert them at will into your templates/pages. You can even make callbacks through HTML POSTs or Ajax directly into a component, dynamically updating and reloading parts of the web page.
  • The exception system has been overhauled, giving more meaningful error codes.
  • Responses are now automatically prepared for Ajax calls, decoding and encoding responses as necessary (no more $Response->reset()).
  • The database/persistence layers can now handle relations between tables. You can now issue a $users = $Persistence->loadAll(‘Data_Users’); and immediately thereafter a $Persistence->loadRelated(‘Data_CompanyDepartments’, $users) and link users with corresponding department objects. The initial objects are dynamically updated with references to the new objects.
  • Page session objects and page ViewState is being incorporated directly into PageBase, no longer requiring the use of Forms.
  • Templates can now load through loadDefault() and runDefault(), automatically determining the template file names from the current call context.
  • The Autoloader can make more checks for loadable classes and has a more fine-grained control.

It’s currently in development (possibly soon alpha), but that’s the news so far.

Code folding in Netbeans PHP

I recently found out a tip that C#-style #region and #endregion-style declarations work in NetBeans for PHP too, although with a slightly different syntax.

The trick was making it work in HTML, since I use it mostly for defining different sections of my .phtml templates, which can get pretty long:

<? // <editor-fold defaultstate="collapsed" desc="JavaScript code"> ?>
...
<? // </editor-fold> ?>

Realized you had to escape to PHP for it to work. A little extra syntax, but look at my beautiful, beautiful HTML code:

I’m Publishing My Little Programs Now

I’ve published one or two of my little programs before, but now I’m expanding with a set of new ones.

  • DesktopShooter (shoot up your desktop)
  • Mobile Clock (display a neat clock/countdown on the desktop)
  • Mobile Notepad (the old “notepad” under a new and better name)
  • Mobile Wallpaper (replacement for Webshots)

These are all available under the Software Downloads page. Knock yourself out.

(Oh, and, uh, don’t expect an installation program.)

All These Mornings

For many years now, while working with computers on a daily basis, I’ve sometimes had these moments when I’m just between sleeping and waking up, and I imagine myself doing ordinary things – you know, like making coffee, taking a shower, stuff like that – and the thing that bothers me in my sleepy state is that I can’t remember what program I need to run to do that.

I have this uncanny feeling that there’s a certain command I need to run (with unix pipes and all) but I can’t remember the syntax, and I struggle with this until I wake up; and it takes me a few moments to realize that I actually don’t need a computer program to do that. I don’t even need a computer at all. I am a human being and I can do whatever I want. :)

Or am I…?

Programming with Nifty 1.2

Some features in the upcoming Nifty Framework 1.2 release:

<?php

class Index extends NF_Page
{
    public function executeView($id)
    {
        global $Request, $Persistence, $Response;

        $form = NF_Component::fromArray(array(
            'component' => 'NF_CForm', 'name' => 'form',
            array('component' => 'NF_CInputHidden', 'name' => 'id', 'dataField' => 'id'),
            array('component' => 'NF_CInputText', 'name' => 'name', 'dataField' => 'name',
                  'label' => 'Name: '),
            array('component' => 'NF_CSelect', 'name' => 'type', 'dataField' => 'type',
                  'label' => 'Nationality: ', 'options' => Nationality::getList()),
            array('component' => 'NF_CButton', 'name' => 'submit',
                  'type' => NF_CButton::Submit, 'label' => 'Save!')
        ));

        $form->dataObject = $Persistence->load('User', $id);

        if (!$Request->isPost())
            $Response->content = $form;
        else
        {
            $form->processPostback();
            $Persistence->save($form->dataObject);
            $Response->redirect("/index/view/$id");
        }
    }
}

The whole thing…

  1. Defines a form, containg an input field for “name”, a dropdown list for “nationality”, and a submit button.
  2. Loads a “User” object from the database, and binds the form to this object.
  3. Renders the form and sends it to the client.

When the postback occurs,

  1. The form processes it, feeding all the data into the bound object.
  2. Saves the object to the MySQL database.
  3. Finally redirects back to the input form again.

I can’t make it shorter than that.

(There is also a configuration file, containing database parameters, a skeleton “User” class that holds three data fields – and one “Types” class that loads nationality lookups. Nothing more. This is a complete application.)

What an Enormous, Unbelievable Mess

I’ve been trying to config our Apache server today.

These are the requirements:

  • We want PHP version 5.
  • All users accounts are separated through virtual hosts.
  • PHP should be run with the same user rights as the user, this means either CGI or FastCGI with suexec; because when frameworks create files in the home directory, they should be owned by the user, not by apache.
  • PHP should be locked down with open_basedir, and session storage should be in the user’s own home directory.

What an enormous, unbelievable mess this has been to set up. We’re also doing this with CentOS 5.1.

suexec is a bitch to set up, but, in the end, it works.

There is practically no documentation on FastCGI and how it works. There is a ton of user-submitted scripts, all of which are crazy in one way or other, and don’t seem to work on my box.

Many of these methods seem to rely on patches, and I want to maintain my yum compatibility.

The most difficult thing was to make PHP default to different values for each user account, and in the end, I had to make a cgi-bin/php5 file, setting PHPRC to the user’s home directory, and build a small shell-script that copies /etc/php.ini, tacks on a few custom settings at the end, and puts that where the cgi-bin php script can find it.

Unbelievable. But, the good news is, with a plain vanilla suexec + php-cgi setup, it now works.

Publishing My “Nifty” Framework?

I’m sitting here wondering if I should go public with the PHP framework I’ve built over the past couple of years. It’s gone through a couple of iterations and is now something that I’m regularly building internal and external websites on top of.

No, it’s not the same thing as my Nifty CMS, but that one is built on top of what I now shall call the Nifty System Library.

It features

  • MVC-based mechanisms, including templates, controllers, and database mapping
  • A simple, custom built templating class, using pretty much PHP’s own template system with a few enhancements sprinkled in
  • Page caching
  • Basic application configuration
  • Automatic call routing, including friendly URL rewriting, call-to-method dynamic invocation, and parameter filling
  • Several wrapper classes for Request, Responses, Sessions etc
  • Complete PHP5 OO design
  • Minimalistic and intuitive class design, using static calls for shortcut class operations
  • Database abstraction, including a simple class-to-table POPO persistence layer
  • Simple module layer
  • Clean separation between pages requiring authentication and public pages
  • Zend-like directory layout (separated system, application and public_html folders for instance)
  • Utility classes for…
    • Excel/Delphi-style DateTime handling (DateTimeEx)
    • Image manipulation (GD)
    • HTML and database escaping (database agnostic)
    • Password-checking
    • TCP/IP connections
    • Uploading functions
  • ~40 files, 141 kilobytes total.

Once you’ve learned the basics, the system is very efficient, allowing you to build clean, efficient web applications with database integration using a minimal effort.

Is this something that people might be interesting in using, you think?

Using XDebug and WinCacheGrind to Optimize PHP Scripts

I noticed earlier that our helpdesk system (written in PHP) became somewhat slower after we upgraded to the new version, 1.1. I always thought I’d look into it but never got that far. Of course, I’m using a self-written framework, and I’ve known that it hasn’t been profiled for speed, so I knew there’d be a few things in there that could use a tweaking. So, I fired up a debugger/profiler today and went to work.

XDebug is the premier choice for PHP debugging/profiling. It is available both on Windows and Linux. Just plug it into PHP as a Zend extension, set the configuration to enable profiling, and voila!

zend_extension_ts=”c:/program files/php/ext/php_xdebug.dll”

[xdebug]
xdebug.remote_autostart = 0
xdebug.remote_enable = 0
xdebug.profiler_enable = 1
xdebug.profiler_output_dir = “c:\home\temp\xdebug”

It creates a nice little output file in the output directory. And using WinCacheGrind, it was easy to analyze the logs and see what functions took most of the time.

One little caveat, though – it seemed as though the actual execution time reported by PHP and by XDebug varied by a factor of 10 – a huge difference. But the relative time between function calls indicated by WinCacheGrind was still useful in isolating the time hogs. Just pretend that 466 ms actually is 4.66 s, and there you go.

The result: I discovered that one single function, DateTimeEx::getDateTime, which decodes Excel numeric dates into actual date/time values, stood for a whopping 90% of the total execution time. In this case, there are about 200 objects instantiated from the database, and each of those database objects are called several times to extract date values. So there was a lot of date calculation going on. However, there is no advanced stuff going on (like loops) inside the function, just a bunch of float arithmetic – the only conclusion I can draw is that PHP really sucks when it comes to complex float calculations.

First, I was able to cut down on a few things inside the actual function; and then I made a self-populating date-value cache, holding 300 calculated values.

The result: Execution time for the entire browser request went down from 4.8 seconds to about 650 milliseconds.

Lessons learned:

  • Profiling is invaluable, especially with an interpretative language like PHP, where you never really can be sure what costs time and what doesn’t.
  • XDebug and its companion WinCacheGrind are essential tools and work well on a Windows/Apache platform.
  • The DBGp plugin for Notepad++ is also useful, and allows you to debug PHP scripts live, but has some limitations. However, it doesn’t require a full-blown IDE, like Eclipse or NetBeans, and can be useful as a little drop-in tool.
  • PHP is fun, especially when you have powerful tools. :)