Editors Note, February 14th 2022: This project is now ABANDONED and no longer supported or updated.

asherwunk/phabstractic now has type detection and comparison using an enumerator generated by Phabstractic/Data/Types/Enumeration.php

Type Detection and Generation Through Enumeration

Although PHP is making strides in strong typing (See SitePoint, and HHVM) and the sparse but useable string and array keywords in multi-order functions, it doesn’t have a very approachable typing system.  This is usually the case with an interpreted language like PHP, for instance, Python and PERL have very similar fluidity in their variable assignment operations.

I wanted to make it easier to determine a variable’s type (string, integer, array, resource) in one fell function call rather than rely on a bunch of calls to is_array(), is_int() say in an if clause.  I also wanted it to handle objects, both standard, and custom, as well as the null value, functions, and closures.  So, I used Data/Types/Enumeration.php to create an enumeration of all the data types (BASIC_XXX).  I instantiate this in the Type.php file itself where I also define the two functions inside another namespace.

The namespaces of the Type.php file are a little different.  I define the Enumeration encapsulated in one namespace (note, in version 3 of enumeration I don’t specify a key-value pair):

Enumeration::createEnumerator('Type', array( 'BASIC_BOOL',
                                      'BASIC_FUNCTION', ),
                               array('namespace' => 'Phabstractic\\Data\\Types' ) );

This creates an enumeration class in the Phabstractic\Data\Types namespace, giving it a fully qualified identifier of Phabstractic\Data\Types\Type.  But then I create two ‘global’ functions (I decided not to use an object/class because Phabstractic/Data/Types/Type was thus taken.  Since I cannot/shouldn’t put custom functionality in the enumeration object, I thought in terms of convenience this worked well.  So the following is set:

namespace Phabstractic\Data\Types\Type
    // Use the above enumerator generator namespace
    use Phabstractic\Data\Types;

    function getValueType($value)
    function stringToType($string)

These functions are in the same file as the enum generation.  So as soon as Data\Types\Type is loaded (the enumeration object) as a side effect these two functions are also defined. I know this isn’t PSR compatible (I don’t think), but in terms of functionality for the rest of the library, it’s a very convenient side-effect.  Auto-loading should work the same though, and I haven’t run into any problems with it in previous programming incarnations.  These functions make use of the enumeration object defined before, for example:

function getValueType( $value )
    // Get all user defined functions
    $functions = get_defined_functions();
    $functions = $functions['user'];
    if ($value === null) {
        return new Types\Type(Types\Type::BASIC_NULL);
    } else if (is_bool($value)) {
        return new Types\Type(Types\Type::BASIC_BOOL);
    } else if (is_int($value)) {
        return new Types\Type(Types\Type::BASIC_INT);
    /* If string is the name of an existing user defined function, supersede
       string comparison and return as function type */
    } else if (is_string($value) && in_array(strtolower($value), $functions)) {
        return new Types\Type(Types\Type::BASIC_FUNCTION);
    } else if (is_string($value)) {
        return new Types\Type(Types\Type::BASIC_STRING);
    } else if (is_array($value)) {
        return new Types\Type(Types\Type::BASIC_ARRAY);
    } else if (is_resource($value)) {
        return new Types\Type(Types\Type::BASIC_RESOURCE);
    /* Closures are of the special class Closure, check this AFTER function type
       but before Object type, lest it be mistaken for a typed object. */
    } else if (is_object($value) && is_a($value, 'Closure')) {
        return new Types\Type(Types\Type::BASIC_CLOSURE);
    // Is this a generic object?
    } else if (is_object($value) && (get_class($value) == 'stdClass')) {
        return new Types\Type(Types\Type::BASIC_OBJECT);
    // Or a typed object?
    } else if (is_object($value) && (get_class($value) != 'stdClass')) {
        return array(new Types\Type(Types\Type::TYPED_OBJECT), $value);
    /* This function returns a new instance of the enumerator value (so it 
       can also include the class name if it is a typed object), if for 
       some reason a variable isn't ANY type, we return false, rather than 
       throw an error, since it's possible that a variable might not fit any
       type (in the future). */
    return false;

As you can see when we poll a variable for its data type, we receive a data type back.  In the case of a custom-defined object, we receive a blanket TYPED_OBJECT in an array along with the original variable for convenience.

NOTE:  These functions use the ability for an enumeration to be instantiated, and returns enum OBJECTS holding the value of their respective types.  Thus, you would access an enum instance value: ->get();  or typecast as (string)  Remember the ability to compare two objects as stated in the header of Enumeration.php.

With this data ‘type’ we would, for instance, be able to perform our own type check.  However, our type check would be entirely dynamic, as opposed to a static typing system where, in short, the variables can’t change their type once they are initialized.

View on GitHub

This is part of the Phabstractic Library.

photo credit: Historic Tour 2016 – Charade via photopin (license)

Asher Wolfstein

Metaverse Resident

About the Author

A metaverse resident, you can find me on Second Life (kadar.talbot) and other online platforms. I write about my digital life, my musings, and my projects as a programmer, webmaster, artist, and game designer. (exist (be wunk) (use rational imagination) (import artist coder maker furry) (conditional (if (eq you asshole) (me (block you))))

View Articles