0

I have asked this question beforehand, but I might have worded it poorly. I did not get the answer.

I have an Image class that always creates an instance of an Id class when it constructs. Each Image always has an Id, and when Image is destroyed, the Id is destroyed as well. As far as I understand, this is called Object Composition.

My Image class (here: $myImage), during intialization/construction, creates a property: $this->id = new Id(); I want $this->id to be able to access a property of $myImage. Simple example:

class Image {
 public $fileSize;
 public $id;
 const validMimeTypes = array('image/png', 'image/jpeg');
 public function __construct($fileSize = 0.0) {
  $this->fileSize = $fileSize;
  $this->id = new Id();
 }
}

class Id {
 public function echoMe() {
  echo $creatorInstance->fileSize;
  echo creatorClass::validMimeTypes;
  //This is what I'd like to know how to do 
 }
}

$myImage = new Image();
$myImage->id->echoMe();

I would like to know how an Id can access one of its creator's properties. I would like to know if there are differences between accessing class constants and object properties if it turns out to not be obvious.

For example, Id might need the creator object's fileName and fileSize to generate a hash, or it might need its validMimeTypes, which could be a const array describing that class.

I don't mind knowing if this is has better alternatives - in fact, I'm curious - but first of all I'd like to know how to achieve this without passing down arguments during the __construct() stage.

Dwarf Vader
  • 429
  • 1
  • 5
  • 14

1 Answers1

2

First, you shouldn't use public attributes, because it breaks encapsulation. Take a look at the code below. You can pass $this to the target class, and be able to access its methods and attributes:

class A
{
    public function __construct()
    {
        $this->b = new B($this);
    }

    public function func()
    {
        echo "hello, world!";
    }
}

class B
{ 
    private $a;
    public function __construct(A $a)
    {
        $this->a = $a;

        echo $a->func();
    }
}

$a = new A;

It will display hello, world!

So, in your case, just use $this->id = new Id($this); and create a constructor to Id class that will set the Image instance to a class attribute.

Felippe Duarte
  • 14,901
  • 2
  • 25
  • 29
  • Thank you. This seems rather obvious in hindsight, although I was hoping for a cleaner solution instead of passing down the whole object. Still, this is interesting to know. Could you explain something thought? When you construct B, you type `A $a` into the argument. Why is that? Instead of, say, just typing $a, as you are passing the same thing anyway, no? Thanks in advance. – Dwarf Vader Jan 10 '18 at 20:39
  • 1
    Object `Id` need to know the `Image` it belongs. So, you can pass the reference in the constructor like I did, or pass later using a method fot that. The result will be the same, `Id` will have a attribute that references some instance of `Image`. The `A $a` is just to check type, there is no need to use that in your code, it's just to show that `$a` is a instance of `A`. – Felippe Duarte Jan 10 '18 at 20:41
  • So, it's to make sure that what you pass down is of the correct class. It seems to give an error if I try to pass down an instance of a wrong class. Could you give an example of where this would be useful? For example, if I code B to only accept instances of A, I might as well know not to invoke B from anywhere else? I understand the concept of additional integrity, but where would this really be necessary? Thanks – Dwarf Vader Jan 10 '18 at 20:55
  • 1
    Exactly. It's not necessary, but it may be easier for others to understand the code and the composition between these objects, like a self-documented code. – Felippe Duarte Jan 10 '18 at 21:40
  • nice answer. +1 – Tim G Jan 10 '18 at 22:03