Welcome, guest | Sign In | My Account | Store | Cart

In Ruby, the Struct class is a convenient way to create a hash-like object on the fly and use it for your nefarious purposes. PHP 5+ can be convinced to do this type of things as well, it just doesn't have it out of the box. Here is a simple class that implements iterator and allows you to populate the internal data structure similar to how Ruby's Struct works. Syntactic sugar? Probably.

Note: I haven't bothered to implement the Ruby Struct API per se, Instead I just got something similar by implementing the Iterator interface and keeping things very PHP-like.

PHP, 71 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?php

/* A basic data class sort-of based on Ruby Structs */
class Struct implements Iterator {
    
    /* protected array that contains the class properties */
    protected $_data;
    
    /* constructor, takes in data */
    function __construct($mixed=array()) {

        $this->_data = array();

        if (!is_array($mixed) || func_num_args() > 1) {
            $mixed = func_get_args();
        }
        
        if ($this->_isAssoc($mixed)) {
            foreach ($mixed as $prop => $val) {
                if (!is_numeric($prop)) {
                    $this->_data[$prop] = $val;
                }
            }
        }
        else {
            foreach ($mixed as $prop) {
                if (!is_numeric($prop)) {
                    $this->_data[$prop] = FALSE;
                }
            }
        }
    }
    
    /* utility function to decide if an array is associative */
    protected function _isAssoc($var) {
        return is_array($var) && array_diff_key($var, array_keys(array_keys($var)));
    }
    
    /* implementation of __set, just chucks stuff in _data */
    function __set($name, $value) {
        $this->_data[$name] = $value;
    }
    
    /* grabs stuff from _data */
    function __get($name) {
        if (isset($this->_data[$name])) {
            return $this->_data[$name];
        }
        return FALSE;
    }
    
    function rewind() {
        reset($this->_data);
    }
    
    function current() {
        return current($this->_data);
    }
    
    function key() {
        return key($this->_data);
    }
    
    function next() {
        return next($this->_data);
    }
    
    function valid() {
        return ($this->current() !== FALSE);
    }
}

A quick example:

$z = new Struct(array('foo' => 1, 'bar' => TRUE, 'baz' => array(1,2,3)));

// iterating through the data like an array
foreach ($z as $key => $var) {
    echo "$key : $var <br/>\n";
}

// accessing a property directly
echo $z->foo . "<br/>\n";

1 comment

Marius Ghita 13 years, 11 months ago  # | flag

Interesting but I would still stick to plain PHP, an upvote non the less.

$z = array('foo' => 1, 'bar' => true, 'baz' => array(1,2,3));
//accessing values as properties
$y = (object)$z;
echo $y->foo;
Created by Jeff Griffiths on Sun, 28 Mar 2010 (MIT)
PHP recipes (51)
Jeff Griffiths's recipes (3)

Required Modules

  • (none specified)

Other Information and Tasks