Converting URLs to links with PHP

June 4, 2010

While trying to read user timelines from the Twitter API, I found out that the tweets are only available in plain text. Of course, it is nicer (and more usable) if URLs are actually displayed as links. With a little use of regular expressions, this can easily be done.

But if you have long URLs and are displaying tweets in a relatively narrow column, this leads to a problem. Your tweets can have large gaps, depending how your browser puts line breaks in URLs. Some browsers break on slashes, some on dashes, on both or not at all. So I wrote a small function in PHP to add zero width breaks to links. Because I want to determine how links break and not leave it up to some random browser.

function linkify($str) {
    return preg_replace_callback('@(https?://)(\S+)@smu', 'linkify_callback', $str);
}

function linkify_callback($matches)
{
    $title = str_replace(
        array('/', '.', '-'),
        array('/​','.​', '-​'),
        $matches[2]);

    return '<a href="' . $matches[1] . $matches[2] . '">' . $matches[1] . $title . '</a>';
}

And in case you are wondering. Yes, I do not like to use URL shorteners.

Validating email addresses in PHP made simple

May 22, 2010

An important aspect of processing user input on a website should be filtering it. Primarely for security reasons, but also to have valid data. Since PHP 5.2 it is very easy to validate (and sanitize) user input using the filter functions. But a lot of PHP developers seem not to be aware of them and create their own filters using regular expressions. Which is very easy to get wrong. So I highly recommend the built-in PHP filters.

Here is a simple example for validating email addresses:

if( !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL) ) {
    echo 'Invalid email address';
}

Because who needs invalid data?

Activating translations for Yii core messages

January 29, 2010

The excellent Yii framework makes it easy to jumpstart development and quickly create a working prototype. It also includes flexible translation features. But the official documentation for internationalization isn't all that clear on how to activate the translations for the Yii core messages. A lot of translations are included in the default download.

Turns out that you have to define both the source language and the target language. The default source language is english, but it only seems to work if you define it explicitly.

To activate translations for your entire app, change "protected/config/main.php" accordingly:

return array(
  …
  'language' => 'de',
  …
  'components'=>array(
    …
    'coreMessages' => 'en',
    …
  ),
  …
);

Modernism & Post-Modernism in Web Design

January 19, 2010

Here are the slides of my talk at Web Montag Frankfurt

Using Zend AMF with the CodeIgniter PHP framework

December 8, 2009

CodeIgniter is an very easy to use and fast framework. From all the PHP frameworks out there it is probably the one closest to the way PHP actually works. It doesn't try to be an enterprise level solution, but focuses on practicality, flexibility and ease of use. For example: you can use an MVC setup, but only if you want to. It doesn't force you to follow strict rules. A reason why Rasmus Lerdorf actually likes the framework.

Also you can integrate other libraries. If you are building Flash/Flex applications probably you would want to use the Zend AMF component from the Zend Framework. It has been developed in cooperation with Adobe to create web services that can use the AMF data exchange format.

First you have to create an autoloader for the Zend Framework to easily access Zend components. Assuming you put the Zend Framework in the system/libraries/Zend folder, create system/application/libraries/zend.php:

<?php if( !defined('BASEPATH')) exit('No direct script access allowed');
class Zend {
  public function __construct() {
    ini_set('include_path',ini_get('include_path').PATH_SEPARATOR.APPPATH.'libraries/');
    require('Zend/Loader/Autoloader.php');
    spl_autoload_register(array('Zend_Loader_Autoloader','autoload'));
  }
}

After this you can create a web service by creating the appropriate controller:

class Items extends Controller {
  public function __construct() {
    parent::Controller();

    $this->load->library('zend');
  }

  public function index() {
    $server = new Zend_Amf_Server();
    $server->setClass(__CLASS__);
    echo $server->handle();
  }

  public function getData() {
    return array(1,2,3,'...');
  }

  public function getItem($id) {
    $this->load->model('Itemmodel');
    return $this->Itemmodel->getItem($id);
  }
}

Be aware that you have to load any model from inside the method you are calling. It cannot loaded from the constructor, because this will create a conflict with the Zend AMF instance. Which I found out the hard way.