Javascript-like objects in PHP? - php

It's pretty handy in JS to create objects like this:
test = { foo : { bar : "hello world" }, bar2 : "hello world 2" }
and then use them like:
test.foo.bar
test.bar2
Is there anything like this in PHP without declaring classes?

It's called associative arrays.
Example (note: the indentation is for layout purposes):
$test = array(
'foo' => array(
'bar' => 'hello world'
),
'bar2' => 'hello world 2'
);
$test['foo']['bar'];
$test['bar2'];
This is equivalent to the following Javascript code:
var test = {
'foo': {
'bar': 'hello world',
},
'bar2': 'hello world 2'
};
As an alternative, you can use the pre-declared StdClass.
$test = new StdClass;
$test->foo = new StdClass;
$test->foo->bar = 'hello world';
$test->bar2 = 'hello world 2';
which would be written in JavaScript as:
var test = new Object;
test.foo = new Object;
test.foo.bar = 'hello world';
test.bar2 = 'hello world 2';
(note: new Object is the same as {} in Javascript)

stdClass allows you to create (essentially) typeless objects. For example:
$object = (object) array(
'name' => 'Trevor',
'age' => 42
);
As shown here, the fastest way to create a stdClass object is to cast an associative array. For multiple levels, you just do the same thing again inside like this:
$object = (object) array(
'name' => 'Trevor',
'age' => '42',
'car' => (object) array(
'make' => 'Mini Cooper',
'model' => 'S',
'year' => 2010
)
);
Another method is to convert the associative array to an object afterwards with a recursive function. Here's an example.
function toObject(array $array) {
$array = (object) $array;
foreach ($array as &$value)
if (is_array($value))
$value = toObject($value);
return $array;
}
// usage:
$array = // some big hierarchical associative array...
$array = toObject($array);
This is useful when you're not the one making the associative array.
Unfortunately, even though PHP 5.3 supports anonymous methods, you cannot put an anonymous method into a stdClass (though you can put one into an associative array). But this isn't too bad anyway; if you want functionality in it, you really should create a class instead.

You can use a StdClass object or an ArrayObject which are included in php (though the latter requires that you have SPL installed). Though unless you need to access the values specifically with the -> operator its more efficient to just use an associative array instead.

I think what you are looking for is an Associative Array
$test["foo"]["bar"]
http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=keyed+arrays

The closest thing would be arrays.
$test = array(
'foo' => array('bar' => 'hello world'),
'bar2' => 'hello world 2',
);
echo $test['foo']['bar'];

Technically, no. However if you are creating a data object (ie no methods), you could technically write a JSON string and use
$obj = json_decode($obj_string);
I wouldn't recommend it however. I assume there would be significant speed loss.
EDIT
Though it goes without mentioning, associative arrays should be used for this instead of flat data objects.

The only reason to do that is if you wish to pass data back to a JavaScript function with JSON. In that case, use json_encode on the array. Otherwise, just keep it as an array, as there's not reason to encode it and then decode it just so it looks like JavaScript.

Try this way: https://github.com/ptrofimov/jslikeobject
Author implemented JS-like objects, you can even access properties from functions via $this pointer.
But perhaps it is not so good to use such objects instead of usual ones.

$a = array(
'a'=> 123,
'b'=> 334,
'c'=> 7853
);
echo json_encode($a);
This will be the result: {"a":123,"b":334,"c":7853}

Related

Use array value while declaring an array in PHP

I was wondering...is it possible to use a value from an array which is currently being declared? Something like:
$a = array(
'foo' => 'value',
'bar' => $a['foo']
);
This is only a simple example. It would be pretty useful doing this, since it frees you from doing extra manipulation after the array declaration.
No, you can't, but you can do something like :
$a = array(
'foo' => ($val = 'value'),
'bar' => $val
);
No. $a['foo'] will only be available after the assignment completes entirely.

how to convert multidimensional array to object in php?

i have a multidimensional array:
$image_path = array('sm'=>$sm,'lg'=>$lg,'secondary'=>$sec_image);
witch looks like this:
[_media_path:protected] => Array
(
[main_thumb] => http://example.com/e4150.jpg
[main_large] => http://example.com/e4150.jpg
[secondary] => Array
(
[0] => http://example.com/e4150.jpg
[1] => http://example.com/e4150.jpg
[2] => http://example.com/e9243.jpg
[3] => http://example.com/e9244.jpg
)
)
and i would like to convert it into an object and retain the key names.
Any ideas?
Thanks
edit: $obj = (object)$image_path; doesn't seem to work. i need a different way of looping through the array and creating a object
A quick way to do this is:
$obj = json_decode(json_encode($array));
Explanation
json_encode($array) will convert the entire multi-dimensional array to a JSON string. (php.net/json_encode)
json_decode($string) will convert the JSON string to a stdClass object. If you pass in TRUE as a second argument to json_decode, you'll get an associative array back. (php.net/json_decode)
I don't think the performance here vs recursively going through the array and converting everything is very noticeable, although I'd like to see some benchmarks of this. It works, and it's not going to go away.
The best way would be to manage your data structure as an object from the start if you have the ability:
$a = (object) array( ... ); $a->prop = $value; //and so on
But the quickest way would be the approach supplied by #CharlieS, using json_decode(json_encode($a)).
You could also run the array through a recursive function to accomplish the same. I have not benchmarked this against the json approach but:
function convert_array_to_obj_recursive($a) {
if (is_array($a) ) {
foreach($a as $k => $v) {
if (is_integer($k)) {
// only need this if you want to keep the array indexes separate
// from the object notation: eg. $o->{1}
$a['index'][$k] = convert_array_to_obj_recursive($v);
}
else {
$a[$k] = convert_array_to_obj_recursive($v);
}
}
return (object) $a;
}
// else maintain the type of $a
return $a;
}
Hope that helps.
EDIT: json_encode + json_decode will create an object as desired. But, if the array was numerical or mixed indexes (eg. array('a', 'b', 'foo'=>'bar') ), you will not be able to reference the numerical indexes with object notation (eg. $o->1 or $o[1]). the above function places all the numerical indexes into the 'index' property, which is itself a numerical array. so, you would then be able to do $o->index[1]. This keeps the distinction of a converted array from a created object and leaves the option to merge objects that may have numerical properties.

Are there dictionaries in php?

For example:
$names = {[bob:27, billy:43, sam:76]};
and then be able to reference it like this:
$names[bob]
http://php.net/manual/en/language.types.array.php
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
);
// as of PHP 5.4
$array = [
"foo" => "bar",
"bar" => "foo",
];
?>
Standard arrays can be used that way.
There are no dictionaries in php, but PHP array's can behave similarly to dictionaries in other languages because they have both an index and a key (in contrast to Dictionaries in other languages, which only have keys and no index).
What do I mean by that?
$array = array(
"foo" => "bar",
"bar" => "foo"
);
// as of PHP 5.4
$array = [
"foo" => "bar",
"bar" => "foo",
];
The following line is allowed with the above array in PHP, but there is no way to do an equivalent operation using a dictionary in a language like Python(which has both arrays and dictionaries).
print $array[0]
PHP arrays also give you the ability to print a value by providing the value to the array
print $array["foo"]
Normal array can serve as a dictionary data structure. In general it has multipurpose usage: array, list (vector), hash table, dictionary, collection, stack, queue etc.
$names = [
'bob' => 27,
'billy' => 43,
'sam' => 76,
];
$names['bob'];
And because of wide design it gains no full benefits of specific data structure. You can implement your own dictionary by extending an ArrayObject or you can use SplObjectStorage class which is map (dictionary) implementation allowing objects to be assigned as keys.
Use arrays:
<?php
$arr = [
"key" => "value",
"key2" => "value2"
];
If you intend to use arbitrary objects as keys, you may run into "Illegal offset type". To resolve this you can wrap the key with the call of spl_object_hash function, which takes any object, and returns its unique hash.
One thing to keep in mind, however, is that then the key itself will be the hash, and thus you will not be able to get a list of the objects used to generate those hashes from your dictionary. This may or may not be what you want in the particular implementation.
A quick example:
<?php
class Foo
{
}
$dic = [];
$a = new Foo();
$b = new Foo();
$c = $a;
$dic[spl_object_hash($a)] = 'a';
$dic[spl_object_hash($b)] = 'b';
$dic[spl_object_hash($c)] = 'c';
foreach($dic as $key => $val)
{
echo "{$key} -> {$val}\n";
}
The output i get is:
0000000024e27223000000005bf76e8a -> c
0000000024e27220000000005bf76e8a -> b
Your hashes, and hashes at different executions may be different.

Arrays vs Single vars

I recently faced a design problem with PHP. I noticed that in a function you can pass as parameter an array. I didn't noticed the powerful of this thing first, but now i'm obsessed with arrays.
For example, in my template class i have to pass some variables and some mysqli_results into the template file (like phpbb do). And i was wondering which one of the following possibilities is the best.
# 1
$tpl = new template(array(
'vars' = array('var1' => 'val1', 'var2' => 'val2'),
'loops' = array('loop1' => $result1, 'loop2' => $result2)
));
# 2
$tpl = new template;
$tpl->assignVars(array(
'var1' => 'val1',
'var2' => 'val2'
));
$tpl->assignloops(array(
'loop1' => $result1,
'loop2' => $result2
));
# 3
$tpl = new template;
$tpl->assignVar('var1', 'val1');
$tpl->assignVar('var1', 'val1');
$tpl->assignLoop('loop1', $result1);
$tpl->assignLoop('loop2', $result2);
Or if there is something better. I was even thinking about creating a db class that performs a query as follow:
$result = $db->fastQuery(array(
'select' => 'user-name',
'from' => $table,
'where' => array('user-id' => 123, 'user-image' => 'none'),
'fetch' => true
));
Oh my God, i'm really obsessed.
If it was up to me I would chose #1, I don't like nesting objects and arrays only if it is necessary. by doing so I keep my code simple.
and if you follow your obsession you may end up writing a full ORM.
#4
Allowing both:
function assign($name, $val = null)
{
if (is_array($name)) {
// loop through and assign
} else {
// assign single var
}
}
This is akin to overloading techniques you would see in C++/Java.
You can also allow #1 by just calling assign in the constructor. It is not uncommon in OOP programming to have the constructor allow a shortcut to setting properties that can also be set in other methods.

PHP dump variable as PHP code

I'm looking for a function to dump a multi-dimension array so that the output is valid php code.
Suppose I have the following array:
$person = array();
$person['first'] = 'Joe';
$person['last'] = 'Smith';
$person['siblings'] = array('Jane' => 'sister', 'Dan' => 'brother', 'Paul' => 'brother');
Now I want to dump the $person variable so the the dump string output, if parsed, will be valid php code that redefines the $person variable.
So doing something like:
dump_as_php($person);
Will output:
$person = array(
'first' => 'Joe',
'last' => 'Smith',
'siblings' => array(
'Jane' => 'sister',
'Dan' => 'brother',
'Paul' => 'brother'
)
);
var_export()
var_export() gets structured
information about the given variable.
It is similar to var_dump() with one
exception: the returned representation
is valid PHP code.
serialize and unserialize
This is useful for storing or passing PHP values around without losing their type and structure. In contrast to var_export this will handle circular references as well in case you want to dump large objects graphs.
The output will not be PHP code though.

Categories