Home » Php » PHP equivalent to Ruby symbol

PHP equivalent to Ruby symbol

Posted by: admin July 12, 2020 Leave a comment

Questions:

Does PHP have symbols like Ruby? Or, should I just use strings as the keys in a PHP associative array?

I’m guessing it’s the same answer as that of the question Is there a Python equivalent to Ruby symbols?

How to&Answers:

PHP has definable constants, but that’s not really very useful in this context.

So no. Use strings as keys.

Answer:

If your concern is the overload of using strings as array keys and the fact that the array is copied instead of passed as reference every time, I can suggest you to use stdClass, that is basically an object class that can be modified dynamically, array-like, but it behaves as an object.

Answer:

PHP has nothing like symbols, and even constants work significantly different in PHP than they do in ruby. Array keys must be string or numeric. You can assign a string or number to a constant, and then “use” the constant as the array key. But, constants are static in PHP so this might not be what you want, requires more “boilerplate” code, and the actual array key will still end up being either a string or number (based on the value of the constant).

Answer:

No, PHP does not have anything like this. The most close approximation in PHP would be to use single-quoted strings for your hash keys — just to make sure there would be no “interpolations” in them.

Few examples:

  • $arr[key] — this would work like $arr['key'] in most cases, but has couple of drawbacks:
    a) if there is indeed a defined constant (e.g., define('key', 'rubbish') — you’ll access $arr['rubish']. So, it’s simply unsafe.
    b) it would produce “PHP Notice” messages (unless notices are suppressed)

  • $arr[@key] — just like before, but without notices. In fact, errors suppressing is very bad in terms of maintainability.

  • $arr["key"] — absolutely valid way, unless you have some special symbols inside the double-quoted string. For example: "ab\ntc" != 'ab\ntc', "ab$c" != 'ab$c' and so on. But its a bit paranoid to think of such cases, I believe.

  • $arr['key'] — this is, to my opinion, the closest to Ruby’s arr[:key] as you could get in PHP.

Answer:

Associative arrays are your only option.

http://railsforphp.com/reference/array/array – 2nd header.

Answer:

You can use simple objects to have a similar effect like symbols in ruby. Some database functions have an FETCH_OBJECT option to emulate this effect.

class StoreMe {
    public $A;
    public $B;
    public $C;
    public $D;
}

The main advantage of symbols is the use as hash keys to optimize performance and memory usage. Since PHP uses “Copy on write” for storing variables, strings might be equivalent like symbols in ruby. But PHP uses some type of translation table to get index for an array from an hash key. So every small array has a certain overhead.

Testscript

I wrote this small script to test the memory footprint with PHP.

error_log("Start:  " . memory_get_usage());
$iterations = 10000;

$hash = [];
for ($i=0; $i<$iterations; $i++) {
    $hash[] = [
        "A" => "Test",
        "B" => "Test",
        "C" => "Test",
        "D" => "Test",
    ];
}
error_log("String: " . memory_get_usage());    
$hash = null;
error_log("Reset:  " . memory_get_usage());

$hash = [];
for ($i=0; $i<$iterations; $i++) {
    $hash[] = [
        "Test",
        "Test",
        "Test",
        "Test",
    ];
}
error_log("Raw:    " . memory_get_usage());
$hash = null;
error_log("Reset:  " . memory_get_usage());

$hash = [];
$copy = [
        "Test",
        "Test",
        "Test",
        "Test",
    ];
for ($i=0; $i<$iterations; $i++) {
    $hash[] = $copy;
}
error_log("Copy:   " . memory_get_usage());
$hash = null;
error_log("Reset:  " . memory_get_usage());

$hash = [];
for ($i=0; $i<$iterations; $i++) {
    $store = new StoreMe();
    $store->A = "Test";
    $store->B = "Test";
    $store->C = "Test";
    $store->D = "Test";
    $hash[] = $store;
}
error_log("Object: " . memory_get_usage());
$hash = null;
$store = null;
error_log("Reset:  " . memory_get_usage());

Here are the results with the official Docker images for PHP. The right value is the memory consumption in bytes.

PHP 5.6

Start:  225680
String: 8837400
Reset:  226088
Raw:    8837400
Reset:  226088
Object: 5580488
Reset:  1209264

PHP 7.0

Start:  355400
String: 4643840
Reset:  355400
Raw:    4643840
Reset:  355400
Copy:   884216
Reset:  355776
Object: 2127096
Reset:  478656

PHP 7.1

Start:  355336
String: 883776
Reset:  355336
Raw:    883776
Reset:  355336
Copy:   883776
Reset:  355336
Object: 2126656
Reset:  478216

Conclusion

Objects do need less memory like expected. But PHP 5.6 seems to have problems with garbage collection using objects. The results from PHP 7.1 seem to be some kind of compiler optimization, cause there is no difference on “Copy on write” and creating the arrays.