0635a8e46531193666e660800916ed64

Hi, I am looking for a code review of a function. Any suggestions as to how I can make it more efficient (faster) while maintaining the same functionality would be greatly appreciated. Thanks for taking a look!

<?php

/**
 * Returns the value of an array key after checking to make sure it exists. May
 * also check the value's type, make sure the value is in an array of allowed
 * values and/or make sure the value is not NULL.
 *
 * @param array $array Array that should contain the key to return the value of.
 * @param string|int $key Array key to return the value of.
 * @param array  $options Array of options. Possible keys are:
 *
 *   type (string) - If included, must be 'string', 'numeric' or 'object'. If
 *     array key's value is not specified type, default value or NULL will be
 *     returned.
 *
 *   class_name (string) - If type must be 'object', can also make sure array
 *     key's value is an instance of a specific class. If not, default value or
 *     NULL will be returned.
 *
 *   value_array (array) - Array of values. If included, array key's value must
 *     match one of the values in this array. If not, default value or NULL will
 *     be returned.
 *
 *   value_array_check_type (bool) - If value_array is included, can set this
 *     key to TRUE to enforce type checking when comparing array key's value to
 *     array of allowed values. If value_array is included and
 *     value_array_check_type is not included, types will not be checked when
 *     comparing the array key's value to the array of allowed values.
 *
 *   default (any) - Optional default value to set array key's value to if any
 *     of the checks fail. If not included, default value will be NULL.
 *
 *   allow_null (bool) - Whether or not array key's value may be NULL. If
 *     allow_null is FALSE and array key's value is NULL or ends up being set to
 *     NULL when one of the checks fails, an exception will be thrown.
 *
 * @return any Value of array key or default value if any of the checks fail.
 */
function get_value($array, $key, $options = array())
{
  if ( ! is_array($array))
  {
    throw new Exception('Argument $array must be an array.');
  }

  if (( ! is_string($key)) && ( ! is_int($key)))
  {
    throw new Exception('Argument $key must be a string or an integer.');
  }

  if ( ! is_array($options))
  {
    throw new Exception('Argument $options must be an array.');
  }

  $value_is_valid = TRUE;

  # existence check
  if (( ! isset($array[$key])) && ( ! array_key_exists($key, $array)))
  {
    $value_is_valid = FALSE;
  }

  # type check
  if ($value_is_valid)
  {
    if (isset($options['type']) && (in_array($options['type'], array('string', 'numeric', 'object'))))
    {
      $data_type_check_function = 'is_' . $options['type'];

      if ($data_type_check_function($array[$key]))
      {
        if ($options['type'] === 'object')
        {
          if (isset($options['class_name']) && is_string($options['class_name']))
          {
            if (get_class($array[$key]) !== $options['class_name'])
            {
              $value_is_valid = FALSE;
            }
          }
        }
      }
      else
      {
        $value_is_valid = FALSE;
      }
    }
  }

  # value check
  if ($value_is_valid)
  {
    if (isset($options['value_array']) && is_array($options['value_array']))
    {
      if (( ! isset($options['value_array_check_type'])) || ($options['value_array_check_type'] !== TRUE))
      {
        $options['value_array_check_type'] = FALSE;
      }

      if ( ! in_array($array[$key], $options['value_array'], $options['value_array_check_type']))
      {
        $value_is_valid = FALSE;
      }
    }
  }

  # determine potential return value
  if ($value_is_valid)
  {
    $return_value = $array[$key];
  }
  elseif (isset($options['default']) || array_key_exists('default', $options))
  {
    $return_value = $options['default'];
  }
  else
  {
    $return_value = NULL;
  }

  # determine if null return values are allowed
  if (( ! isset($options['allow_null'])) || ($options['allow_null'] !== TRUE))
  {
    $options['allow_null'] = FALSE;
  }

  # null check
  if (($return_value === NULL) && ( ! $options['allow_null']))
  {
    throw new Exception('Return value was determined to be NULL but NULL return values are not allowed.');
  }

  return $return_value;
}
<?php

$my_array = array();

$my_array['id'] = 1;
$my_array['action'] = 'Delete';

echo get_value($my_array, 'id', array('type' => 'numeric'));
# 1

echo get_value($my_array, 'action', array('type' => 'string', 'value_array' => array('Add', 'Edit', 'View'), 'default' => 'View'));
# View

try
{
  echo get_value($my_array, 'action', array('type' => 'string', 'value_array' => array('Add', 'Edit', 'View')));
}
catch(Exception $e)
{
  echo $e->getMessage();
}
# Return value was determined to be NULL but NULL return values are not allowed.

echo get_value($my_array, 'some_other_key', array('default' => 'Some other value...'));
# Some other value...

try
{
  echo get_value($my_array, 'some_other_key');
}
catch(Exception $e)
{
  echo $e->getMessage();
}
# Return value was determined to be NULL but NULL return values are not allowed.

echo get_value($my_array, 'some_other_key', array('allow_null' => TRUE));
# (NULL)

Refactorings

No refactoring yet !

F9a9ba6663645458aa8630157ed5e71e

Ants

January 8, 2011, January 08, 2011 06:42, permalink

No rating. Login to rate!

The following is untested, but hopefully you get the drift of what the refactoring is trying to do...

<?php
function get_value($array, $key, $options = array())
{
  if ( ! is_array($array))
  {
    throw new Exception('Argument $array must be an array.');
  }

  if (( ! is_string($key)) && ( ! is_int($key)))
  {
    throw new Exception('Argument $key must be a string or an integer.');
  }

  if ( ! is_array($options))
  {
    throw new Exception('Argument $options must be an array.');
  }

  $return_value = NULL;
  if (array_key_exists($key, $array) && isset($array[$key]))
  {
    $return_value = $array[$key];
  }
  elseif (array_key_exists('default', $options))
  {
    $return_value = $options['default'];
  }

  # type check
  if (   $return_value !== NULL
      && isset($options['type'])
      && in_array($options['type'], array('string', 'numeric', 'object')))
  {
    $data_type_check_function = 'is_' . $options['type'];
    if (   ! $data_type_check_function($return_value)
        || (   $options['type'] === 'object'
            && isset($options['class_name']
            && is_string($options['class_name'])
            && get_class($return_value) !== $options['class_name']))
    {
      $return_value = NULL;
    }
  }

  # value check
  if (   $return_value !== NULL
      && isset($options['value_array'])
      && is_array($options['value_array'])
      && ! in_array($return_value, $options['value_array'], $options['value_array_check_type'] === TRUE))
  {
    $return_value = NULL;
  }

  # null check
  if (   $return_value === NULL
      && isset($options['allow_null'])
      && $options['allow_null'] !== TRUE )
  {
    throw new Exception('Return value was determined to be NULL but NULL return values are not allowed.');
  }

  return $return_value;
}

Your refactoring





Format Copy from initial code

or Cancel