Viewed   53 times

How do you declare a class property as an object?

I tried:

 public $objectname = new $Object();

But it didn't work. Additionally, why should you do it like that?

Isn't it better to just instantiate that object and just use its members?

 Answers

5

From the PHP manual on class properties (emphasis mine):

Class member variables are called "properties". You may also see them referred to using other terms such as "attributes" or "fields", but for the purposes of this reference we will use "properties". They are defined by using one of the keywords public, protected, or private, followed by a normal variable declaration. This declaration may include an initialization, but this initialization must be a constant value --that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.

Either create it inside the constructor (composition)

class Foo
{
    protected $bar;
    public function __construct()
    {
        $this->bar = new Bar;   
    }
}

or inject it in the constructor (aggregation)

class Foo
{
    protected $bar;
    public function __construct(Bar $bar)
    {
        $this->bar = $bar;   
    }
}

or use setter injection.

class Foo
{
    protected $bar;
    public function setBar(Bar $bar)
    {
        $this->bar = $bar
    }
}

You want to favor aggregation over composition.

Monday, November 14, 2022
1

Why are template strings not allowed as literal object keys?

Template strings are expressions, not literals1. You can only use string literals (and identifiers) for property names, for everything else - that is not known to be static - you need a computed property name.

Is it for performance reasons?

No, that's unlikely. It's to ease parsing, and makes it easy to distinguish constant (statically known) property names from dynamically computed ones.

And mostly, it's a feature that no one needs. It doesn't simplify or shorten anything, and what you would achieve with it is already possible.

Will the syntax be allowed sometime in the future?

Nope.

1: Even when they're called "template literals", technically they aren't literals. And: templates don't even need to be strings, they can evaluate to anything.

Friday, September 30, 2022
 
1

It is not possible to prevent the constructor from being called when the object is constructed (line 9 in your code). If there is some functionality that happens in your __construct() method that you wish to postpone until after construction, you should move it to another method. A good name for that method might be init().

Why not just do this?

class Test {
    public function __construct($param1, $param2, $param3) {
        echo $param1.$param2.$param3;
    }
}

$ob = new Test('p1', 'p2', 'p3');

EDIT: I just thought of a hacky way you could prevent a constructor from being called (sort of). You could subclass Test and override the constructor with an empty, do-nothing constructor.

class SubTest extends Test {
    public function __construct() {
        // don't call parent::__construct()
    }

    public function init($param1, $param2, $param3) {
        parent::__construct($param1, $param2, $param3);
    }
}

$ob = new SubTest();
$ob->init('p1', 'p2', 'p3');

This is might make sense if you're dealing with some code that you cannot change for some reason and need to work around some annoying behavior of a poorly written constructor.

Saturday, September 10, 2022
 
2

In the constructor, yes.

class User
{
    public $x = "";
    public $y = null;
    public $w = array();

    public function __construct()
    {
        $this->y = new ErrorVO();
    }
}

Edit

KingCrunch made a good point: You should not hard-code your dependencies. You should inject them to your objects (Inversion of Control (IoC)).

class User
{
    public $x = "";
    public $y = null;
    public $w = array();

    public function __construct(ErrorVO $y)
    {
        $this->y = $y;
    }
}

new User(new ErrorVD());
Monday, October 17, 2022
 
4

You may use Factory Pattern. Basket, Billing and Delivery objects should be created by the 3rd-party service API wrapper class:

$svc = new The3rdPartyServiceApiWrapper();
$svc->init();  // connect, get session etc.
if ($svc->fail()) die("halp! error here!");

$basket = $svc->createBasket();
$baskSumm = $basket->getBasketSummary();

$billing = $svc->createBilling();
$billSumm = $billing->getBillingSummary();

$delivery = $svc->createDelivery();
$delSumm = $delivery->getDeliverySummary();

The best way to connect Basket, Billing and Delivery class with the API is storing a reference to the API class, then they can call any method of it, not just getSession().

Another advantage is, that if you have an identified entity, e.g. a User, then the wrapper class can grant you, that there will be no double objects in the scene.

If the main program creates the users, there should be different objects with the same user, which is wrong:

$user1 = new User("fred12");
$user2 = new User("fred12");

VS if the API wrapper creates them, the wrapper class should keep a "cache" of users, and return with the same User object for the same request:

$user1 = $svc->createUser("fred12");
$user2 = $svc->createUser("fred12");  // $user2 will be the same object

(Maybe it's not a best example, if a program creates twice the same User, it means that the program has major design faulty.)

UPDATE: explanation of svc class

The The3rdPartyServiceApiWrapper should look like this:

 function getSessionId() {
   return $this->sessionId;  // initialized by constructor
 } // getSessionId()

 function createBasket() {
   $basket = new Basket($this);
   return $basket;
 } // createBasket()

The Basket:

 function Basket($s) {  // constructor of Basket class

   $this->svc = $s;

   //... the rest part of constructor

 } // Basket() constructor

function doSomethingUseful() {

  // if you wanna use the session:
  $sess = $this->svc->getSessionId();
  echo("doing useful with session $session");

  // you may access other api functions, I don't know what functions they provide
  $this->svc->closeSession();

} // doSomethingUseful()
Tuesday, October 18, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :