Rallyhat lives!
Some of my long-time readers have seen me mention a long-festering (I believe that is the correct term at this point) project that I dubbed Rallyhat. It first started out as a “figure out when some baseball teams are in town and buy tickets” and then morphed into “a tool for helping people plan road trips by tagging destinations with information”.
What it really became was a tool for me to learn how to write a solid web-app using Python and Django. I’m happy to say I finally have a version that I feel comfortable sharing with the rest of you. So feel free to check it out. Pound on it, try and break it and I will also read your feedback and comments. I’m sure you can figure out my email address…
Also, I’ve found it has been easy to pick up not only Python and Django itself. I’m ready to tackle some other applications using Django, and I have one just in mind.
Yes, I am aware at how spartan it looks right now. I’m more focussed on functionality than how it looks right now. I’ve already gotten some interesting ideas on expanding the app to include adding in images to go with locations, so we’ll see how that goes.
For those who are curious, I built it using the following:
- Python 2.6
- Django 1.2 beta 1
- CouchDB to store the trip plans
- couchdb-python
- GeoPy
- django-registration
- Google Maps services
- Django Debug Toolbar
- deployed using Nginx + Gunicorn, configured with the help of Eric Florenzano’s awesome Django Advent article about deploying Django using FastCGI because it mentioned how you could use Gunicorn
Matthew Weier O'Phinney's Blog: Module Bootstraps in Zend Framework: Do's and Don'ts
Matthew Weier O'Phinney as a new post to his blog today looking at a few "do's" and "dont's" when it comes to working with module boostraps in your Zend Framework applications - an apparently somewhat confusing topic for several developers out there.
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.He talks briefly about why module boostraps are run on every request (getting into some detail on Zend_Application), how you can properly set up your boostrapping process and how you can use plugins to initialize only the things you might need and, as he openly admits, that there's just not a really good way to handle this sort of module funcionality.
Pablo Viquez's Blog: Zend Framework Documentation
Pablo Viquez has put together something that all of the Windows-based Zend Framework developers might find very useful during their next offline (or online, really) development session - a Windows Help file version of the Zend Framework manual.
As you might now, you can view and download the Zend Framework reference manual from the Zend Framework site and download it from the download section, however what I wanted was the Windows compiled version of it (CHM file). In order to get this version you need to compile the documentation, after running into some small issues, I manage to do it, and to save you some work.He only had to fix an issue with one XML file to correct some escaping in the Zend_Feed_Writer.xml and zend.feed.writer.html files. You can download both the English CHM and the Spanish CHM files depending on your needs.
Johannes Schluter's Blog: Future of PHP 6
With the releases in the PHP 5.x series (5.3 and now a newly branched 5.4), people have been left wondering about PHP 6 and the promised Unicode support it will include. Development on that branch had all but stalled out and things weren't looking too good for the method of introducing full Unicode support to the language. Johannes Schluter has some good news, though - the effort has been restarted and a new approach has been decided on.
Yesterday the stagnation created by the situation has been resolved and it was decided that our trunk in svn will be based on 5.3 and we'll merge features from the old trunk and new features there so that 5.3 will be a true stable branch. The EOL for 5.2 has not yet been defined but I suggest you to really migrate over to 5.3, which usually can be done with very little work, as soon as possible.Discussion are being made about which type of Unicode support will actually be introduced with a "string class" wrapper gathering some support behind it to provide an alternative to the current string handling.
Ian Christian's Blog: Handling Uploaded file in symfony's admin generator
Ian Christian has an informative new post for the Symfony developers out there. He's figured out a way to handle uploaded files with Symfony's admin generator relatively easily, changing the filename option.
When a file is uploaded using sfForm in the admin generator, by default the filename that's used is a random string, which can look bad in URLs. If you want to change this, it's not immediately obvious how - but it is incredibly simple.The Symfony project does have some documentation on the topic, but it's not the easiest to read. It basically boils down to is defining a function in your extended class based on the name of the file where you can change the name however you'd like. Code snippets are included to make the point a bit more clear.
Jani Hartikainen's Blog: Should a failed function return a value or throw an exception?
Jani Hartikainen poses an interesting question on his blog today - is it more correct for a function, having failed at its job, to return a value of throw an exception.
You have created a nice, well written function, but you realize you forgot something: The failure case. What should a function do when it fails? There are two schools for this - the "throw an exception" school and the "return an error value" school. But which of these is the correct approach?He suggests that this debate has stuck around from the time when there weren't exceptions in several popular programming languages and that returning the value was the only valid way. He touches on what an exception condition is (with a few code examples) and situations where each choice might be the right way to go.
Brian Swan's Blog: MSSQL vs. SQLSRV: What's the Difference? (Part 2)
Brian Swan has posted the second part of his series looking at the difference between the MSSQL driver and the SQLSRV drivers for connecting to SQL Server databases from PHP (part one can be found here). He gets a bit more detailed in this second post.
I'm aiming to provide a high-level comparison that you might use if you were considering moving to the SQLSRV extension, but I think there is also some interesting information if you are just curious about the differences. [...] In cases where a short note wasn't enough (and there were several of these), I've provided relevant links to topics in the SQLSRV documentation.He talks about things that one offers that the other doesn't, like prepared statements (sqlsrv) and working with stored procedures (mssql). He also mentions error handlng, persistent connections and scrollable cursors in sqlsrv. Finally he gets into a one-to-one function comparison of the two drivers with the sqlsrv function list coming up a bit short compared to the features of the more recend (and well-supported) mssql driver.
Phil Sturgeon's Blog: CodeIgniter 2.0: Everything you need to know
Phil Sturgeon has posted a look ahead at everything you need to know about the next version of the popular CodeIgniter framework, version 2.0.
It has been 6 months since the last CodeIgniter minor update and 18 months since the last major update. Through all this time we were given no information about the next release of CodeIgniter, but finally 2.0 is on the way.Because of the Ellis Labs move to Mercurial for its version control system (and BitBucket for the repository), it allows for a more "social coding" environment where it's easier for developers to just fork and contribute. Other major changes for this upcoming version include the fact that PHP4 support will officially be deprecated, driver libraries, application "packages", a smaller reserved controller name list and the dismissal of plugins.
Check out the Changelog for more detailed information as things are updated.
Solar 1.0.0 Stable Released
Site News: Popular Posts for the Week of 03.12.2010
- Brian Swan's Blog: What's the Right Way to Prevent SQL Injection in PHP Scripts?
- Brian Teeman's Blog: Who is the Joker in the Joomla pack?
- PHP.net: PHP 5.3.2 Release Announcement
- CatsWhoCode.com: Getting started with CouchDB: a beginner's guide
- Matthew Weier O'Phinney's Blog: Responding to Different Content Types in RESTful ZF Apps
- Zend Developer Zone: How to avoid Identity Theft in Zend Framework with Zend Auth
- Alvaro Videla's Blog: Erlang as a Fast Key Value Store for PHP
- Site News: Job Postings for the week of 02.28.2010
- Template Monster Blog: It's coming! WordPress 3.0 - Pros and Cons
- Kavoir.com: Just Hashing is Far from Enough for Storing Passwords (Dictionary & Rainbow Attacks)
Video: MySQL and SQL Joins Part 2

Hi,
We continue from where we left off in part 1 of our video on SQL joins. Still setting up things to do our SQL work, in this particular video, we continue to build our MySQL table.
The video:
There will be several other sample videos to come, but if you want them all NOW, (at the risk of being a shameless self promoter!) you can pick the entire 4hrs of the MySQL and SQL course in the killer video store.
Thanks,
Stefan Mischook
www.killerphp.com
php|architect: Programming: you're doing it wrong
In an opinion piece posted to the php|architect site Marco Tabini suggests that we (as developers) are doing it wrong as we move further and further away from the pragmatic side of programming into the abstract.
No matter how advanced the techniques that we use, there is always something that we could be doing better. [...] Which one is right? The real problem is that the answer to that question is, "yes." That's because it lacks a specific context in which it can be inserted.He suggests that, in our quest to figure out what the perfect case for any situation, we stop focusing on the practicality of writing applications to accomplish goals. Sometimes it's not about getting the right theory behind the code - sometimes it's just doing it.
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.
Continue reading "Module Bootstraps in Zend Framework: Do's and Don'ts"
Brian Moon's Blog: PHP command line progress bar
Brian Moon has a quick post that links to a but of code that gives you a progress bar for the command line that's flexible enough to be used in an number of situations.
Was just looking through some code and came across this function I wrote some time ago. If you do a lot of your processing scripts in PHP like we do, you probably need to know what is going on sometimes. So, I made a progress bar for use on the cli. I thought I would share it.You can see a demo of it here (screencast) or just download the code. Comments on the post also point out the PEAR Console_Progressbar package and the ez Components class for creating a more advanced progress bar.
Utopia in the header file
Climategate Stunner: NASA Heads Knew NASA Data Was Poor, Then Used Data from CRU
Use CakePHP + jQuery to build dynamic selects…
First, I can’t believe I’ve missed a whole month of posting…. damn 28 days :(
Anyway, a recent post on the bakery http://bakery.cakephp.org/articles/view/dynamic-select-boxes-with-ajax-jquery prompted me to show a slightly more accurate approach on working with the given scenario.
(I don’t mean to piggy-back on someone’s work, but I feel it deserves a little “touch-up”).
If you don’t feel like reading the other post, the basic idea is to build a dynamic select list using CakePHP + jQuery.
For this example we’ll first select a car make and then build a select list of available models using jQuery.
In order to accomplish this, first of all, the appropriate association should be established between the models:
Car hasMany CarModel
Based on that we can have two controllers:
- cars_controller.php
- car_models_controller.php
Next, of course, we’ll need some actions and views…
(The simple add/edit/etc. you can easily “bake”, so I’ll just focus on jQuery and relevant views at this point).
In CarsController we’ll add a list_models() method…
Now let’s take a look at the relevant view (list_models.ctp).
Again, here we are only focusing on the two drop-downs.
<?php $this->Html->script('views/cars/list_models.js', array('inline' => FALSE)); ?>
<?php
echo $this->Form->input('Car.name', array('empty' => 'Select One', 'options' => $names, 'id' => 'car-name'));
?>
<div id="car-models" style="display: none;">
<?php echo $this->Form->input('CarModel.name', array('type' => 'select', 'id' => 'car-model-name')); ?>
</div>
First, we’ll load up the jQuery script, which is relevant to the view. Despite my previous conventions, I find it much easier to replicate the structure of your JS file placement exactly as you’d do for the views. With one obvious difference, that all JS goes under /webroot/js/views/some_controller/same_as_view_name.js
You’ll notice that I wrapped the second select input into a div, which is hidden by default.
This is just one approach, but you certainly could leave it visible in your UI and populateit with an:
'empty' => 'Select Car First' … just a matter of choice here, I guess.
Next, comes our cars_controller.php:
I’m only showing the “interesting” actions.
public function list_models() {
$this->set('names', $this->Car->find('list'));
}
public function get_models_ajax() {
Configure::write('debug', 0);
if($this->RequestHandler->isAjax()) {
$this->set('carModels', $this->Car->CarModel->find('list',
array('conditions' =>
array('CarModel.car_id' => $this->params['url']['carId']),
'recursive' => -1)));
}
}
Let’s review the code a little… The list_models() method doesn’t really do anything special, it simply sets the car names to be used for the first select list in the view.
The get_models_ajax() will be called via jQuery in order to build our second select input. We are turning off debug here, so that any “extra” output does not mess with the returned data. Also, note the $this->params['url']['carId'] this value will come from our first select list, which lists the car names with the corresponding ID’s from the database. Because we’ve previously established a proper model association, finding all the models for a given car (car_id) is no trouble at all now.
Next, we still need a view for our get_models_ajax() action. The purpose of that view would be to return all the $carModels, which as you see we are setting in the controller.
Here it is, get_models_ajax.ctp:
<?php
if(isset($carModels)) {
echo $this->Js->object($carModels);
}
?>
Not terribly interesting, but one thing to note is that $this->Js->object($carModels); will convert the array of data, which is returned by the find('list') in the controller, into a JSON object.
Mental note… You certainly don’t have to work with JSON and any type of data can be returned back to the client, but for simple AJAX communication between the client and the server I find JSON to be most convenient format.
Alright, last, but not least let’s see the jQuery snippet that makes all the magic happen.
list_models.js
$(document).ready(function(){
$('#car-name').live('change', function() {
if($(this).val().length != 0) {
$.getJSON('/cars/get_models_ajax',
{carId: $(this).val()},
function(carModels) {
if(carModels !== null) {
populateCarModelList(carModels);
}
});
}
});
});
function populateCarModelList(carModels) {
var options = '';
$.each(carModels, function(index, carModel) {
options += '<option value="' + index + '">' + carModel + '</option>';
});
$('#car-model-name').html(options);
$('#car-models').show();
}
Unfortunately it would take a few more days to explain every line of code in detail, and there are quite a few jQuery tutorials our there that will do a better job of explaining it, so I hope a little googl’ing will answer any outstanding questions.
… but I do want to point out a few things.
First, we are using jQuery’s handy $.getJSON, which does a GET request to a given URL with some data and returns the results back to our client.
Remember this line: $this->params['url']['carId']? Well that’s exactly where the carId value is coming from… the select box value as specified between the curly brackets. Of course, there is no point in sending empty values to the server so we wrap the entire chunk of AJAX code into if($(this).val().length != 0)… this will prevent jQuery making the extra call to the server if the “empty” option is selected.
Next, we already know that the data returned from the server will be a JSON object so before attempting to do anything with the returned data we check for some valid data with: if(carModels !== null) . Here carModels is our JSON object, which is returned by CakePHP back to jQuery.
When all said and done, we use yet another awesome tool $.each to traverse the JSON object (i.e. carModels) and build our options list.
Finally, we add the freshly built HTML options list to the contents of our second select input and display it to the user.
We are done now, but just for some more detailed Q&A you can read further, if interested.
Q. Why use .live('change'... instead of just .change?
A. .live is a great tool to use if you are manipulating the DOM in some way and need to work with freshly inserted element. Granted in this example it is not necessary, but I wanted to show it off anyway. Just keep in mind that this approach is available and could be a life-saver at times.
Q. Why create populateCarModelList() function?
A. I like to keep things separated as much as possible, and who knows this function might come in handy for other reasons in a more complex application.
Q. Shouldn’t the get_models_ajax() action go into the CarModels Controller ?
A. Truth be told… it should. For the sake of simplicity I kept it in the same controller as the other method, but it would be “more proper” to place it in the CarModels Controller.
Q. Why did I assign DOM ID’s to the drop down elements, doesn’t cake do that automagically?
A. It does indeed, but cake’s DOM ID’s look like SomeModelThenField. In the world of CSS it is almost an unwritten rule that ID’s most often represented as some-model-then-field… so that’s my basic goal there. Thanks to a tip from Mark Story I promise to show in an upcoming post how to override the default CamelCasedID’s with dash-separated-ones.
New Video: MySQL and SQL Joins Part 1

Hi,
I just released the first of many videos on more advanced SQL and MySQL than we’ve covered before. From the courses description:
This course teaches you the very basics of MySQL, SQL then shows you how to use PHP with them. Once you have that under your belt, we jump into more advanced SQL and MySQL.
In this free sample video, we prepare our environment (MySQL) so we can start working with on SQL join queries:
There will be several other sample videos to come, but if you want them all NOW, (at the risk of being a shameless self promoter!) you can pick the entire 4hrs of the MySQL and SQL course in the killer video store.
Thanks,
Stefan Mischook
www.killerphp.com
CMStr.com: How to manually install Joomla 1.5+
From CMStr.com there's a new tutorial showing you how to set up Joomla manually just in case something happens with the install and you need to change things yourself.
Why would I want to do a manual install when my web host has this Fantastico thingy that will install Joomla for me? Good question. [...] If you are building websites for a living, and or plan on using Joomla a lot, then you really need to start doing your own installs. [...] If you are an experienced parachute jumper, you would pack your own chute right? This is no different.Screenshots are included to help make the process easier as they walk you through setting up the basics like language settings and database information. They also touch on the FTP setting (off for security) and removing the admin user's information to help make things a bit more secure. It's not a comprehensive list of the things you'd need to do to get it 100% configured for just what you need, but it's a start.