Posts Tagged ‘php’

Web-based API platforms

Friday, October 26th, 2012

There is something nice about Google’s App Engine. Deployment to the GA cloud is done through a desktop application, the database schema is mutable and the environment scales to meet any load. The developer deploys the app without the mess of custom built scripts and server administration. The only downside to Google’s product is the choice of programming language. At Spafax, we use PHP almost exclusively for web development. To switch to either Python or Java would be impractical and expensive.

For our needs, I set out to find a platform that could act as a back end to our web and mobile applications. Each utility application would serve mainly as a data store and business logic repository. Potentially, they could emulate the type of service provided by AddThis: limited in scope by providing a very specific function via JavaScript or REST API.

The database model is not expected to grow past 10 models. There would not be a need for complex queries. There is, however, a need for performance as any web-based service naturally suffers from latency of the network.

Out of the needs grew the following check list:

  • Push of a button deployment: we are not a big team
  • NoSQL-style DB for persistent data storage: there will be few joins
  • File hosting: serving static content is a plus
  • Custom domains: this is a must
  • Supports PHP development: our team is uses primarily PHP
  • Production ready: no services in Beta
  • Easy enough for a junior developer: setting up a local environment should be fast and easy

Following is a list of solutions I found that meet at least some of the features above. Each solution is evaluated based on available documentation, not on experience.

AppFog

AppFog is the most mature PHP cloud host. Their free server includes 2GB of memory and 512MB of storage. Prices quickly escalate to $100/month for 4GB of memory and go up from there.

AppFog includes a versatile command line tool. With the command `af`, a programmer can deploy, start and stop an app. She may also check the crash logs, boot additional servers and much more. A full list of features is available at the support section of their site.

Unlike Google’s App Engine, AppFog does not come with a proprietary framework. This is both a blessing and a curse. Though you can use any PHP library or Framework, I was looking for a service with tight integration between the code and the storage mechanism. Otherwise, the ease of development is reduced by having to install a local MySQL instance.

A huge setback is the database MySQL and PostgreSQL are there, so is MongoDB. Though MongoDB is a schema-less solution, recent blog posts have pointed some of its immaturity. The other two database solutions can be made almost schema-less with RedBean, but it would still require configuring a local instance of MySQL.

More at AppFog.com.

PHP Cloud

Next up is Zend’s own PHP cloud. Though it is promising, given the Zend name, the service is in beta and does not consider itself a product environment. Instead, Zend expects you to develop and test on their cloud, then move the code to a production-ready environment.

More at PHPCloud.com

Orchestra IO

At first glance, Orchestra seems like another virtual host provider. It enables easy project initialization and publishing via Git. The free application provides a MySQL database but no storage.

Orchestra is probably the closest to our needs. However, once again, the MySQL database solution is a setback as configuring a MySQL instance for every developer seems like a hassle.

More at Orchestra.io

Microsoft Azure

Microsoft’s Azure service is an unexpected entry in the cloud PHP provider list. Their service offers the standards MS stack of development tool and support for some open source technologies. Specifically, Azure includes PHP with an API to their unstructured storage mechanism called Azure Storage.

Azure offers publishing via Git.

Unfortunately, the Azure Storage emulation environment is limited to Windows 2008 servers and as we are a Mac-only shop, this limits our ability to develop on that platform.

More at windowsazure.com

AppEngine with Quercus

The final contestant is AppEngine. It does not support PHP natively but with the help of Quercus, PHP can be interpreted by the JVM. This way, PHP has access to the full Java library provided by AppEngine.

Though this solution is very appealing, going through another programming language takes something away from the ease of building PHP applications.

More on Quercus

Summary

Though many services now offer easy deployment of PHP applications and dynamic scaling, most fail to make the distribution process invisible. Setting up a local sever and MySQL (or MongoDB) instance is still necessary, so is maintaining MySQL migration scripts. You can sidestep assist with most of the problems using tools such as MAMP or RedBean but, ultimately, no environment will satisfy all of our needs the way AppEngine could in Python.

In a future post, I will discuss the decision I took and the tools I used.

 

 

 

The PHP getter/setter

Monday, March 12th, 2012

Perl has a neat way to define both a getter and a setter in the same class method. The basic definition goes a little like this:

sub color {
  my $shift;
  if (@_) { # are there any more parameters?
    # yes, it's a setter:
    $self->{Color} = shift;
  } else {
    # no, it's a getter:
    $self->{Color};
  }
}

PHP can do something similar with a structure that matches quite cleanly to the code above. The example below is taken from our upcoming stand-alone form library.

public function name() {
    if ( func_num_args() ) {
        $this->_name = func_get_arg( 0 );
        return $this;
    } else {
        return $this->_name;
    }
}

In the example above, passing a value to the method named name() will set the value and return the object (to allow chaining). If the method is called without a parameter, it return the current value of the object’s name.

This structure is preferable to the magic methods __set and __get for its clarity.

PHP array_remove and array_remove_assoc

Thursday, August 25th, 2011

The array_remove and array_remove_assoc PHP functions allow your code to remove an element from an array (or associative array) given the element’s value. See the comments in the code bellow on how to use the two functions.

Download the code

<?php
/**
 * Removes the given value from the given array.
 *
 * Returns either FALSE if the value was not found in the array
 * or the index at which the value was found and removed.
 * 
 * $array = array('a', 'b', 'c', 'd');
 * assert( array_remove( 'b', $array ) == 1 );
 * assert( array( 'a', 'c', 'd' ) == $array );
 * assert( array_remove( 'z', $array ) === false );
 * assert( array( 'a', 'c', 'd' ) == $array );
 *
 * @param mixed $val The value to remove
 * @param array $array The array from which to remove the value
 * @author Dimitry Zolotaryov, http://old.webit.ca
 * @returns FALSE or the index at which the value was found
 */
function array_remove( $val, &$array ) {
    foreach ( $array as $i => $v ) {
        if ( $v == $val ) {
            array_splice( $array, $i, 1 );
            return $i;
        }
    }
    return false;
}
 
/**
 * Removes the given value from the given associative array.
 *
 * Returns either FALSE if the value was not found in the array
 * or the key at which the value was found and removed.
 *
 * $array2 = array( 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4 );
 * assert( array_remove_assoc( 1, $array2 ) == 'a' );
 * assert( array( 'b' => 2, 'c' => 3, 'd' => 4 ) == $array2 );
 * 
 * @param mixed $val The value to remove
 * @param array $array The associative array from which to remove the value
 * @author Dimitry Zolotaryov, http://old.webit.ca
 * @returns FALSE or the index at which the value was found
 */
function array_remove_assoc( $val, &$array ) {
    foreach ( $array as $key => $value ) {
        if ( $value == $val ) {
            unset( $array[ $key ] );
            return $key;
        }
    }
    return false;
}

Download the code

Uploaded Excel mime type

Thursday, November 5th, 2009

I’ve been strugling to find the reason behind a malfunctioning Excel upload feature. The problem was that some times, the file would not have the application/vnd.ms-excel mime type. This was a bit of an issue, it was required for invaliding the type of the file.

By luck, a coworker discovered that the Excel file would return a different mime type if the Excel file was open in Excel when it was uploaded. Under these conditions, the mime type is application/octet-stream. In other words, when uploading an open Excel doc, Internet Explorer would have trouble identifying the file type and send along the generic mime-type application/octet-stream.

Bellow is a quick fix that should take care of future problems:

if (   $_FILES['excel_file']['type'] == 'application/vnd.ms-excel'
    || preg_match('/\\.xls$/', $_FILES['excel_file']['name']) ) {
    // continue working on the uploaded file...
}

PHP isset()

Sunday, September 20th, 2009

The PHP function isset() is often used to determine the presence of a variable. When the variable is not defined, false is returned. Using isset() is also an easy way to determine whether an array has a given key.

$assoc = array('key' => 'value');
echo isset($assoc['key']) ? 'true' : 'false';
// true
echo isset($assoc['missing']) ? 'true' : 'false';
// false

There is a catch: isset() called on a null variable will return false.

$var = null;
echo isset($var) ? 'true' : 'false';
// false
 
$array = array('key' => null);
echo isset($array['key']) ? 'true' : 'false';
// false

For checking the presence of a key in an array, use the PHP function array_key_exists() instead.

echo array_key_exists('key', $array) ? 'true' : 'false';
// true
 
function has_empty($key, &$array) {
    return array_key_exists($key, $array) && !$array[$key];
}
echo has_empty('key', $array) ? 'true' : 'false';
// true

To determine the presence of a null variable, a custom function is required.

function isvar($var) {
    return isset($var) || @is_null($var);
}
$null = null;
echo isvar($null) ? 'true' : 'false';
// true