PHP on Cowboy Web Server – Give It a Shot

In previous post, I gave some background to making PHP run on Cowboy web server. In this post, I’m going to provide technical details how to run your own setup. But it’s really not complicated at all. So, let’s install, run and play with unix1/cowboy_fcgi.

Prerequisites

  • Erlang (19.0 or newer) installed
    • on Linux use your distro’s package manager or download binary from Erlang Solutions
    • on MacOS run brew install erlang
  • GNU make and git in your path
  • php-fpm is in your path
    • on Linux it might be in /usr/sbin/php-fpm

Steps

$ git clone https://github.com/unix1/cowboy_fcgi.git

$ cd cowboy_fcgi/examples/cowboy_php_hello

$ make run

Enjoy

With your browser go to http://localhost:33080/hello.php – you should see the output from the hello.php script.

Modify or add more PHP files

Your currently running application release is located in _rel/cowboy_php_hello_release/lib/cowboy_php_hello-0.1.0/priv/www relative to your current working directory. In that directory you’ll find the hello.php file that produced the output to the browser. You can modify that file, or add more files in that directory.

Change php-fpm configuration

The example includes a php-fpm.conf file in priv/conf/php-fpm.conf. When starting the application, it starts php-fpm with that configuration file. You can modify it prior to building and running the application. For example, try increasing max_children setting from 5 to some other number.

What happened behind the scenes

When make run executed, the following happened:

  • dependencies were fetched
  • Erlang project was compiled and release made
  • released application was started, which, in turn
  • started the php-fpm

Given this, to fully stop both the Erlang application and php-fpm, you could either:

  • hit Ctrl-C twice in Erlang application prompt and manually kill all php-fpm processes; OR
  • type application:stop(cowboy_php_hello). and press enter in the Erlang prompt and then exit out of it

Try more things

Run your own php-fpm

For the sake of simplicity, this example by default started the php-fpm processes for you. But maybe typically you wouldn’t want to do that – instead, you might want to start php-fpm separately as a service. You can do this, and then in src/cowboy_php_hello_app.erl replace this line

cowboy_php_hello:start_with_phpfpm(33080, 33000),

with

cowboy_php_hello:start(33080, 33000),

And replace 33000 with whatever port you ran your php-fpm service on.

Add your own Cowboy handlers

One of the exciting parts of this setup is that you can host both PHP and Erlang applications under one web server. The example project only includes one Cowboy dispatch rule that routes all incoming HTTP requests to the cowboy_fcgi handler. However, this doesn’t need to be the case. You can add your own routing rules to route specific requests to specific handlers, allowing you to have mixed Erlang and PHP environment for your web applications!

Feedback

Try it out, play around with it, and give me feedback. I’d love to hear about use cases, issues, or other thoughts.

PHP on Cowboy Web Server – The Update

Background

Cowboy is an awesome web server – it’s simple, small, fast, standards compliant, and highly scalable. It also provides easy ways to get started with RESTful web applications. Its downside is that, unlike with Apache, nginx, and other more mainstream servers, it’s only usable in Erlang (and related BEAM languages) environments.

There used to be a couple of projects long time ago (2011!) that added FCGI handler module for Cowboy version 0.4, but they were never really maintained beyond the initial release. They quickly became incompatible with rapid development of Cowboy.

Current work

Now that the modern version of Cowboy is 2.0 (as of this writing), I decided took take a stab at updating those 2 projects to work with it. And here’s the result:

https://github.com/unix1/cowboy_fcgi

There are enough quick start steps and examples in that repo to get most developers experimenting. Regardless, in the next post, I’ll go deeper into how one can play around with this setup in greater detail.

The functional if

The if statement is a low level flow construct in most imperative programming languages. It is traditionally used to do things like this:

if (some condition is true) {
    execute branch 1 of code
} else {
    execute branch 2 of code
}

where different branches of code represent different execution paths your program could take. It is basically a specific conditional case of a GOTO statement – if some condition holds go to this line; otherwise, go to that line. The common objectives of those branches are:

  • execute code with different side effects
  • assign different values to existing or new variables

I’m going to show how in these common cases you can write more expressive, less error prone code that to certain degree resembles the functional style. The examples will be in PHP, although other languages that support anonymous functions would probably allow similar technique as well.

Let’s look at the difference between procedural vs the functional if.

The procedural style:

$a = 20;
$b = 10;
if ($my_condition) {
    $x = $a + $b;
} else {
    $x = $a - $b;
}

Equivalent functional style, using the ternary operator – http://php.net/manual/en/language.operators.comparison.php:

$x = $my_condition ? $a + $b : $a - $b;

Notice that the right hand side of this line is an expression, not a statement. It always returns a value and, consequently, the $x will always have a value assigned as a result. While in the procedural style, we have to explicitly set it in each branch.

This is important because in procedural style:

  • logic is more error prone, we may forget to assign correct value to $x during certain execution path and not notice
  • programmer is tempted to set other variables in some or all of these exection paths that are used outside of the if block logic
  • more generally, statements execute in current lexical scope, which encourages logic with implicit dependencies on its context

These are all bad things that lead to (1) bugs during runtime, (2) bad code that can’t be easily read, understood and modified.

So, to avoid this, we could do something like this instead:

if ($my_condition) {
    $x = my_func_1($a, $b);
} else {
    $x = my_func_2($a, $b);
}

function my_func_1($a, $b) {
    return $a + $b;
}

function my_func_2($a, $b) {
    return $a - $b;
}

This is better, but a few disadvantages of doing this are:

  • it still suffers from multiple assignment issue
  • it potentially pollutes the current (which may be global) namespace with functions that may not be reusable and makes the code too verbose
  • the if statement doesn’t enforce this pattern, it must be explicitly used everywhere
  • it encourages programmer to create a single myfunc($a, $b) and move the procedural if logic there instead

Ideally, we’d have a way to:

  • be able to create local variables that don’t affect context
  • provide proper isolation for the logic
  • provide pattern that we can re-use in other places

Basically, we would want a flexible, multi-line ternary operator, or “the functional if.”

In functional programming languages, this is the only way. For example, in Erlang I can say:

X = if my_condition() -> A + B; true -> A - B end.

In fact, if I try to assign (or more precisely, pattern match) the X variable inside the if blocks, I’ll get a compiler warning.

In Lisp:

(setf X (if (my-condition) (+ a b) (- a b)))

But most imperative and procedural programming languages do not provide such features. So how close can we get to this in PHP? Let’s try this syntax:

$x = X::if(
    $my_condition,
    function($a, $b) { return $a + $b; },
    [$a, $b],
    function($a, $b) { return $a - $b; },
    [$a, $b]
);

Here we call X::if() static function that takes 5 arguments:

  • condition that evaluates to true or false
  • anonymous function to execute and return its result if the condition is true
  • array of arguments to pass to true anonymous function
  • anonymous function to execute and return its result if the condition is false
  • array of arguments to pass to false anonymous function

So, how would the X::if() look like? It’s actually pretty simple 3 lines of code:

class X
{
    /**
     * Depending on the condition, executes corresponding function with arguments.
     *
     * @param bool $condition Condition that evaluates to true or false
     * @param callable $true Callable that gets executed if $condition is true
     * @param array $true_args Arguments that get passed to $true callable
     * @param callable $false Callable that gets executed if $condition is false
     * @param array $false_args Arguments that get passed to $false callable
     *
     * @return mixed result of either $true or $false callable execution
     */
    public static function if(
        $condition,
        callable $true,
        array $true_args,
        callable $false,
        array $false_args
    ) {
        $fun = $my_condition ? $true : $false;
        $args = $my_condition ? $true_args : $false_args;
        return call_user_func_array($fun, $args);
    }
}

Now if you can convince your team to get behind this pattern and somehow avoid the WTF moment every time someone looks at it, you might even avoid few bugs and hopefully make your code more readable and easier to modify and reason about.

PHP Sessions in Erlang Mnesia

Motivation

  • create a very simple first Erlang/OTP application
  • link to conventional web development

I decided one of the simplest things to do would be to create a session storage for PHP in Mnesia. But that, in doing so, I would also create an extremely simple key value store wrapper around Mnesia which would track access times.

Disclaimer

Do NOT use this in production, or anywhere where it’s important. If you do, you’re crazy because:

  • it has not been tested in production or production-like environment
  • as I mentioned, this is my first Erlang application
  • connection is made to a single Erlang node, and there is no failover mechanism if that fails
  • session garbage collection is not implemented

Good Stuff

OK, the disclaimer is out of the way, let’s get to the good stuff! Here’s what I did and how.

Tools used

  • Erlang runtime and development headers
  • PHP >=5.3 (>=5.4 preferred) binary and development headers
  • Apache
  • mypeb
  • kvstore
  • lib360

Architecture

[ PHP ] <–> [ mypeb ] <–> [ Erlang ] <–> [ kvstore ] <–> [ Mnesia ]

Instructions

  • download and install prerequisites as best done in your environment
    • Erlang runtime and development headers
    • Apache
    • PHP >=5.3 binary and development headers
  • download and compile mypeb
    • git clone git://github.com/videlalvaro/mypeb.git
    • cd mypeb
    • phpize
    • ./configure
    • make
    • sudo make install
    • php -m | grep peb
    • Note 1: the last command is a test to verify peb module loads successfully
    • Note 2: you might need to specify --with-erllib and --with-erlinc options with ./configure command if they are not automatically found
  • download, compile and run kvstore
  • download lib360
    • git clone git@github.com:unix1/spoof.git
  • add sample PHP script to your web server and test everything
    • download sample gist
    • replace the path in require_once() to wherever you downloaded lib360
    • replace the your-erlang-cookie-here with the contents of ~/.erlang.cookie file
    • access the file through the web server and have fun!

Missing

These are things that I thought of but didn’t bother implementing that I might someday add:

  • make kvstore more configurable and easy to install/start/stop
    • kvstore currently fails to stop (you have to abort)
    • it could use rebar and more automated scripts instead of manual commands
    • support for configurable multiple table names
    • make access time tracking optional
    • implement other storage backends
  • account for failover when primary node connection fails from PHP
  • PHP session garbage collection
  • implement kvstore access through lib360 database layer

Suggestions/Contributions/Feedback

If you have any feedback, feel free to give it via github, blog comments, etc. as appropriate. Enjoy!

Simple PHP Object Oriented Framework

This marks the initial release of Simple PHP Object Oriented Framework – spoof on codefly.org. Well, I intend for this to be a framework, but I’m starting with the extensible core – the main class library. To that end, the first crack is at:

  • autoload
  • data access components

Autoload is a simple implementation for spl_autoload_register:

  • one class per file
  • \namespace1\subnamespace\MyClass automatically turns into [root_dir]/namespace1/subnamespace/MyClass.php
  • you never have to use require_once again

Database components are a more significant undertaking, as they are designed to be language, connection and execution agnostic.

Finally, currently both PHP 5.2 and 5.3+ are supported. However, I am making a full use of PHP 5.3 namespaces which are not backward compatible. I would expect to continue work on 5.3+ version only.

Please check it out and feedback is more than welcome.

PHP array_merge vs plus union Operator

The purpose of this post is simple: I’ve seen way too many uses of array_merge function with associative arrays in PHP. In most cases the “+” union operator should have been used and here’s why. Given:

<?php
$a1 = array('abcd' => 'value 1');
$a2 = array(1234 => 'value 2');

var_export(array_merge($a1, $a2));
var_export($a1 + $a2);
?>

The result is as follows:

array (
  'abcd' => 'value 1',
  0 => 'value 2',
)
array (
  'abcd' => 'value 1',
  1234 => 'value 2',
)

I bet the latter is what you would need most of the time. Let’s list the behavior of the two methods:

  • non-matching string keys: simplest case – both methods append all elements and produce merged result
  • matching string keys: array_merge overrides from latter array; union operator keeps element from the former
  • non-matching integer keys: array_merge re-keys latter array(s) as integer keys are available, starting from 0; union operator leaves original keys
  • matching integer keys: array_merge re-keys and appends; union operator keeps element from the former array

Also consider the following:

<?php

$key = "1234";
$a = array();

$a[$key] = "abc";
$a["$key"] = "abc";
$a["" . $key] = "abc";
$a[(string)$key] = "abc";

?>

All of the above will result in an integer key! PHP will force anything that looks like an integer into an integer even if you explicitly specify a string. From PHP array documentation:

If a key is the standard representation of an integer, it will be interpreted as such (i.e. “8” will be interpreted as 8, while “08” will be interpreted as “08”).

This means all integer rules will apply when using these elements with array_merge – i.e. all of them will be re-keyed. Conclusion: if you are using associative arrays, you most likely need the “+” union operator to merge arrays and not the array_merge function. Just be mindful of the order in which they are added.

Generate Random Characters in PHP

I searched and looked for this but didn’t find a good solution online: I need to come up with a random alphanumeric string of arbitrary length fast and using least memory. How do you do this in PHP? Most solutions I saw posted would define a set of allowed characters, then iterate arbitrary number of times generating a random number each time that would be mapped to one of the characters. Append to result string every time and you get the result.

That method, even when done efficiently, is very expensive because:

  1. You have to generate a different random number with each iteration
  2. Use a run-time interpreted loop
  3. Map to character
  4. Append to string with every iteration

Then I thought of this:

base_convert(mt_rand(1,pow(36,5)), 10, 36);

What does it do?

Step 1: generates a random number between 1 and 36^5. Why 36^5? Because 36 is 26+10: 26 is for letters a-z, and 10 for numbers 0-9. base_convert function’s max base is 36. Why 5? Because for this example, I wanted to generate random string of max 5 characters in length.

Step 2: converts the resulting random number from 10-base to 36-base, resulting in a random alphanumeric string. No for-loops required.

Now, let’s take this one step further. What if we always wanted to get a result that’s n characters long? Well, creatively set a minimum for mt_rand like this:

$n = 10;
base_convert(mt_rand(base_convert(pow(10, $n-1), 36, 10), pow(36, $n)), 10, 36);

This will generate 10 character alphanumeric strings. Enjoy!