Tuesday 13 May 2008

Helpers are the way forward

Read and weep at the sheer awesomeness that is helpers in the Zend framework. Helpers are going to be how
  • individual stylesheets are applied to a page
  • Client-side script can be added
  • Metadata such a description and keywords

Sunday 4 May 2008

Using XSLTs as a template engine in Zend

I've been working my way through a book that is using the Zend framework to do—buzzword approaching—"Web 2.0" stuff, and it started to mention the Smarty template engine. It seems the author, as well as many other PHP developers love this silly template engine stuff made up placemarker tags. Whereas I'm sure Smarty has lots of really cool features which would make my life a lot easier, I really couldn't be bother to learn how it works, and figure out what it needs from me so that it does just that. I seem to prefer the idea of my application models spitting out well-formed XML and using XSLT to style this to whatever template style I want to use later on.

I don't know why I like the idea so much. I think it's the extent to which the model doesn't care how the data is rendered, it's job is just to deliver it and it does that through XML. There is of course a parsing delay involved in doing transforms and I'm going to try to get some data or results of my own to try and analyse that, but for the time being I'm happy. There's even the possibility of processing the document client-side by either delivering pure XML with a stylesheet declaration, or using a javascript library like Sarissa and falling back to server-side transforms onlyZend to do XSLT transform instead of rendering templates and it's just about working. But it's led me to thinking about the bigger picture. XSLT allows us to include multiple stylesheets in one document by using expressions such as import and include. So why can't we make a master XSLT template file which doesn't transform any XML itself, but simply matches the document root to apply its template only once, but then crucially providing a placeholder for an imported stylesheet in the right place. This would allow me to use it as a 'master view' which is combined with the view my controller action renders.

There is however, a few problems. Whereas now my view renders whatever XML its passed using a single stylesheet, it now has to use the master stylesheet, but the master itself has to be aware of which view-specific stylesheet to include. This is getting a bit too much like a template language – replacing strings in the master template file with a path to the view specific stylesheet, and that's what I'm trying to avoid. The other problem is with CSS. Putting persistant navigation in the master stylesheet is fine, but what happens when you want to change the CSS class of one of the link elements? You have no hook to the master from the view specific stylesheet. I thought about having the navigation as its own XML file – easily editable and adaptable. Then view scripts can be used to change that nav XML, marking which link should have a CSS class of "current" and combining it with any data XML the view has received assuming there and some mechanisms are in place for the master stylesheet to find those flags, and produce the right XHTML output. Perhaps xml namespaces are the right way to go here, in order to differentiate between nav and content XML. Ideally, minimising the number of transforms is a good idea, so I don't want to have to transform the nav XML data, then use another template to transform that result to the final output including the actual content. The content XML and nav XML could be combined just before XSLT processing. It would be simple to wrap content XML from the model with persistent data. But the problem still remains to tell the master stylesheet which view specific stylesheet to include in order to render it correctly.

Javascript may be an alternative. Client-side transforms has the nice quirk of sorting through XSLT which is really neat, but Javascript is so horrible to code with. I have to think about it more.

Saturday 3 May 2008

MySQL and "serial"

In MySQL and PostgreSQL serial can be used when setting up a column in a table. It's the same as writing bigint unsigned not null auto_increment just a lot shorter to write.

Zend and XSLT as a template engine

If you have XML data that you need displayed, turn off automatic view rendering within you bootstrap file with


$controller->setParam('noViewRenderer', true);

This gives you more control over how Zend renders views. Then, in your controller action , create a new view and assign some variable from you application logic. You need to tell the view where the script is to execute. You do this using $view->setScriptPath('...');. Once this points to the right directory, you can add a script in there you want the view to run. You do this by calling the render method of the view instance you create, passing it a single string parameter as the script you want it to run. As the contents of the script is returned, the whole thing needs to either be echoed or printed from the controller action.

Within the view script, print anything you want to be rendered on the page. So here you can pair up the xml data passed from the controller action using $this and an XSLT stylesheets you want to transform.

Brilliant hey? I sort of get this stuff.

Friday 2 May 2008

Zend and MySQL

Zend currently uses the Pear library to do stuff with DBs. Whereas installing this library may be fine, you might not have access to the server to install more stuff. Instead, follow this article about Adding adapters to Zend which allow it to use PHP. Alternatively, get the latest source files here and put the Php directory within Zend/Db/Adapter/. It works a treat, just remember to set the connection type to php_mysql as opposed to pdo_mysql

None of this is my own work. It all belongs to David Coallier (davidc@agoraproduction.com) and his blog http://blog.agoraproduction.com. Awesome job, thanks.

Apache mod_rewrite refusing to work

Apparently, some servers require FollowSymLinks to be turned on. If mod_rewrite is refusing to work and just denying all access (particularly important when trying to implement MVC with a bootstrap file) try including this in the .htaccess file:
Options +FollowSymLinks

More cool stuff with http.conf

Ok, I'm getting there. I know know a bit more about Apache's VirtualHost directive:

DocumentRoot /var/www/phpweb20/htdocs

This gives an absolute path to the directory where your web files will be served from. It can be anything you want.

<Directory /var/www/phpweb20/htdocs>
AllowOverride All
Options All
</Directory>


This says, for a given directory (and it says which in particular with the path) AllowOverride which allows me to use .htacess files in that folder. Not too sure what Options does yet.

The other cool bit is this line:

php_value include_path .:/var/www/phpweb20/include:/usr/local/lib/pear

This tells the PHP module in Apache where to look for include files. Pretty handy.

Thursday 1 May 2008

PHPDoc

Use PHPDoc rules for formatting:


/**
* functionName
*
* Brief description of the function. What it DOES,
* not how it does it
*
* @param string $name The name of the user
* @param int $age The age of the user
* @return string The generated welcome message
*/
function functionName($name, $age)
{
...
}

Pretty simple really.

Debugging Google Maps Apps

Check out GLog.

Back ticks

you can call UNIX commands in PHP by putting commands in back ticks (`). Similarly, shell_exec('...'); will run scripts too.


popen() is also apparently useful, it allows you to open processes and talk to them.

Differences between echo and print

It's all in the single, or double quoting. echo "$variable" will get echo to replace the variable name with it's value. If echo is used with single quotes it won't work.

Also, echo is slightly quicker than print apparently.


Sunday 6 April 2008

iPhone Problems #1 : Texts (minor concerns)

Following on from my major gripe about individual deletion, here's a few other aspects of texting that bug me every so often.

2. 'Conversation' is a misnomer.
The first message after an undesignated period of inactivity (it's less than 25 minutes but more than 6) gets time and date stamped. Which is fine, but clearly what Apple means by 'conversation' is 'a number of texts sent reasonably close together', regardless of whether they are replies to previous messages or entirely new trains of thought. This has the result of not only clumping together groups of texts in a slightly jolting way, but also leaving most messages without a time stamp. If you happen to text rapidly but over a reasonably long period - when arranging to meet someone, for example - you can easily end up with the final text in a string being hours newer than the first, with no way of differentiating it. I for one would like to know exactly what time a text saying 'just got on the bus' was sent, so I can judge how late I'm going to be in meeting said bus. It's the slightly random nature of this which bugs me - either time stamp each text, or don't bother at all.

3. Lack of delivery reports.
This is probably an O2 problem - to get a delivery report from a text, one is required to type *0# (note: that's a zero, not an O) before the message. Which is extraordinarily fiddly, and just too incredibly frustrating to do before every message. Why there's no option on the iPhone itself to turn delivery reports on or off, as there is on almost all other handsets sold in the UK, I've no idea.

4. Call/contact info scroll time
A very minor point, this one, but another example of Apple having wonderful intentions which fall a little short in practice. At the top of every text conversation are two highly useful buttons: 'Call' and 'Contact Info' (if it's an unknown number, the latter becomes 'Add to Contacts'). These have clearly been designed for no other purpose than to be helpful when one is in a rush and doesn't want to go back to the home screen, get into the contacts list, etc. This sort of unobtrusive handy-help is the reason I love my iBook, and Apple in general, so much. However, the text folders of those people I am most likely to want to call at the drop of a hat are, not surprisingly, rather full. So scrolling up from the latest text to the 'Call' button is painfully slow. The option to tap the screen once to have all of this displayed (as with Quicktime or Safari) would be much appreciated.

iPhone Problems #1 : Texts

Being a big fan of gmail, I like the 'conversation' style of the texts, and I like how my side of the speech-bubble debate is green. But an odd lack of research seems to have been carried out on how people actually use texts. Perhaps this is partly because of the gap between the UK and the US on texting - it took much longer for it to catch on in the US, and still isn't embraced with quite the same fervour. This might be because we've never managed to master the American-style quick-fire phone call, which is in essence a verbal text message. SMS allows the British to arrange appointments without the ten minutes of asking how the other person is at the beginning and a lengthy polite goodbye sequence at the end. So, maybe Apple should have a talk with us before the June update and sort out some of the following:

1. There's no way to delete individual texts.
This issue has been commented on by many, and there are a few hacks around already to help out, although they're all a little clunky - a common problem seems to be their tendency to only show numbers, not names. I like having a different section for each contact, even when such sections are empty of any actual messages; I like that my replies aren't hidden in some 'sent' folder; I like that a line of the most recent text is displayed on the first page. But a big problem stems from my having, essentially, two different sorts of text messages - those containing humorous observances or Happy Birthday greetings, which I save as long as I have the phones, and those saying thinks like 'yes, 5 mins', which are usually deleted instantly. The choice is therefore to keep everything, no matter how long it takes to scroll through them and how difficult it is to find the interesting/useful/funny ones; or, to mercilessly delete them all. Not only can I not delete the ones I don't want, I also can't save the ones I do. Given that in the last ten days I've had over 70 texts from Michele alone (and I live with him), the former isn't really an option - I dread to think what people with real jobs are going through trying to find the date of a crucial meeting hidden among hundreds of 3-word exchanges about coffee and photocopiers (or whatever it is the employed discuss with their collegues).

So, for the moment, I'm following a strict regime of entering important dates in my calendar as soon as they arrive, and typing up into a word document any sentiments from friends I know I'll want to look back on. This way, I've covered all bases when I accidentally delete everything in one go. But I feel it somewhat defeats the purpose of the wonderful-looking, easy to use text app I have at my disposal. What I should be doing is signing up to O2's Bluebook, where Sean Bean nicely saves a copy of everything as it comes in, but I've found O2 almost as disappointing as Virgin Media during my short ten day spell as their customer, so I've been putting it off as long as possible.

Further minor problems to follow.

iPhone Problems - Introduction

My iPhone is wondrous and I love it dearly, from its shiny back to its smudged and slightly sticky front. But while the features it has are (for the most part) extraordinarily well designed in terms of both usability and aesthetics, Apple seem to have clean forgotten to include some of the standards I was expecting. I'm by no means the first to point these out but, being someone who enjoys making lists, I'm going to detail them again.

cakePHP database config

Ok this is cool.

For CakePHP, database configurations are saved in the app/config/database.php file. But notice each config is given a variable name. Any number of configs can be added in this file so that when you're working on a controller you can set the $useDbConfig variable equal to a string of the same name as your config array. Simple.

here's more info

CakePHP conventions

This page outlines CakePHP conventions.

An interesting and useful paragraph is the following:

The first function you write for a controller might be the index() function. When a request specifies a controller but not an action, the default CakePHP behavior is to render the index() function of that controller. For example, a request to http://www.example.com/apples/ maps to a call on the index() function of the ApplesController, where as http://www.example.com/apples/view maps to a call on the view() function of the ApplesController.


Notice visibility is also mentioned on the page but starting a function name with an underscore

Saturday 5 April 2008

Automatic Documentation in PHP

Something to do with phpDocumentor.

But basically, make a code block but use a double asterisk. The make elements with an @ symbol:

/**
* This function builds a simple XML file for the client to parse.
*
* @author Michele Memoli
* @since Version 0.5.3-23
* @return string Returns an XML string.
* @see ui::get_xml( )
*/

Monday 24 March 2008

Google Maps on the fly

Adding Google Maps and dynamically filling it with goodies you have stored in a database is an exciting thing, but there are a number of alternatives available to you when deciding to do this. Firstly, GDownloadUrl(url) Can be used to go off and get a remote file for you. This remote file can be an XML file and parsed using the GXml() although this then leads to navigating the DOM to extract the data you want. Secondly, if the XML file your downloading is more specifically a KML file (very possible considering you may be producing that file from your database). You may want to just use the GGeoXML() class. This class can be passed a KML directly and theoretically get displayed on a map using map.addOverlay(GGeoXML). However, this doesn't give you access to a function you may have to create (and therefore return) a marker. This function is useful because it allows stuff to be bound to particular marker instances (like code for click events). With GGeoXML you loose this.

I keep seeming to start by plotting an arbiturary XML file full of <marker> tags. I then decide to use a standard XML file like KML, get satisfied, then remember the GGeoXML which could have done most of it for me.

Javascript: Binding and Scope

Here's quite a cool help post on the mootools forums about in Javascript.http://www.blogger.com/img/gl.link.gif

Saturday 22 March 2008

Printing Arrays in PHP

always use print_r(); to debug an array. I guess echo and print just produce array.

When displaying stuff in web pages use a foreach loop.

VirtualHosts in Apache, Leopard

There's a few key files when playing with Apache WebServer. They are all .conf files, the most important being http.conf. In Leopard this is at etc/apache2/. Editing this file is pretty straight forward, it's very templatey - find out where it's done once, then copy, paste and edit.

Virtual hosts are a good thing to set up if you're working with a lot of websites. People talking about enabling the following line beginning with Include in the http.conf file:

# Virtual hosts
#Include /private/etc/apache2/extra/httpd-vhosts.conf

This is fine, but it doesn't really do anything, it just gets Apache to pull in that extra configuration file when starting up. In fact, you can keep that file commented out (not used) and put virtual directory right there, in the http.conf file. Here's the basic code for setting up a virtual host

<VirtualHost *:80>
#ZDS Name: redmonkey
ServerName redmonkey
DocumentRoot "/Users/michele/Sites/redmonkey"
ServerAlias redmonkey
ErrorLog error.log
Options Indexes MultiViews Includes
</VirtualHost>

I'm sure loads can be changed, and I'm not sure what all of it does yet, but get this in and edit the rest.

Once this is done, you need to setup your hosts file. This can be found in /etc/ and it's simply called hosts (note: no file extension). Here add the following:

127.0.0.1 redmonkey

The IP address is equivalent to "localhost" and then a name of your new hosts. From then on you should be good to go with your new hosting directory in Apache on Leopard.

Thursday 20 March 2008

Unix Aliases

Absolutely awesome. If you have a command you use over and over again, chuck it in a login script and give it an alias.

When using the bash shell, include aliases in ~/.bash_login (create the file if it doesn't exist already). Some useful aliases I've already added in macOS are the following:
  • alias ll='ls -la'
  • alias clr='clear'
  • alias here='open -a finder .'

The last one is really cool. It opens a finder window at the current terminal location.

MySQL wrapper class

I started writing a wrapper, then I found this PHP MySQL wrapper class prebuilt. It seems very good and the site includes lots of cool example of how to use it. Why bother trying to re-invent the wheel? Well done guys.

SQLite

SQLite seems to be an alternative to MySQL. Sure it has many benefits, by i'm sticking to MySQL for the time being.

Apparently it's fully OOP though so you can do cooler things with exception classes, and it comes with PHP 5.

Useful Links

You may want to re-write the blogs html and put some cool useful links in there, and you could make it look a bit better.

Also Im using the google reader, you subscribe blogs to ur reader and it consolidates and displayes all unread blog posts. You can then throw a google reader widget onto ur igoogle page and see all the new posts from there. I should'nt miss any posts now...

Smarty: A PHP template Engine

Ok Smarty. All you really need is everything in the libs/ directory. When copying in unix, remember to add option -r to go into the internals/ and plugins/ directories within libs/. With those files saved somewhere, your PHP has to find one file in particular-Smarty.class.php (they also seem to be quite strict about the capital "S" in "Smarty"). That file needs to be referenced with an absolute path. This can be done a number of ways, look them up at Smarty's documentation. One cool way I've found so far is this:

// Use the absolute path for Smarty.class.php
$base_path= basename(dirname(__FILE__));
require($base_path.'/Smarty/Smarty.class.php');

Of course this assumes that you're writing this in a file which is in the document root of your webserver, and that the Smarty files are located further down in the folder Smarty/. The require_once is similar to PHP's include statement apart from it will result in an error if it can't find the file (include will just try and not care if it can't) and the _once part ensures there's no errors if you accidentally try to require it again.

Within that Smarty directory, make four folders: templates, templates_c, cache and configs. Link these files up with your code with

$smarty = new Smarty();
$smarty->template_dir = $base_path.'Smarty/templates';
$smarty->compile_dir = $base_path.'Smarty/templates_c';
$smarty->cache_dir = $base_path.'Smarty/cache';
$smarty->config_dir = $base_path.'Smarty/configs';

Put this immediately after the required_once statement. Then start making templates and go.

Wednesday 19 March 2008

PHP: the ? operator

The ? in PHP is shorthand for an if..else statement. It works like this
{expression} ? return_when_expression_true : return_when_expression_false;
Notice the ? and the : to separate everything apart.

Casting in PHP

Casting seems relatively straight-forward:
$test = 1234;
$test_string = (string)$test;

Simple.

Unix pipes and other commands

Pipes "|"are really cool. They redirect output from one command and pass it as input into the next command. A useful command to use in this situation is grep which pattern matches line by line and displays that line if the match succeeds, but grep -v inverts how the command works, and displays every line that doesn't match the pattern, making it useful as a filter...very cool.

Tuesday 18 March 2008

MySQL basics

The USE database command sets the default database for your stuff. All operations from that point on are applied to that database. When declaring numeric types, a number in brackets called a width specifier which tells MySQL to pad the field when retrieving it. With floats and decimals a precision parameter can also be specified such as FLOAT(7,4). Marking a field with the ZEROFILL attribute will force MySQL to pad the value with zeros. UNSIGNED forces only positive numbers.

The alter can be used in a number of different ways to change name of fields within a table. If you try to convert field types using CHANGE, MySQL may result in errors. Try using IGNORE to get round them.

Use mysqldump to backup and restore databases or tables. Delete stuff from databases and tables using DROP.

Hello Michele!

Im now an added contributer to the blog

.inc files and libraries

Use require_once() to include files to use as a library. These files get interpreted by the interpreter but aren't called directly. They are conventionally given a .inc file extension, and they allow you to call functions and stuff hidden inside them. Quite useful.

Monday 17 March 2008

mod_rewrite

First thing to get your head around is the fact that it's kinda backwards. Messy URLs still exist, you're just translating them from nice to messy for your code to understand.

After that, it's quite simple really. Regex expressions: from, to. Use ^ and $ to mark the beginning and the end of the expression to match. Here is a good mod_rewrite cheat sheet although there's loads of help online. Try to set a RewriteBase to set the base directory within the site

the [R] flag will redirect the user and the URL in the browser window will change automatically. The [L] flag will redirect behind the scenes but the users won't know. Use this for query-string stuff. Remember to turn the engine on (as it's off by default) with RewriteEngine on.

The only other thing I've discovered so far is there seems to be a default index being made by Apache which I haven't been able to disable yet. This default indexing causes Apache to ignore my rules and display any file in a directory by default if they share the same name i.e. if I have rules like

RewriteRule ^$ catalog/ [R]
RewriteRule ^catalog/$ hello.php [L]

and within the directory there's also a file called catalog.php, Apache seems to be ignoring the redirect to hello.php and just displays catalog.php as the index. I know this because if I change the filename and the redirect directory to something else I have the same affect. I'm still working on this, no idea how to do it.

All of this can be written in a .htaccess file.

Apache settings

Main files: httpd.conf and .htaccess. The first sets some site-wide settings. It seems to be similar to web.config in .NET. .htaccess works on a per-directory basis.

Monday 14 January 2008

The start of something truely terrible...

Here it is, the first Red Monkey post ever. Utterly pointless, sorry for wasting your time.