PHP's visibility applies at the class level, not instance level. We better use an example to explain this:
public function __construct($msg)
$this->msg = $msg;
class MessageService extends Message
public function __construct(Message $message)
$this->message = $message;
public function printMessage()
$m = new Message('hello world');
$service = new MessageService($m);
$service->printMessage() looks like it should not be able to work because it is trying to access another instance's protected property. But, surprisingly, it works. This is because PHP's visibility applies at class level instead of instance level. So, as long as MessageService extends Message, an instance of MessageService class would be able to access the protected properties of the instance of Message class.
If we break the inheritance between MessageService and Message, simply do:
Then the code will not work properly and we will get "Fatal error: Cannot access protected property Message::$msg"