PHP, Meet YAML
-
Just about every PHP application needs some kind of configuration, if only to define the connection to a database. One popular way to store configuration is to use a PHP file itself because it’s convenient and fast for PHP to read. This approach is taken by the Solar PHP Framework and many others.
However, while PHP is convenient for us as developers, it’s often inconvenient for others. For example, we often leave the task of deploying and configuring our applications with system administrators. For those sysadmins without PHP knowledge, it’s easy to become frustrated by a missing quote, parenthesis, or semicolon in a PHP file.
Introducing YAML
Besides PHP itself, the most popular config file formats for PHP applications are INI and XML files. More people understand these formats, but these have problems of their own. The INI format is easy-to-use but not great at representing hierarchical data. XML improves on hierarchical data but is not nearly as easy-to-use as INI.
YAML is a relatively new format that has been pioneered by the Ruby and Rails communities. It blends the best aspects of XML and INI, giving us a format with the flexibility of XML and the ease-of-use of INI.
Here’s what a snippet of YAML looks like:
development: adapter: mysql socket: /tmp/mysql.sock encoding: utf8 database: newsletter_development username: the-username password: the-password
The YAML site has a more complex example showing what’s possible.
All Rails applications use the same
config/database.yml
file to configure the database connection. The snippet above was taken from Chapter 1 in the book, where we developed a simple newsletter application using Rails.Let’s explore Ruby’s built-in YAML support and then look at it from a PHP perspective.
Ruby’s YAML Support
One of the strengths of Rails is that it is built on a foundation of solid Ruby tools. Rails got the ability to read YAML files for free because YAML support is bundled with Ruby. Fire up IRB and try it yourself:
irb> require "yaml" => true irb> h = YAML.load("foo: bar\nbaz: qux") => {"foo"=>"bar", "baz"=>"qux"} irb> h["foo"] => "bar"
Above, we put a YAML document into a string. The
YAML.load
method then parses it into a Ruby hash, which is simple to use.If you have a Rails application handy, such as the newsletter or user group apps from the book, change to the application’s base directory and try this from IRB:
irb> require "yaml" => true irb> h = YAML.load_file("config/database.yml") => {"development"=>{"adapter"=>"mysql", "encoding"=>"utf8" ... } irb> h['development']['database'] => "newsletter_development"
You can see it’s relatively painless for Rails to read the
config/database.yml
file just with the YAML support included with Ruby.PHP and YAML
PHP 5 includes built-in support for reading many different formats including INI, XML, and JSON. Unfortunately, YAML support is not yet bundled with PHP like it is with Ruby.
A few different solutions have appeared to fill this gap. One is pecl/syck, a fast PHP extension that provides bindings to the Syck library written in C.
Perhaps the best at this time is Horde/Yaml. This library is PHP 5 E_STRICT complaint, uses the familiar PEAR coding standards, and is based on Spyc. Horde/Yaml includes a number of bug fixes, cleanup, and will transparently use pecl/syck if it is available.
Now, we’ll do the same exercises from above but with PHP and Horde/Yaml.
Installing Horde/Yaml
The Horde/Yaml library is distributed as a PEAR package, the analog of RubyGems.
To install it, run these commands from your shell. If you’re on a Unix-like machine, you will probably have to add sudo before these commands.
shell> pear channel-discover pear.horde.org shell> pear install horde/yaml
If installation is successful, you should see
install ok
.Using Horde/Yaml
Horde/Yaml, like many newer PHP 5 libraries, does not explicitly use require to load its files. Instead, it uses autoloading. If you’re unfamiliar with this or don’t yet have an autoloader set up, adding something like this to the top of your script will get it working:
function sample_autoloader($class) { require str_replace('_', '/', $class) . '.php'; } spl_autoload_register('sample_autoloader');
With that out of the way, Horde/Yaml is ready to go.
Let’s look at the equivalent of the first Ruby example, where a string containing YAML is loaded into a PHP associative array:
$a = Horde_Yaml::load("foo: bar\nbaz: qux"); var_export($a);
The
Horde_Yaml::load()
method parses YAML into a variable, just like its Ruby counterpart. The output ofvar_export()
is:array ( 'foo' => 'bar', 'baz' => 'qux', )
Horde/Yaml can also read from a file with
loadFile()
or an open stream withloadStream()
.That’s all you need to start reading YAML in PHP.
Notes
Be careful in your PHP applications that sensitive YAML files are not web-accessible. Keep them outside of the document root or use an
.htaccess
file if that’s not an option. If you don’t, your web server will give them to anyone who requests.This article focuses on reading YAML, but both Horde/Yaml and Ruby’s built-in YAML support can dump data structures into YAML. Just pass a hash (associative array) to the
dump()
method of either to get the equivalent YAML string.