aklump/data

Common interface for interacting with data in objects and arrays.

0.0.28 2017-05-31 01:04 UTC

README

************* ABANDONED *************

Suggested replacement:

// Setter
$setter = (new \Dflydev\DotAccessData\Data($multi_array));
$setter->set('do.re.mi', $value);
$multi_array = $setter->export();

// Getter
print (new \Dflydev\DotAccessData\Data($multi_array))
  ->get('do.re.mi', 'default');

Summary

Provides a common means for getting data from objects or arrays with default option such as Lodash's get method. Other methods for working with array/object data will be added in time.

Rationale

Given a multidimensional array, in vanilla PHP you will do this:

print isset($multi_array['do']['re']) ? $multi_array['do']['re'] : 'default';

Using this class you would do this:

$data = new Data;
print $data->get($multi_array, 'do.re', 'default');

Not too impressive... but wait... imagine when you have complex objects, like say a Drupal 7 field value translated into spanish.

print isset($node->field_description['es']['1']['value']) ? $node->field_description['es']['1']['value'] : '';

// vs...

print $data->get($node, 'field_description.1.value', '');

Or when you need to work in Drupal 8 for a few days.

print isset($node->field_description) ? $node->get('field_description')->get(1)->value : '';

vs.

print $data->get($node, 'field_description.1.value', '');

This is where a consistent interface approach starts to make sense. By the way, there is a Drupal module that uses a different implementation of this class which can be found here.

Default value

Every call to ::get can have a default value, which removes the need for if/thens or issets.

$country = $data->get($record, 'home.address.country', 'U.S.');

Callback

You can pass a callback to process the value such as loading a record by id.

$url = $data->get($record, 'picture.id', 'http://mysite.com/default.jpg', function($id) {
    return load_url_by_record_id($id);
});

Details

<?php
use AKlump\Data\Data;

$data = new Data;

// Let's create a data subject, from which we want to pull data.
$a = array('b' => array('c' => 'd'));

// First let's pull data that exits.
// Because $a['b']['c'] has a value 'd', it will be returned.  Default is ignored.
$value = $data->get($a, 'b.c', 'e');
$value === 'c';

// Because $a['b']['z'] is not set then the default value comes back, 'e'.
$value = $data->get($a, 'b.z', 'e');
$value === 'e';

// This interface works on objects or arrays, regardless.  Let's convert this to a nested object using json functions.
$a_object = json_decode(json_encode($a));

// Make the same call and you'll get the same answer.
$value = $data->get($a, 'b.c', 'e');
$value === 'c';

Data::set()

Unconditionally sets a value at path.

Data::ensure()

Ensures that a path is set, does not overwrite if the key/property exists.

Data::fill()

This is a conditional setter method. It will fill in only if a path is empty (or based on some other test see example 3).

Example 1

<?php
// In this case the value is filled in.
$array = array('do' => '');
$data->fill($array, 'do', 're');

// The value is filled in because the current value is empty.
$array === array('do' => 're');

Example 2

<?php
// In this case the value is NOT.
$array = array('do' => null);
$data->fill($array, 'do', 're', 'strict');

// The old value of null remains because 're' is a string and the current value not a string; even though it's empty, it will not be replaced because we've used the 'strict' test.
$array === array('do' => null); 

Example 3

<?php
// In this case the value is replaced based on a callback.
$array = array('do' => 45);
$data->fill($array, 'do', 're', function ($current, $exists) {
    return $exists && is_numeric($current);
});

// The value is replaced because our custom callable tested it as a number and returned true.
$array === array('do' => 're');

Acknowledgments