Playing With Wire » PHP http://www.playingwithwire.com The Internet Startup Blog Wed, 20 Jul 2011 18:45:29 +0000 en-US hourly 1 A Condensed Guide to Extending PHP http://www.playingwithwire.com/2007/07/a-condensed-guide-to-extending-php/ http://www.playingwithwire.com/2007/07/a-condensed-guide-to-extending-php/#comments Fri, 13 Jul 2007 22:24:44 +0000 http://www.playingwithwire.com/2007/07/a-condensed-guide-to-extending-php/ This guide is for the programmer who needs to write a quick and dirty PHP extension. A PHP extension is a module for PHP written in C. You may wish to write such a module to expose library functionality only available in C, or to optimize certain key sections in your execution path.

As I have done before, I will attempt to make a terse summary. I assume you have or confidently can acquire knowledge of PHP and C. I’m a big fan of simple cookbook ‘recipe’ like guides, so here we go. Hold on to your hat.

Step 1: Compile PHP With Debugging Enabled

When developing your own module, you’ll want to enable debugging in PHP. This will generate error messages which may contain additional information beyond an unhelpful ‘segmentation fault’ when your module crashes.

In FreeBSD, just go into your ports, and do make config. Turn on the ‘debugging’ option and recompile PHP and its modules. Other platforms are similar; if you’re compiling from source by hand, take a look at the output of ./configure --help and you’ll find the right option for your version.

Before you start working on your module, make sure everything is in order with your server and that your extensions.ini file looks good. In my experience, rebuilding PHP under FreeBSD sometimes causes modules to appear twice in the extensions.ini file, and you may wish to be wary of this.

Step 2: Set up a project skeleton

PHP comes with great support for developing your module. There are a couple of scripts and configure related tools that automate almost all the work for you.

First, create a config.m4 file in your new project. (There’s even a tool that does this for you – ext_skel – but we’ll do it by hand for the purposes of this guide.) Here’s a bare bones config.m4 file for an extension named “pwwext”:

dnl config.m4 for extension pww

PHP_ARG_ENABLE(pwwext, whether to enable pww support,
[  --enable-pwwext          Enable pww support])

if test "$PHP_PWWEXT" != "no"; then
  PHP_NEW_EXTENSION(pwwext, pwwext.c, $ext_shared)
fi

You’ll also need some source code. Lets begin with the header file, which we’ll call pwwext.h. Lets write a minimal header:


#ifndef PHP_PWWEXT_H
#define PHP_PWWEXT_H

#define PHP_PWWEXT_EXTNAME  "pwwext"
#define PHP_PWWEXT_EXTVER   "0.1"

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"

extern zend_module_entry pwwext_module_entry;
#define phpext_pwwext_ptr &pwwext_module_entry

#endif /* PHP_PWWEXT_H */

In my experience, it’s often a waste of time to learn things before you need them. This is a good example of that: the header code does pretty much what it appears to do, and more in depth knowledge is not strictly needed. In short it exposes the entry point of the module and brings in the most important header files.

Step 3: The Actual Source

Finally, we’ll need the file we referred to in config.m4 previously. It’s the main source file, pwwext.c:

/*
 * This extension enables cool pww functionality.
 */

#include "pwwext.h"

PHP_FUNCTION(pwwext_calculate)
{
  long a, b;
  
  /* Get some params. */
  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 
      "ll", &a, &b) == FAILURE) {
    RETURN_NULL();
  }

  if (a < = 0) {
    zend_throw_exception(zend_exception_get_default(), 
      "First argument can't be negative nor zero.", 
      0 TSRMLS_CC);
    RETURN_NULL();    
  }

  /* 
  PHP preallocates space for return values, so
  its important to use these return macros.
  */
  RETVAL_LONG(a+b);  
  return;
}

static function_entry php_pwwext_functions[] = {
  PHP_FE(pwwext_calculate, NULL)
  { NULL, NULL, NULL }
};

zend_module_entry pwwext_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
  STANDARD_MODULE_HEADER,
#endif
  PHP_PWWEXT_EXTNAME,
  php_pwwext_functions, /* Functions */
  NULL, /* MINIT */
  NULL, /* MSHUTDOWN */
  NULL, /* RINIT */
  NULL, /* RSHUTDOWN */
  NULL, /* MINFO */
#if ZEND_MODULE_API_NO >= 20010901
  PHP_PWWEXT_EXTVER,
#endif
  STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_PWWEXT
ZEND_GET_MODULE(pwwext)
#endif

There are a couple of important structures here. The variable php_pwwext_functions lists all the functions we wish to expose from the module. In our example, we’re only exporting a single function.

Then we have the pwwext_module_entry structure which truly is the entry point into your module. If you would look near the sixth line in the structure you’d see a pointer to our list of functions, for instance.

Step 4: Compiling and Running

Finally, we’ll want to build the actual module. The command phpize will get everything in order for a compilation based on your configuration. After phpize is done, the normal configure make dance is all we need. Make note of the ‘--enable-pwwext‘ argument to configure.

  1. [~/pwwext]$ phpize
  2. ./configure --enable-pwwext
  3. make

That’s all there is to it. Your module should now be built and almost ready to go. To wrap up, you’ll need to install the module in your PHP extensions folder. If you don’t know it already, run php -i to find the right folder. For me, the result is,

$ php -i|grep extension_dir
extension_dir => /usr/local/lib/php/20060613-debug => 
/usr/local/lib/php/20060613-debug

so I’ll go ahead and copy the module into /usr/local/lib/php/20060613-debug:

# cp modules/pwwext.so /usr/local/lib/php/20060613-debug/

There’s one last step we’ll have to do. We need to add the module to the list of extensions in your php.ini or extensions.ini file. Locate the section with multiple lines beginning with extension=... and add your own line. For me, this line would do it:

extension=pwwext.so

Step 5: Does it work?

Finally, we can test our new module. Run,

$ php -m

and make sure your new module is in the list.

If all is well you should be able to use your new function from any PHP script. For me, this was the final result:

$php -r'echo pwwext_calculate(1, 2);'
3
$ php -r'echo pwwext_calculate(-1, 2);'

Fatal error: Uncaught exception 'Exception' with 
message 'First argument can't be negative.' in 
Command line code:1
Stack trace:
#0 Command line code(1): pwwext_calculate(-1, 2)
#1 {main}
  thrown in Command line code on line 1

Now you have a bare bones module that does something. All that remains now is to change that one function to do something useful and you’re well on your way.

You’ll undoubtedly need more reference material going forward. Php.net is the logical starting point: The Zend API. If that’s not enough, Sara Golemon wrote a whole book about the subject: ‘Extending and Embedding PHP’.

Good luck, and don’t forget to turn off PHP debugging when you’re done.

]]>
http://www.playingwithwire.com/2007/07/a-condensed-guide-to-extending-php/feed/ 0
Review of The Definitive Guide to symfony http://www.playingwithwire.com/2007/02/review-of-the-definitive-guide-to-symfony/ http://www.playingwithwire.com/2007/02/review-of-the-definitive-guide-to-symfony/#comments Tue, 27 Feb 2007 06:33:44 +0000 http://www.playingwithwire.com/2007/02/review-of-the-definitive-guide-to-symfony/ Picture of The Definitive Guide to symfony.Symfony is a PHP web development framework, similar to Ruby on Rails. The framework is currently gaining in popularity; a few months ago it was announced that it is used by Yahoo! Bookmarks, for instance. Recently, version 1.0 of symfony was released. A print manual, “The Definitive Guide to symfony” by Fran├žois Zaninotto and Fabien Potencier, was prepared in conjunction with this major update of symfony.

As the title suggests, the Definitive Guide to symfony is a guide book. Every chapter explores a certain component or part of symfony, ordered in such a manner that someone who hasn’t touched symfony before can easily get started. The book is not a tutorial; even that the chapters are sensibly ordered, the book does not take the reader through the process of developing an application.

The sections of the guide are,

  1. The Basics: An introduction to symfony, who made it and why, and a primer to the underlying technologies used by symfony including PHP itself. Later chapters in the first part delve into an overview of how symfony works and how to set up an application in the framework.
  2. The Core Architecture: This part of the book is essentially a description of the MVC pattern and how it is employed in symfony. The chapters talk about how the Control, View and Model layers work in symfony.
  3. Special Features: If the previous parts are about the foundation of symfony, the Special Features part of the book is really about the bells and whistles of the framework. The routing system, the form helpers, Ajax, caching and internationalization are described here.
  4. Development Tools: A description of the tools and mechanisms in symfony used during the development tools, just like the name would imply. Generators, unit testing and other important tools are described here. Towards the end there is an oddly placed chapter about extending symfony.
  5. Becoming a symfony Expert: This is a very interesting section which gets into performance optimization for symfony. The authors pool some very valuable practical experience about deploying symfony applications into this part of the book.

The book places almost no requirements on the reader. Obviously you will need to know PHP 5, but apart from that the book carefully introduces almost every concept used in the framework. At the same time I don’t think that a more experienced programmer would find the hand-holding excessive – the 450 or so pages went by quickly when I read the book, and I have worked with symfony before.

The book also features a good selection of sample code and examples. This is in line with the general pragmatic feeling of the book. There is no key concept left without an illustrative code sample. Anyone who has worked with symfony and its developers before will recognize this. The official website is absolutely brimming over with code samples, and Mr. Zaninotto in fact even wrote ‘snipeet’, a code snippet repository. The book is right in line with this demonstrate-by-code philosophy.

The book has some shortcomings. The chapter about Generators feels incomplete for one. Ostensibly the chapter is about the automatic generation of code, called scaffolding, that is a common feature for many modern web development frameworks. This kind of generation makes it faster to develop web applications since it creates a foundation (hence the term scaffolding) for building the web application. But the Generators chapter is really hijacked by the automatic admin generation feature of symfony. While this is a very powerful and impressive feature, the very strong focus on this feature may leave the reader wondering about the ordinary, non admin, scaffolding functionality. For example, it is not at all clear how to customize what generated scaffolding should look like. With such a lengthy description about how to customize the generation of the admin interface, the omission of a corresponding general section is conspicuous.

(For the record, this is how to theme or customize the generated scaffolding:

  1. Copy the default theme from

    $sf_symfony_data_dir/generator/sfPropelCrud/default/theme

    to

    data/generator/sfPropelCrud/default/theme

  2. Edit the files in data/generator/sfPropelCrud/default/theme/templates as you would with an admin template.
  3. Generate like usual: symfony propel-generate-crud <app> <module> <base>.

The generated code will be built to specification.)

Another shortcoming of the book is that there are a few instances of bugs in the provided source code. It might have been useful if the authors had taken a day to test-run their code. For example, in the database section, page 156, the following sample databases.yml listing can be found:


all:
  propel:
    class:                sfPropelDatabase
    param:
[...]
      encoding:           utf-8     # Default charset [...]
[...]

When I tested this code I got an error message: Unknown character set: 'utf'. Turns out that “utf-8″ is not the correct identifier – “utf8″ is correct.

These shortcomings are minor though. A few typos are to be expected, and with so much to cover omissions may accidentally be made. All in all the book is a friendly and pragmatic one. The material is described in a light and fluffy way – there is no ‘academic’ dead weight or terse theoretical descriptions, but rather a hands on description about what symfony programming is like. The book can be used both as a primer and as a reference for a person who is not yet a symfony expert.

If you want to know more about the book, you can actually finds its whole contents online. At the time of this writing, the online edition is available at The Definitive Guide to symfony. This is very generous and a great aid when you want to quickly search for something. Curiously enough Apress, the publisher of the book, has a full page ad for an eBook version in the print edition. They charge $10 for this pleasure, which is a bit odd.

Update 1: The original article credited Mr. Potencier with the Snippeet application. Snippeet was in fact written by Mr. Zaninotto. I apologize for the mistake.
Update 2: Jason Gilmore, the book’s editor, wrote to let us know that Apress sells the $10 ebook as an additional means to support GFDL work. Take a look at the comments section below for the full clarification.

]]>
http://www.playingwithwire.com/2007/02/review-of-the-definitive-guide-to-symfony/feed/ 9