A web developer's blog. PHP, MySQL, CakePHP, Zend Framework, Wordpress, Code Igniter, Django, Python, CSS, Javascript, jQuery, Knockout.js, and other web development topics.

Zend Framework: Using Command Line Scripts

Thanks to David Caunt for this very useful article.

The article shows us how to create command line scripts using Zend Framework components. This is very useful especially with the database stuff.

<?php
 
// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH',
              realpath(dirname(__FILE__) . '/../application'));
 
// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV',
              (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
                                         : 'production'));
 
require_once 'Zend/Application.php';
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/config.php'
);
 
//only load resources we need for script, in this case db and mail
$application->bootstrap(array('db', 'mail'));

Using it would be something like this:

$db = $application->getBootstrap()->getResource('db');
 
//do something!
$row = $db->fetchRow('SELECT * FROM something');

The source can be found here. Sorry for the copy-paste. This is so useful that I want to see the code every time I forget.

Thanks to Rob Allen for directing me to David Caunt.

Posted in General | Tagged , , , | 1 Comment

How to Unit Test your Zend Framework Application

I am trying to learn Unit Testing using Zend Framework. I have set up a test application called LyZend in Github. Supposedly, the application should be able to display artists, albums, and tracks.

The tests are found in: http://github.com/wenbert/lyzend/tree/master/tests/ I have follwed Matthew Weier O’phinney’s method of setting up the tests.

lyzend / tests / TestHelper.php

<?php
require_once 'TestConfig.php';
 
/*
 * Start output buffering
 */
ob_start();
 
/*
 * Set error reporting to the level to which Zend Framework code must comply.
 */
error_reporting( E_ALL | E_STRICT );
 
/*
 * Set default timezone
 */
date_default_timezone_set('GMT');
 
/*
 * Determine the root, library, tests, and models directories
 */
$root        = realpath(dirname(__FILE__) . '/../');
$library     = $root . '/library';
$tests       = $root . '/tests';
$models      = $root . '/application/models';
$controllers = $root . '/application/controllers';
 
/*
 * Prepend the library/, tests/, and models/ directories to the
 * include_path. This allows the tests to run out of the box.
 */
$path = array(
    $models,
    $library,
    $tests,
    get_include_path()
    );
set_include_path(implode(PATH_SEPARATOR, $path));
 
/**
 * Register autoloader
 */
require_once 'Zend/Loader/Autoloader.php';
//Zend_Loader::registerAutoload();
Zend_Loader_Autoloader::getInstance();
 
/*
 * Add library/ and models/ directory to the PHPUnit code coverage
 * whitelist. This has the effect that only production code source files appear
 * in the code coverage report and that all production code source files, even
 * those that are not covered by a test yet, are processed.
 */
if (defined('TESTS_GENERATE_REPORT') && TESTS_GENERATE_REPORT === true &&
    version_compare(PHPUnit_Runner_Version::id(), '3.1.6', '>=')) {
    PHPUnit_Util_Filter::addDirectoryToWhitelist($library);
    PHPUnit_Util_Filter::addDirectoryToWhitelist($models);
    PHPUnit_Util_Filter::addDirectoryToWhitelist($controllers);
}
 
 
/**
 * Setup default DB adapter
 */
/*
$db = Zend_Db::factory('pdo_sqlite', array(
    'dbname' => $root . '/data/db/bugs.db',
));
Zend_Db_Table_Abstract::setDefaultAdapter($db);
*/
 
 
/*
 * Unset global variables that are no longer needed.
 */
unset($root, $library, $models, $controllers, $tests, $path);

You might noticed that I included a TestConfig.php file above. Here is the file:

<?php
 
// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
 
// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing'));
 
// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

Here is a sample test for my Artist Model.
lyzend / tests / application / models / ArtistTest.php

<?php
// Call Model_ArtistTest::main() if this source file is executed directly.
if (!defined("PHPUnit_MAIN_METHOD")) {
    define("PHPUnit_MAIN_METHOD", "Model_ArtistTest::main");
}
 
require_once dirname(__FILE__) . '/../../TestHelper.php';
 
/** Model_Artist */
require_once 'Artist.php';
require_once 'ArtistMapper.php';
require_once 'DbTable/Artist.php';
 
/**
 * Test class for Model_Artist.
 *
 * @group Models
 */
class Model_ArtistTest extends Zend_Test_PHPUnit_ControllerTestCase 
{
    /**
     * Runs the test methods of this class.
     *
     * @return void
     */
    public static function main()
    {
        $suite  = new PHPUnit_Framework_TestSuite("Model_ArtistTest");
        $result = PHPUnit_TextUI_TestRunner::run($suite);
    }
 
    /**
     * Sets up the fixture, for example, open a network connection.
     * This method is called before a test is executed.
     *
     * @return void
     */
 
    public function setUp()
    {
        $this->bootstrap = new Zend_Application(
            APPLICATION_ENV,
            APPLICATION_PATH . DIRECTORY_SEPARATOR . 'configs' . DIRECTORY_SEPARATOR . 'application.ini'
        );
        parent::setUp();
 
    }
 
    /**
     * Tears down the fixture, for example, close a network connection.
     * This method is called after a test is executed.
     *
     * @return void
     */
    public function tearDown()
    {
    }
 
    public function testCanTest()
    {
        //this is a sample test
    }
}

The XML file is like this:

<phpunit>
    <testsuite name="Ly Test Suite">
        <directory>./</directory>
    </testsuite>
 
    <php>
        <!-- <ini name="include_path" value="../library"/> -->
    </php>
 
    <filter>
        <whitelist>
            <directory suffix=".php">../library/</directory>
            <directory suffix=".php">../application/</directory>
            <exclude>
                <directory suffix=".phtml">../application/</directory>
                <file>../application/Bootstrap.php</file>
                <file>../application/controllers/ErrorController.php</file>
            </exclude>
        </whitelist>
    </filter>
 
    <logging>
        <log type="coverage-html" target="./log/report" charset="UTF-8"
            yui="true" highlight="true"
            lowUpperBound="50" highLowerBound="80"/>
        <log type="testdox-html" target="./log/testdox.html" />
    </logging>
</phpunit>

Running the test would be something like this:

phpunit --configuration phpunit.xml

Matthew did not provide sample test for Mappers. So I created one something like this:

$mapper = new Ly_Model_ArtistMapper();
$this->assertTrue($mapper instanceof Ly_Model_ArtistMapper);

My process was like:

  1. Setup Unit Testing in Zend Framework
  2. Create tests (let’s say for Artist Model).
  3. Make code in my model to pass the tests.
  4. Repeat step 2 and then go to next model if satisfied.

FYI: I am not so sure about my Model. I am not sure if I am breaking any rules when I created them. It would be cool if you could check them out (http://github.com/wenbert/lyzend/tree/master/application/models/) and discuss my mistakes below.

Thanks!

Posted in General | Tagged , , | 5 Comments

Akra’s Zend Framework 1.10 Tutorial

From Akrabat’s blog:

As a result, I have updated my Zend Framework tutorial so that it is completely current. The main change I made was to remove the _init methods in the Bootstrap as they are no longer needed. I also take advantage of the new features of the zf tool to enable layouts and create forms. It’s a shame that it gets the class name of the form wrong though!

Posted in General | Tagged , , | Leave a comment

HTML5 Canvas Tutorial

The Paint Application from Mugtug.com is very impressive. It uses HTML5. Very responsive. I found it in HN and the hackers seemed to be impressed as well.

Around the web, people are already talking about HTML5 and Canvas as a replacement for Flash. Click here to read the Canvas Tutorial.

Posted in General | Tagged , , | Leave a comment

An example of an Object-relational Mapper in PHP

Dennis Hotson posted in his blog a brief and good example of an ORM for PHP.

What is an Object-relational Mapper?

Data management tasks in object-oriented (OO) programming are typically implemented by manipulating objects that are almost always non-scalar values. For example, consider an address book entry that represents a single person along with zero or more phone numbers and zero or more addresses. This could be modeled in an object-oriented implementation by a “person object” with “slots” to hold the data that comprise the entry: the person’s name, a list of phone numbers, and a list of addresses. The list of phone numbers would itself contain “phone number objects” and so on. The address book entry is treated as a single value by the programming language (it can be referenced by a single variable, for instance). Various methods can be associated with the object, such as a method to return the preferred phone number, the home address, and so on.

However, many popular database products such as structured query language database management systems (SQL DBMS) can only store and manipulate scalar values such as integers and strings organized within normalized tables. The programmer must either convert the object values into groups of simpler values for storage in the database (and convert them back upon retrieval), or only use simple scalar values within the program. Object-relational mapping is used to implement the first approach.

The heart of the problem is translating those objects to forms that can be stored in the database for easy retrieval, while preserving the properties of the objects and their relationships; these objects are then said to be persistent.

-Wikipedia

The full source code can be found in Github.

I’m sure this will come in handy as a reference in the future. Thanks to Dennis Hotson for sharing.

Posted in General | 3 Comments

A Quick Update

Hello All. Sorry for the few updates. I have not been doing any Zend Framework / PHP related work for over a month now. I am in Aurland, Norway for a training. I will be staying here for about three months. I will be back home on April 2010.

Right now, I am thinking of starting a new pet project. I have the initial specifications in my head and I will put it into writing when I have time.

I will have more updates and Zend Framework / jQuery / PHP / MySQL / web development related soon.

Thanks!

-wenbert

Posted in General | Tagged | 2 Comments

Excel-like Javascript Grid Editors

Here is quick quote:

A short list of my favorite JavaScript grid components.
How many times did you hear users asking you: “something simple, a grid like excel”?

When I was a VB programmer, oh yes, I have this dark spot on my career, and it is not the only one… this request threw me in panic. Usually what your “killer” is asking you is not what you, programmer, are thinking of (namely the power of cell functions, programmability, graph etc., that probably your “killer” does not even imagine): what they are thinking about is the editor flexibility, the ability to add columns, rows, move cells blocks, copy and paste from different sources.

After the ritual pointing-out that your application is NOT Excel, the VB solution was to adopt the standard flexGrid or the mythical TrueDbGrid that made happy both the killer-user and the victim-programmer.

The source here: roberto.open-lab.com

Posted in General | Leave a comment

Zend Framework: Accessing configuration data in application.ini

Lately, I haven’t been doing any Zend Framework related things. Although currently tied up with other stuff, I check the community from time to time. Today, I found this quick and useful tip from Akrabat.

Akra talks about how you can access your configuration that you have set in your application.ini file – your configuration file.

Since it is a short post, I will copy-paste everything here.

Zend_Application will read the data in your application.ini and make it available from your bootstrap’s getOptions() method. It then sets the bootstrap as a parameter in the front controller. Note that the top level keys are all normalised to lowercase too.

You can then retrieve the options in a number of ways.

In the controller you can do this:

    public function someAction()
    {
        $bootstrap = $this->getInvokeArg('bootstrap'); 
        $options = $bootstrap->getOptions();
    }

Outside of the controller you can do this:

    $bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
    $options = $bootstrap->getOptions();

One downside is that $options is a nested array, and not a Zend_Config object. If you prefer to work with a Zend_Config object you need to create it yourself as Zend_Application discards the one it creates. The easiest way to do this is to create a new method in your bootstrap to create the Zend_Config object and store to the registry.

    protected function _initConfig()
    {
        $config = new Zend_Config($this->getOptions());
        Zend_Registry::set('config', $config);
        return $config;
    }

You can then get at your config data wherever you need it. Try not to depend too much on Zend_Registry keys though, as it can make testing harder.

Of course, the source is found here with all the comments from Akrabat’s readers.

Posted in General | 3 Comments

My free WordPress Theme: Warmth

I got bored and spent a few days creating a theme in WordPress. This is a quick release of the theme and I tested this in Firefox and Chrome. screenshot

You can download it here.

Nothing special except that I spent about 4 hours creating the header image for it. LOL :P

Also, I have not validated the HTML and CSS for this theme. I got tired and I need to do something else – um like play CounterStrike: Source (?). But seriously, I am starting to get busy and thought that I should finish and release this now.

And oh, by the way, Eddie Vedder is in the theme. Just wanted to share. Thanks!

Posted in General | Tagged , , | Leave a comment

I’m giving away 20 Google Wave invites!

I have 20 available Google Invites. Leave your email below. Format it to something like youremail[AT]gmail.com or something to avoid getting spammed. Just leave your email in the Email textbox when commenting :P

First 20 legit emails will get the invites.

UPDATE:
I still have around 10 or so invites left.

Posted in General | Tagged , | 27 Comments