1

Lets imagine that we have following:

class Foo
{
    public static $foo;
    public static $bar;
    public static $baz;
    public static $str;
    public static $arr;   
}

class Bar
{
    public static $foo;
    public static $bar;
    public static $baz;
    public static $str;
    public static $arr;
}

class Baz
{
    public static $foo;
    public static $bar;
    public static $baz;
    public static $str;
    public static $arr; 
}
Foo::$foo = new Foo();
Bar::$foo = Foo::$foo;
Baz::$foo = Foo::$foo;

Foo::$bar = new Bar();
Bar::$bar = Foo::$bar;
Baz::$bar = Foo::$bar;

Foo::$baz = new Baz();
Bar::$baz = Foo::$baz;
Baz::$baz = Foo::$baz;

Foo::$str = 'cat';
Bar::$str = Foo::$str;
Baz::$str = Foo::$str;

Foo::$arr = [1, 2, 3, 'dog'];
Bar::$arr = Foo::$arr;
Baz::$arr = Foo::$arr;

WHERE:
Foo::$foo, Bar::$foo, Baz::$foo refer same instance of Foo;
Foo::$bar, Bar::$bar, Baz::$bar refer same instance of Bar;
Foo::$baz, Bar::$baz, Baz::$baz refer same instance of Baz;
Foo::$str, Bar::$str, Baz::$str refer same string;
Foo::$arr, Bar::$arr, Baz::$arr refer same array;

Is there any way to identify these values? For instance in C++ I could just use a pointer, which would contain same value for Foo::$foo, Bar::$foo and Baz::$foo.
What is it for?
I have a function which iterates all properties of a given classes and writes property values into common array.
Lets imagine we are iterating over Foo's, Bar's and Baz's properties and adding them into array. In final array we'll have 15 values instead of 5(really different values). If we'll search and compare these values before adding into array then(if `Foo::$str, Bar::$str and BAZ::$str will be not a refs to same value, but just an equal values) we'll have only 5 values instead of 7(3 objects, 1 array and 3 strings).
I hope this edit will help to understand me.

Also:

$a = 1;  
$b = &$a;
$c = 1;

($a == $b) // true  
($a == $c) // true

In both cases result will be true. But how to know that im comparing 2 references of the same value(2 refs that point same memory address) or im comparing 2 different memory addresses and they they are just equal? It will be helpful for solving this problem.

FiftyStars
  • 298
  • 1
  • 16
  • If my understanding of classes is correct you are calling unrelated properties, also you cannot call properties outside their class like that because they're private. – angelcool.net Aug 07 '15 at 15:28
  • @angelcool.net what do you mean? – FiftyStars Aug 07 '15 at 15:30
  • I dont see any instance methods / properties, so its kind of hard to under what you want to achieve – Steve Aug 07 '15 at 15:31
  • he means that each instance of $foo is a totally new variable, even though they share a name. – frymaster Aug 07 '15 at 15:33
  • 2
    @frymaster there are no instances of $foo, only uninitialized static identifiers, so i have no clue what (s)he wants to acheive – Steve Aug 07 '15 at 15:36
  • My suggestion is to read more about [Object Oriented Programming in PHP](http://php.net/manual/en/language.oop5.php), expecially the [basics](http://php.net/manual/en/language.oop5.basic.php) and the chapter about the [static keyword](http://php.net/manual/en/language.oop5.static.php). –  Aug 07 '15 at 15:38
  • @Steve ive made some edits for you – FiftyStars Aug 07 '15 at 15:40
  • @angelcool.net they are static properties, they are called using `::$`. –  Aug 07 '15 at 15:40
  • 1
    What do you mean *identify these values*? – Jason McCreary Aug 07 '15 at 15:42
  • @JasonMcCreary ive given a C++ example for you. Pointer is a good identifier of any value. I will add some additional info about it in a couple of minutes. – FiftyStars Aug 07 '15 at 15:45
  • @Matteo'Ingannatore'G. But they're private. – angelcool.net Aug 07 '15 at 15:47
  • 2
    @angelcool.net taken from the official PHP [Static Keyword](http://php.net/manual/en/language.oop5.static.php) documentation: "For compatibility with PHP 4, if no visibility declaration is used, then the property or method will be treated as if it was declared as public." –  Aug 07 '15 at 15:49
  • 1
    @Matteo'Ingannatore'G. He had private before editing. – angelcool.net Aug 07 '15 at 15:55
  • @angelcool.net my bad, I saw the question after the first edit (no `private` modifiers). –  Aug 07 '15 at 15:59
  • @Matteo'Ingannatore'G. there were 'private's but ive changed it to 'public's when i added classes initializing(instead of using tons of setters and getters). – FiftyStars Aug 07 '15 at 16:09
  • [this](http://stackoverflow.com/questions/4817562/detecting-whether-a-php-variable-is-a-reference-referenced) might be helpful.. If refcount from debug_zval_dump > 1 then the value shares a reference with other variables. – Orangepill Aug 07 '15 at 16:35
  • @Orangepill thx but no, there can be multiple references for same value(static properties etc) so in theory we dont know the refs count. Also....it outputs the string, which should be parsed after using an output buffer – FiftyStars Aug 07 '15 at 16:54
  • It's messy I admit but afaik it's the only way to get the zval's ref count which is the only way you are going to know if a given scalar or array is referenced by anything else. – Orangepill Aug 07 '15 at 16:59

2 Answers2

0

well, i admit i'm not fully aware of what you're trying to do... but i'll take a stab at it and suggest you want a super class to hold your static $foo, $bar etc. then you can extend from there. here's a truncated example.

<?php

abstract class Super
{
    static $foo;
    static $bar;
}

class Foo extends Super
{
    public function test() {
        print "i am foo\n";
    }

}

class Bar extends Super
{
    public function test() {
        print "i am bar\n";
    }
}

$foo = new Foo();
Bar::$foo = $foo;
Bar::$foo->test(); // "i am foo""
$foo->test(); // "i am foo"
frymaster
  • 664
  • 7
  • 12
0

As I read it, you seem to be trying to identify if a given reference is unique or not.

Objects

In PHP, when you instantiate an object and assign it to a variable (be it a standard variable in scope, or an object/class property) you are assigning a reference, which is a symbol table alias, not a pointer.

You can use strict equality === to determine if values are the same instance of the same type.

So, given a similar example to the one you provided:

class Foo
{
}

class Bar
{
    public static $bar;
}

$foo = new Foo();
Bar::$foo = $foo;

Both $foo and Bar::$foo refer to the instance of Foo that we created. We can prove this with strict equality:

var_dump($foo === Bar::$foo); // bool(true)    

On the other hand, the following:

$foo = new Foo();
Bar::$foo = new Foo();

var_dump($foo === Bar::$foo); // bool(false)

Because the instances being compared are different in this case.

You can also use spl_object_hash() which returns a unique hash id for an object.

Revisiting first example above:

$foo = new Foo();
Bar::$foo = $foo;

var_dump(spl_object_hash($foo));
var_dump(spl_object_hash(Bar::$foo));

Yields:

string(32) "00000000706dad460000000129210cdf"
string(32) "00000000706dad460000000129210cdf"

Both object hashes are identical for each reference; i.e: the same underlying object.

In contrast, the second example where we create two new instances of Foo:

$foo = new Foo();
Bar::$foo = new Foo();

var_dump(spl_object_hash($foo));
var_dump(spl_object_hash(Bar::$foo));

Yields:

string(32) "0000000004e5dfeb0000000107143bbf"
string(32) "0000000004e5dfe80000000107143bbf"

They look almost identical, but if you look closely, they are different values.

Arrays & Strings

These don't work in the same manner. Given the following example:

Foo::$str = 'cat';
Bar::$str = Foo::$str;

Bar::$str = 'dog';

var_dump(Foo::$str, Bar::$str);

Yields:

string(3) "cat"
string(3) "dog"

You can however assign scalar values by reference with &:

Foo::$str = 'cat';
Bar::$str = &Foo::$str;

Bar::$str = 'dog';

This yields:

string(3) "dog"
string(3) "dog"

The same applies to arrays iirc.

Your update suggests that you are iterating over objects in order to maintain an object store, or store of unique references. I'm not sure about your specific use case but SplObjectStorage might be useful to you.

Hope this helps :)

Darragh Enright
  • 13,676
  • 7
  • 41
  • 48
  • i've added it to question but does it work with scalar types? See $a $b $c example in question – FiftyStars Aug 07 '15 at 16:28
  • Hi there, sorry - I realised I forgot that part. Just added more detail on that. – Darragh Enright Aug 07 '15 at 16:30
  • look at this: `Foo::$dog = 'Caesar'` , `Bar::$dog = 'Caesar'` and `Baz::$dog = Bar::$dog`. Simple real life example: mr. Foo has his own dog named 'Caesar'. Mr. Foo's neighbors - a family...Mr.Bar and Mrs. Baz. They have a dog named 'Caesar' too. So how can i know that im comparing dog with itself when im comparing Mr. Bar's dog with Mrs. Baz's dog? – FiftyStars Aug 07 '15 at 16:45
  • IMHO, In the example you gave, I think you would be better to create a `Dog` object if you want to check for strict equality, deciding if a specific reference is the same `Dog` or just another `Dog` with the same name property. – Darragh Enright Aug 07 '15 at 17:03
  • You can compare if strings are the same, but afaik scalar comparison is different. Strict equality does not check if two scalars are the same instance, instead it checks if the compared values are the same and of the same type, which is different. You pass around references to a string as shown above - but it's not quite the same really, it seems less semantic to me given your example, and it's less transparent. – Darragh Enright Aug 07 '15 at 17:05
  • its just a basic example. Actually it can be any value like name, address etc. So in this case i need to know is this value shared with someone else or its just an equal values – FiftyStars Aug 07 '15 at 17:08
  • yeah. As i said it can be achived so ez in cpp but here...its too complicated... if possible at all... – FiftyStars Aug 07 '15 at 17:12