Federico Cargnelutti

Simple is better than complex. Complex is better than complicated. | @fedecarg

Archive for February 2009

PHP UK Conference 2009 Recap

with 2 comments

The conference was very similar to previous years. The only difference was the venue and the weather. Yes, it was sunny in London, can you believe it? I went there to see Andrei Zmievski, Stefan Koopmanschap and Chris Shiflett. Unfortunately, Andrei could not make it. However, I got to see lots of people from the community.

Stefan gave an entertaining presentation about Symfony and some of the myths surrounding it. He was funny, creative and showed a lot of enthusiasm. Well done Stefan!

Chris talked about security-centered design and did a Sherlock Holmes routine which was just spot on. It was an interesting talk, he chose the right images and videos, avoided jargon and even managed to involve the audience.

Stuart Herbert’s talk was not what I expected. A lot of attendees who hadn’t used a framework before, were intrigued and wanted to know more about Symfony, Zend, Cake, Rails, Grails, Django and other non-MVC frameworks. Instead, he focused more on the reasons why his company decided to use Symfony. Good talk, but the title “Living with Frameworks” was a bit misleading.

Scott MacVicar gave an overview about PHP 5.3. Scott carries a great deal of respect in the community, maybe that’s the reason why he was chosen to deliver this talk, he did a good job mentioning some of the PHP interpreter improvements, including “late static binding” and “namespaces”.

Things not mentioned in the conference where: open platforms, open protocols, open standards, cloud computing, Zend framework, mashup applications, deployment (Puppet/RPMs), Linux, Git/Bazaar, Design patterns, mobile application development, social networking, OpenID, OAuth, CI, unit testing, Ant and Hudson, just to name a few. To be honest, I was a bit disappointed.

Thanks to Marcus Baker for organising this event, and to all of the sponsors, MySQL/Sun, IBM (the ProjectZero team), Adobe, and Microsoft.  I hope next year’s conference will be even better.

Written by Federico

February 28, 2009 at 12:34 pm

Posted in Frameworks, Open-source, PHP

Server-side Marker Clustering with PHP and Google Maps

with 5 comments

with_cluster2

As maps get busier, marker clustering is likely to be needed. Marker clustering is a technique by which several points of interest can be represented by a single icon when they’re close to one another.

Mika Tuupola wrote a PHP library that divides the map into a given number of cells and represents all the markers present in the same cell by a single icon. This icon shows the number of markers it symbolizes.

He also wrote an excellent post explaining how marker clustering works.

Related Posts

Written by Federico

February 26, 2009 at 3:32 pm

Zend Framework: The Cost of Flexibility is Complexity

with 30 comments

The Zend Framework is a very flexible system, in fact, it can be used to build practically anything. But, the problem with using a flexible system is that flexibility costs. And the cost of flexibility is complexity.

Martin Fowler wrote:

Every time you put extra stuff into your code to make it more flexible, you are usually adding more complexity. If your guess about the flexibility needs of your software is correct, then you are ahead of the game. You’ve gained. But if you get it wrong, you’ve only added complexity that makes it more difficult to change your software.

Don’t assume that just because you’re using an object-oriented framework you are writing reusable and maintainable code. You are just structuring your spaghetti code. As Paul Graham put it: “Object-oriented programming offers a sustainable way to write spaghetti code”. The main problem with flexibility is that most developers give up trying to understand. I don’t blame them, no one likes dealing with complexity. However, flexibility is sometimes required and generally always desirable. But, sometimes we forget that frameworks exist to help us solve or address complex issues, not to fix bad design decisions for us. So if your code is difficult to understand or unit test, then you are probably doing something wrong.

Just because you can, doesn’t mean you should

What’s the best way to render a view script in the Zend Framework? Think, don’t give up yet. Is it enabling or disabling the ViewRenderer action helper? Remember, the framework allows you to shape the Zend_Controller_Action class to your application’s needs.

The manual clearly states that:

By default, the front controller enables the ViewRenderer action helper. This helper takes care of injecting the view object into the controller, as well as automatically rendering views.

However, no one stops you from doing it manually:

Zend_Controller_Action provides a rudimentary and flexible mechanism for view integration. Two methods accomplish this, initView() and render(); the former method lazy-loads the $view public property, and the latter renders a view based on the current requested action, using the directory hierarchy to determine the script path.

Developer A

class IndexController extends Zend_Controller_Action
{
    public function searchAction()
    {
        $query = $this->_getParam('q', null);
        if (null === $query) {
            $this->view->error = 'Invalid query';
            return;
        }

        $this->view->query = $query;
        if (is_numeric($query)) {
            $this->setUserDetailsById($query);
        } else {
            $this->setUserDetailsByName($query);
        }
    }

    public function setUserDetailsByName($name)
    {
        $row = $this->findUserByName($name);
        $this->view->userId = $row['id'];
        $this->view->userName = $row['name'];
    }

    public function setUserDetailsById($id)
    {
        $row = $this->findUserById($id);
        $this->view->userId = $row['id'];
        $this->view->userName = $row['name'];
    }
}

Developer B

class IndexController extends Zend_Controller_Action
{
    protected $_viewParams = array(
        'error'    => null,
        'query'    => null,
        'userId'   => null,
        'userName' => null,
    );

    public function init()
    {
        $this->_helper->removeHelper('viewRenderer');
    }

    public function searchAction()
    {
        $query = $this->_getParam('q', null);
        if (null === $query) {
            $this->_viewParams['error'] = 'Invalid query';
            $this->renderView('search');
            return false;
        }

        return $this->displayUserDetails($query);
    }

    public function displayUserDetails($query)
    {
        if (is_numeric($query)) {
            $row = $this->getUserDetailsById($query);
        } else {
            $row = $this->getUserDetailsByName($query);
        }

        if (!$row) {
            $this->_viewParams['error'] = 'User not found';
            $this->renderView('search');
            return false;
        }

        foreach ($this->_viewParams as $key => $value) {
            if (!array_key_exists($key, $row) {
                continue;
            }
            $this->_viewParams[$key] = $row[$key];
        }

        $this->_viewParams['query'] = $query;
        $this->renderView('search');

        return true;
    }

    public function renderView($template)
    {
        $view = $this->initView();
        foreach ($this->_viewParams as $key => $value) {
            $view->$key = $value;
        }
        $this->render($template);
    }

    public function getUserDetailsByName($name)
    {
        return $this->findUserByName($name);
    }

    public function getUserDetailsById($id)
    {
        return $this->findUserById($id);
    }
}

Same problem, different solutions.

Now, guess who is doing test-driven development, has all his code unit tested, puts commonly used code into libraries, abstracts out common patterns of behaviour, writes his code using the top-down fashion and uses the principle of “least astonishment”.

Developer A or B?

Conclusion

Many requirements lie in the future and are unknowable at the time our application is designed and built. To avoid burdensome maintenance costs developers must therefore rely on a system’s ability to change gracefully its flexibility. The combination of flexibility and smart design can reduce the maintenance burden. It’s up to us, the developers, to change our thinking when using a flexible framework. Like I said before, frameworks exist to help us solve complex issues, not to make decisions for us.

Written by Federico

February 22, 2009 at 10:03 pm

MySQL Split String Function

with 44 comments

MySQL does not include a function to split a delimited string. However, it’s very easy to create your own function.

Create function syntax

A user-defined function is a way to extend MySQL with a new function that works like a native MySQL function.

CREATE [AGGREGATE] FUNCTION function_name
RETURNS {STRING|INTEGER|REAL|DECIMAL}

To create a function, you must have the INSERT privilege for the <mysql> database.

Split delimited strings

The following example function takes 3 parameters, performs an operation using an SQL function, and returns the result.

Function

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '');

Usage

SELECT SPLIT_STR(string, delimiter, position)

Example

SELECT SPLIT_STR('a|bb|ccc|dd', '|', 3) as third;

+-------+
| third |
+-------+
| ccc   |
+-------+

Written by Federico

February 22, 2009 at 12:11 pm

Posted in Databases

Apache Log Analyzer 2 Feed

with 2 comments

I found this project thanks to Raphael’s post Turning a Zend_Log log file into an RSS feed.

Developed by Simone Carletti, ApacheLogAnalyzer2Feed is a really powerful open source PHP 5 class to parse and analyse Apache Web Server log files. Results are converted into a feed to let users subscribe them with a feed reader. You can define custom filters based on logs data — for instance User-Agent, IP, requested page, etc— and combine them to select just a limited resultset. The class can easily be extended with additional filters and custom feed handlers.

On a side note, Simone’s Wiki is powered by Redmine, an awesome Ruby on Rails Wiki and project management system that’s worth checking out.

Written by Federico

February 21, 2009 at 2:25 pm

ActiveRecord: JavaScript ORM Library

leave a comment »

Aptana has just released a beta version of its ActiveRecord.js which is an ORM JavaScript library that implements the ActiveRecord pattern. It works with AIR and other environments:

ActiveRecord.js is a single file, MIT licensed, relies on no external JavaScript libraries, supports automatic table creation, data validation, data synchronization, relationships between models, life cycle callbacks and can use an in memory hash table to store objects if no SQL database is available.

Example:

var User = ActiveRecord.define('users',{
    username: '',
    email: ''
});
User.hasMany('articles');

var ryan = User.create({
    username: 'ryan',
    email: 'rjohnson@aptana.com'
});

var Article = ActiveRecord.define('articles',{
    name: '',
    body: '',
    user_id: 0
});
Article.belongsTo('user');

var a = Article.create({
    name: 'Announcing ActiveRecord.js',
    user_id: ryan.id
});
a.set('name','Announcing ActiveRecord.js!!!');
a.save();

a.getUser() == ryan;
ryan.getArticleList()[0] == a;

Links

Written by Federico

February 16, 2009 at 8:55 pm

Building a Web Service Client using the Zend Framework

with 9 comments

UPDATE: Interested in creating a web API? Read this post instead.

In this post I’ll demonstrate how to use the Zend Framework to quickly and easily develop a Web application that consumes a Web API as a Web service.

The Zend Framework puts heavy emphasis on Web services. This is a good thing, considering the amount of Web services out there that can help lower costs and increase the value of your site.

The various steps that are involved in creating a Web service client are as follows:

  1. Find a Web Service provider.
  2. Identify Web service endpoints.
  3. Identify query string parameters to endpoints.
  4. Identify response types.
  5. Create a proxy object for the Web service.

Find a Web Service provider

In this example, I’ll develop a Web services client to Digg, a real-world Web services provider. The Digg API has been created to let users interact programmatically with Digg. The API accepts REST requests and offers several response types. More info here: http://apidoc.digg.com/

Identify Web service endpoints

A Web services endpoint is a resource where Web services messages can be targeted. For example:

GET /stories
    All stories.
GET /stories/popular
    Popular stories.
GET /stories/topic//popular
    Popular stories from a given topic.

Let’s assume you only need to target a single endpoint, for example, fetch popular stories by topic:

http://services.digg.com/stories/topic/programming/popular/

Identify query string parameters to endpoints

You can pass additional arguments to a Web service by specifying additional parameters and then passing values for those parameters. In theory, a GET should retrieve a representation of a resource identified by a URI, but many APIs make it extremely easy to view the URI not as a resource identifier, but as a convenient means to encode parameters.

A good example of this is the Digg API that allows you to specify parameters in the query string. For example:

appkey
    The value of the application key.
sort
    How to sort returned stories.
count
    Number of stories to retrieve.
offset
    Offset in complete story list.
domain
    Partial domain of linked article.
link
    URL of linked article.

Identify Response Types

The Digg API provides several response types, each designed to be useful in a variety of programming contexts:

  • text/xml: XML response type
  • application/json: JSON response type
  • text/javascript: Javascript response type
  • application/php: Serialized PHP response type

Create a proxy object for the Web service

We are now ready to create a proxy object to extract data from the Web service. Because the Digg API accepts REST requests, we’ll create a Zend_Service_Digg class that extends Zend_Rest_Client, this allows us to take advantage of some predefined accessor and mutator methods, such as getUri() and setUri():

class Zend_Service_Digg extends Zend_Rest_Client
{
    protected $_uri = 'http://services.digg.com/';

    public function __construct()
    {
        $this->setUri($this->_uri);
        $client = self::getHttpClient();
        $client->setHeaders('Accept-Charset', 'ISO-8859-1,utf-8');
    }
...

Digg provides different response types, so we need to create a method to allow the user define the context (Codepad):

...
    protected $_responseType = 'xml';
    protected $_responseTypes = array('php', 'xml', 'json');

    public function setResponseType($responseType)
    {
        if (!in_array(strtolower($responseType), $this->_responseTypes)) {
            throw new Zend_Service_Digg_Exception('Invalid Response Type');
        }

        $this->_responseType = strtolower($responseType);
        return $this;
    }

    public function getResponseType()
    {
        return $this->_responseType;
    }
...

Now we’ll create a setter and getter method to pass and retrieve additional parameters (Codepad):

...
    protected $_params = array();

    public function setParams($params)
    {
    	// Validate mandatory parameters to endpoint
    	if (!array_key_exists('appkey', $params)) {
            throw new Zend_Service_Digg_Exception('Param appkey missing');
        }

        foreach ($params as $key => $value) {
            switch (strtolower($key)) {
                case 'type':
                    $this->setResponseType($value);
                    break;
                default:
                    $this->_params[$key] = $value;
                    break;
            }
        }

        return $this;
    }

    public function getParams()
    {
    	return $this->_params;
    }
...

All the values of the arguments must be URL encoded. Fortunately, Zend_Rest_Client takes care of this for us. Next, we’ll create a method that fetches the most popular stories by a given topic (Codepad):

...
    public function fetchPopularStoriesByTopic($topic, array $params = array())
    {
        $this->setParams($params);

        $path = sprintf('/stories/topic/%s/popular/', trim(strtolower($topic)));
        return $this->sendRequest('GET', $path);
    }
...

And finally, we create 2 methods, one that sends the request and another one that formats the response data (Codepad):

...
    public function sendRequest($requestType, $path)
    {
        $requestType = ucfirst(strtolower($requestType));
        if ($requestType !== 'Post' && $requestType !== 'Get') {
            throw new Zend_Service_Digg_Exception('Invalid request type: ' . $requestType);
        }

        try {
            $requestMethod = 'rest' . $requestType;
            $response = $this->{$requestMethod}($path, $this->getParams());
            return $this->formatResponse($response);
        } catch (Zend_Http_Client_Exception $e) {
            throw new Zend_Service_Digg_Exception($e->getMessage());
        }
    }

    public function formatResponse(Zend_Http_Response $response)
    {
        if ('json' === $this->getResponseType()) {
            return $response->getBody();
        } elseif ('php' === $this->getResponseType()) {
            return unserialize($response->getBody());
        } else {
            return new Zend_Rest_Client_Result($response->getBody());
        }
    }
}

Usage

$digg = new Zend_Service_Digg();

$params = array('type'=>'json', 'appkey'=>'http://api.test.com');
$stories = $digg->fetchPopularStoriesByTopic('programming', $params);

Response:

http://services.digg.com/stories/topic/programming/popular/?type=json&appkey=http%3A%2F%2Fapi.test.com

Zend_Service_Digg class

That’s it! Time to open your editor and start building some cool WS clients :)

Written by Federico

February 15, 2009 at 6:44 pm

Command Line Kung Fu Developer

leave a comment »

Want to become a Linux guru, or just look like one? Then visit Command-Line-Fu.

From the site:

Command-Line-Fu is the place to record those command-line gems that you return to again and again. Delete that bloated snippets file you’ve been using and share your personal repository with the world. That way others can gain from your CLI wisdom and you from theirs too. All commands can be commented on and discussed. Voting is also encouraged so the best float to the top.

You can subscribe to the feeds or follow the latest commands on Twitter. Every new command is wrapped in a tweet and posted to the Command-Line-Fu account.

Command-Line-Fu

Written by Federico

February 13, 2009 at 1:20 pm

Posted in Linux

Geo Proximity Search: The Haversine Equation

with 24 comments

I’m working on a project that requires Geo proximity search. Basically, what I’m doing is plotting a radius around a point on a map, which is defined by the distance between two points on the map given their latitudes and longitudes. To achieve this I’m using the Haversine formula (spherical trigonometry). This equation is important in navigation, it gives great-circle distances between two points on a sphere from their longitudes and latitudes. You can see it in action here: Radius From UK Postcode.

This has already been covered in some blogs, however, I found most of the information to be inaccurate and, in some cases, incorrect. The Haversine equation is very straight forward, so there’s no need to complicate things.

I’ve implemented the solution in SQL, Python and PHP. Use the one that suits you best.

SQL implementation

set @latitude=53.754842;
set @longitude=-2.708077;
set @radius=20;

set @lng_min = @longitude - @radius/abs(cos(radians(@latitude))*69);
set @lng_max = @longitude + @radius/abs(cos(radians(@latitude))*69);
set @lat_min = @latitude - (@radius/69);
set @lat_max = @latitude + (@radius/69);

SELECT * FROM postcode
WHERE (longitude BETWEEN @lng_min AND @lng_max)
AND (latitude BETWEEN @lat_min and @lat_max);

Python implementation

from __future__ import division
import math

longitude = float(-2.708077)
latitude = float(53.754842)
radius = 20

lng_min = longitude - radius / abs(math.cos(math.radians(latitude)) * 69)
lng_max = longitude + radius / abs(math.cos(math.radians(latitude)) * 69)
lat_min = latitude - (radius / 69)
lat_max = latitude + (radius / 69)

print 'lng (min/max): %f %f' % (lng_min, lng_max)
print 'lat (min/max): %f %f' % (lat_min, lat_max)

PHP implementation

$longitude = (float) -2.708077;
$latitude = (float) 53.754842;
$radius = 20; // in miles

$lng_min = $longitude - $radius / abs(cos(deg2rad($latitude)) * 69);
$lng_max = $longitude + $radius / abs(cos(deg2rad($latitude)) * 69);
$lat_min = $latitude - ($radius / 69);
$lat_max = $latitude + ($radius / 69);

echo 'lng (min/max): ' . $lng_min . '/' . $lng_max . PHP_EOL;
echo 'lat (min/max): ' . $lat_min . '/' . $lat_max;

It outputs the same result:

lng (min/max): -3.1983251898421/-2.2178288101579
lat (min/max): 53.464986927536/54.044697072464

That’s it. Happy Geolocating!

Written by Federico

February 8, 2009 at 11:48 am

Four Great InfoQ Presentations

with one comment

Hope you like these recommendations and if you know of any other good tech-related video, then please let me know.

1. Developing Expertise: Herding Racehorses, Racing Sheep

One of my favourites. In this presentation Dave Thomas (The Pragmatic Programmer) talks about expanding people’s expertise in their domains of interest by not treating them uniformly as they had the same amount of knowledge and level of experience.

Developing Expertise

2. Real World Web Services

Another good presentation. In this one Scott Davis provides a pragmatic, down-to-earth introduction to Web services as used in the real world by public sites, including SOAP-based and REST examples.

Real World Web Services

3. CouchDB and me

This presentation is different, and that’s why I like it so much. Damien Katz shares his experiences and reminds people how difficult but at the same time gratifying is to be an open source developer. He talks about the history of CouchDB development from a very personal point of view. His inspirations for CouchDB and why he decided to move my wife and kids to a cheaper place and live off savings to build this thing.

CouchDB and me

4. Yahoo! Communities Architectures

In this presentation, Ian Flint tries to explain the infrastructure and architecture employed by Yahoo! to keep going a multitude of servers running of different platforms and offering different services. Very interesting!

Yahoo! Communities Architectures

Written by Federico

February 6, 2009 at 12:02 am

Follow

Get every new post delivered to your Inbox.

Join 1,033 other followers