How not to blog
There is nothing more annoying than someone making blog posts that simply state: “I am sorry, I am so far behind… but I will be making a big post shortly …”.
It is better to just post something when you actually have something meaningful to say… save me the trip to your site (thank goodness for my RSS Reader).
The beginning of a dream come true
Kristie and I are both small-town Idaho kids. We grew up where the paved road ends. Having both grown up that way it has been a desire of ours to get out of the little subdivision and get back to our roots. We really want room to breathe, cats to water (inside joke), and calves to feed… and chores for our kids especially.
Well, we have taken step 1 toward that goal. Last week we bought some land that we plan to *eventually* build on and move to. It is located in Payson, UT on West Mountain. It is 5.50 acres and is currently part of a hay field. It will continue to be farmed until we start planting trees and doing other improvements that make it impossible to farm (at least in whole).
That’s one small step….
A week ago I inched a little closer to my goal of 400 lbs in the bench press by getting a new max at 380 (from 375). Byaaahhh!
I’ve never been so happy in my life…
until now – American Idol is finally over. Thank you.
5 sets of 5 at 300 lbs
So, I have been ramping up on my lifting to prepare for a shot at a new bench max in the next month or so (currently 375). Actually, I have not been lifting any more regularly, just bumping up the weight and doing less bench reps and more weight. On Monday I did 5 sets of 5 at 300 lbs, which is a new best for me at that set/rep count. I also did 315 4 times which is the most reps I have ever done at that weight. So… here hoping for 380+ in June. The goal is 400 before the end of the year… ouch, that is going to hurt!
Zend Framework and Propel


This information may or may not be meaningful to anyone but me. I was new to Zend Framework and Propel, so attempting to get them to place nice was twice the undertaking. I am happy to report that all went relatively smoothly.
The first problem I encountered was just getting Propel to do what I wanted since I had 2 databases I was dealing with. I have a ‘global’ database and also a ‘local’ database. The local database actually is one of several dbs that all share the same schema, but is simply specific to which customer is using the system. The global db is, well, global to the application.
Here is a copy of my runtime-conf.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<config>
<propel>
<datasources default="global">
<datasource id="local">
<adapter>mysql</adapter>
<connection>
<dsn>mysql:host=localhost;dbname=local</dsn>
<user>localuser</user>
<password>localpass</password>
<settings>
<setting id="charset">utf8</setting>
</settings>
</connection>
</datasource>
<datasource id="global">
<adapter>mysql</adapter>
<connection>
<dsn>mysql:host=localhost;dbname=global</dsn>
<user>globaluser</user>
<password>globalpass</password>
<settings>
<setting id="charset">utf8</setting>
</settings>
</connection>
</datasource>
</datasources>
</propel>
</config>
The next thing was to get my schema files setup for each database. I created a global-schema.xml and a local-schema.xml. Below you will see the database node lines, which is all that really needed manipulation.
<database name="global" heavyIndexing="true" defaultIdMethod="native" package="orm.global">
<database name="local" baseClass="hvBaseClassLocal" heavyIndexing="true" defaultIdMethod="native" package="orm.local">
Make sure that you specify the package names. This will result in the following file structure:
orm
global
{generated class files}
local
{generated class files}
Note above that I am specifying hvBaseClassLocal as the baseclass. This will make all generated class files extend from my hvBaseClassLocal class. This is great functionality if you have common methods you want available for all your classes (logging, etc).
Before you propel-gen you will want to make sure the files are going to be where and how you want them. This is specified in build.properties.
build.properties
propel.project = safetrax
propel.database = mysql
propel.targetPackage = orm
propel.mysql.tableType = InnoDB
propel.home = .
propel.projhome = /Users/jhansen/Sites/safetrax-zend
propel.output.dir = ${propel.projhome}/application/models
propel.schema.dir = ${propel.projhome}/config/schema
propel.conf.dir = ${propel.projhome}/config/conf
propel.phpconf.dir = ${propel.projhome}/config/conf
propel.sql.dir = ${propel.projhome}/config/sql
propel.runtime.conf.file = runtime-conf.xml
propel.php.dir = ${propel.projhome}/application/models
Note that there is no database connection information there. That info is used if you are going to have propel create your schema files for you (not recommended) or you want propel-gen to manage rebuilding the schema in your databases. It works fine when you have one database, but as soon as you add the second you are hosed, as it can only do one at time… therefore you end up hacking the file and running propel-gen again. So, we just avoid that whole mess by creating our schema.xml files manually and using a separate means for dealing with the databases you will see next.
Ok, next step is to run propel-gen script. This will go ahead and created all your object class files and peer classes. I wrote a little shell script that I use for development that does at bit more:
#!/bin/bash
propel-gen .
echo "DB Destroy & Recreate...";
mysql -u root -pmypassword < config/sql/setup.sql
echo "DB Loading Schema...";
mysql -u globaluser -pglobalpassword global < config/sql/global-schema.sql
mysql -u localuser -plocalpassword local < config/sql/local-schema.sql
echo "Loading Fixtures...";
cd config/fixtures; php populate.php;
echo "Done"
My setup.sql looks like this:
DROP DATABASE IF EXISTS `local`;
DROP DATABASE IF EXISTS `global`;
CREATE DATABASE `local` ;
CREATE DATABASE `global` ;
So, in essence when I execute ./regen.sh my databases are completely destroyed and recreated using setup.sql. Then the schema for both databases is loaded back in using the sql files generated from propel-gen. The next step is running populate.php which is a script I wrote for loading up fixtures that I need in place while in development.
populate.php
<?php
// Set the include
set_include_path("../../application/models" . PATH_SEPARATOR .
"../../application/models/orm" . PATH_SEPARATOR .'../../library' .
PATH_SEPARATOR . get_include_path());
include_once '../../library/hvTools.class.php';
include_once("propel/Propel.php");
Propel::init("../../config/conf/safetrax-conf.php");
$u = new User();
$u->setName("Jeff Hansen");
$u->save();
?>
Populate.php keeps getting larger as I add new objects to the project and load them up when regenerating. I have become very fond of this approach as it tests your code while it is working, therefore you will know right away if you have errors in any overloaded save methods or others that do more than just set attributes on the objects.
The last thing to do is to start acutally integrating this baby w/in the Zend Framework. This really couldn’t be easier. Open up your bootstrap file – index.php and add the following (adjust paths as necessary.):
index.php
set_include_path('.' . PATH_SEPARATOR . '../library' . PATH_SEPARATOR . '../application/models'. PATH_SEPARATOR . '../application/models/orm' . PATH_SEPARATOR . get_include_path());
include_once("propel/Propel.php");
Propel::init("../config/conf/safetrax-conf.php");
That’s it! Byahh! You will now be able to access your classes from both databases in a sane fashion. Below is an image of my project layout in Zend Studio for Eclipse. Click on it for full size.
If you have any questions feel free to ask.
Soldier Surprises His Son
This might make you cry
Marco Island – Saying Goodbye
Wow, the last 5 days have sure flown by. SafeTrax made a number of great contacts and continues to strengthen its position as an IARW Service Partner. There were literally hundreds of vendors at the expo, and I was surprised to see, once again, that no other company offers anything even similar to SafeTrax Online. The preventative maintenance integration we have done sparked a lot of interest as well. We are in a great position and offer a unique, much needed, product / service.
Sandie used some Mark Twain quotes as the basis for our focus session:
“If you eat a frog first thing in the morning, the rest of your day will be wonderful.”
“If you have to eat a frog, don’t look at it for too long.”
Your frog – looking all ugly and nasty on your plate – is the most important, most challenging, the biggest and hardest task you could possibly do. Now that you have eaten that ugly annoying frog you can focus on other tasks knowing you have finished the hardest part first. We have learned in this industry that the ‘frogs’ for many of these companies happen to be safety / regulation items. These are frogs that just don’t ever go away and must be managed regularly. Our spin was that we can really help by reducing the size of that frog through the use of better tools / services. I think it was well received as we had several people approach us after the presentation and comment on the effectiveness of the analogy, and how it relates to them.

The days here have been quite relaxing even with all the activities that we have been involved with. Most of the days started very early but we were finished by noon, which provided plenty of time to get sunburnt to a crisp (my chest took a scolding). The beaches here are beautiful with pure white sands and blue water. There are nice restaurants at the resort as well, so you really don’t have to leave if you don’t want to.
We ventured out a bit and found a great little restaurant called Snooks. We heard about it from the locals so we knew it must be good… and it didn’t disappoint. The food was good and hot and the scenery was even better. And if you like pickles, they have a 50 gallon barrel full of them. If you ever visit Marco Island, be sure to stop by.
The 2008 IARW-WFLO-IRTA Annual Convention & Expo
I am heading out tomorrow morning for the 2008 IARW-WFLO-IRTA Annual Convention & Expo. SafeTrax will have a booth as well as teaching a focus session titled: Altogether Now: Consolidating Your Maintenance and Safety Programs. If it is like all the other IARW events it should be a great time!
Zend Framework, Propel, jQuery
This is long overdue. I have been considering this post for quite some time but have been so wrapped up in development that I just haven’t taken the time to get it done.
Recently I was confronted with some difficult development decisions. It was time to totally redo a project that was getting… well, stale. The original code base was my first stab with PHP 5 object oriented goodness. I rolled my own classes and peers using a php script that connected to the mysql databases (2). There was no MVC framework involved. I used multiple PEAR classes including HTML_AJAX and MDB2.
The new project would need to accomplish the same things as the old… Only in a way that was more modular and easier-to-manage.
I started by analyzing different PHP frameworks. I spent at least 3 full days with each framework. In each case I followed tutorials and eventually attempted to build a simple site that would resemble my scenario.
Frameworks

Eventually I decided that Zend Framework was best for me. First, I am a fan of Zend. I like their products and think they deliver on their committments. Having the framework backed by a company helps as well. Second, I liked how I could as much or little of the framework as I wanted. Third, it just made sense to me.
I actually liked symfony quite a bit, but got frustrated when working with components… as I was getting some unusual results. CakePHP didn’t really appeal to me at all since it was based on PHP 4.
Unlike the other frameworks, Zend does not really come with the full blown ‘model’. I looked at 2.
ORMs

Both of these products are fantastic. I personally think that PHPDoctrine is the way of the future. At the time of my review they were at 0.10 release… so obviously not ready for production use at this point. Once it is stable, it could become the preferred ORM. For now however it is Propel. Propel is stable and has been in use for some time (1.3 beta is what I am using). I appreciate that fact that I can just use
$user = UserPeer::retrieveByPk(1);
instead of what propel requires
$user = $conn->getTable('User')->find(1);
Two problems for me in the above. First, I am dealing with 2 connections that are both being used simultaneously on every page (global and local). I dislike having to have a $conn around to make calls on… let alone make sure it is the right one. Second, I prefer the shorter static calls available with propel.
Also, I like the documentation for Propel better… it is actually much shorter and to the point. Again, like Zend Framework, it just made sense to me.

Last but not least I chose to use jQuery to replace HTML_AJAX and scriptaculous. Thus far I am very impressed with it and the many plugins that are available. Again, the documentation is great as well.
The great thing is that there are quality options to choose from. Each of the above mentioned products are great for different projects. I simply appreciate all the hard work that goes into all of them…
I will be posting some follow-ups on my specific usage of the above.

