F3 Matrix Enhancements

53 views
Skip to first unread message

grrowley

unread,
Dec 3, 2016, 6:20:56 PM12/3/16
to f3-fra...@googlegroups.com
Recently I've been finding myself adding an extra file for some added array manipulation functions, and even more recently I just shoved them in Matrix. I would like to share / propose some additions to the matrix class.


$matrix->force_array($array);
Mostly an edge case function but it's used in the following additions.

function force_array($value)
{
   if ( ! is_array($value)) {
      return array($value);
   }
   return $value;
}

$matrix->resolve($value)
Test if value is a callback or closure

function resolve($value)
{
   return (is_callable($value) && !is_string($value)) ? call_user_func($value) : $value;
}


$matrix->value($array, $key, $default = null);
Get the value of any key in an array or mulit-dimensional array much like $f3->get(), or return default.
eg: $matrix->value($user, 'user.username', 'guest');

function value($array, $key, $default = null) {
   if (is_null($key)) return $array;
   $keys = $this->force_array($key);
   // short-circuit
   if (!is_array($array)) {
      return $this->resolve($default);
   }
      // a flag to remember whether something has been found or not
      $found = false;
      // To retrieve the array item using dot syntax, we'll iterate through
      // each segment in the key and look for that value. If it exists, we
      // will return it, otherwise we will set the depth of the array and
      // look for the next segment.
      foreach ($keys as $key) {
            foreach (explode('.', $key) as $segment) {
                  if (!is_array($array) || !array_key_exists($segment, $array)) {
                        // did we not find something? mark `found` as `false`
                        $found = false;
                        break;
                  }
// we found something, although not sure if this is the last thing,
// mark `found` as `true` and let the outer loop handle it if this
// *is* the last thing in the list
$found = true;
$array = $array[$segment];
            }
            // if `found` is `true`, the inner loop found something worth returning,
            // which means that we're done here
            if ($found) {
break;
            }
      }
      if ($found) {
            // `found` is `true`, we found something, return that
            return $array;
      } else {
            // `found` isn't `true`, return the default
            return $this->resolve($default);
      }
}


$matrix->flatten($array);
Recursivly merge a multi-dimensional array
function flatten($array) {
   $return = array();
   foreach ($array as $key => $value) {
      if (is_array($value)){ $return = array_merge($return, self::flatten_array($value)); }
      else { $return[$key] = $value; }
   }
   return $return;
}


ikkez

unread,
Dec 6, 2016, 4:54:20 AM12/6/16
to Fat-Free Framework
hey grant,

I had a look at it and it seems like the Base can already do the same as your $matrix->value function:


$foo
= ['foo'=>['bar'=>['baz'=>1]]];
$f3
->ref('foo.bar.baz',false,$foo); // 1


though it's currently undocumented, it should do well.
Your flatten function could be an idea.
Reply all
Reply to author
Forward
0 new messages