Peyman Mohamadpour
Peyman Mohamadpour

Reputation: 17944

php - Make class objects as properties for another class

What I have:

$tom = new Driver;
$bmw = new Car;
$benz = new Car;

What I want to have:

foreach (Car::$all_cars as $car) {
    $tom->setRating($car, $rating); // $rating comes from user input
}

Question:

How to implement this?

Constraints:

What I think:

Class Driver {
    private $cars;

    public function __construct() {
        $his->cars = new \stdClass();
        foreach (Car::$all_cars as $car) {
            $this->cars->$car = NULL;
        }
    }

    public setRating($car, $rating) {
        $this->cars->$car = $rating;
    }
}

Class Car {
    public static $all_cars = array();
    public $name;

    public function __construct($name) {
        $this->name = $name;
        self::$all_cars[] = $this->name;
    }
}

$bmw = new Car('bmw');
$benz = new Car('benz');
$tom = new Driver;
foreach (Car::$all_cars as $car) {
    $tom->setRating($car, $rating); // $rating comes from user input
}

Upvotes: 2

Views: 2307

Answers (1)

Gordon
Gordon

Reputation: 316969

PHP allows you to set properties on any object, e.g.

$tom = new StdClass;
$tom->bmw = 95;

Likewise, you can use variable variables for the property names, as long as the property name is a string, e.g.

$car = 'bmw';
$tom = new StdClass;
$tom->$car = 95;

This will put a public property bmw on $tom, which you can then access with

echo $tom->bmw; // prints 95

You cannot assign an object to a property, because it is not a string, e.g.

$car = new Car;
$tom = new StdClass;
$tom->$car = 95;

cannot work. You have to add a __toString method to the Car object and set the name as a property of the Car:

Class Car 
{
    private $name;
    public function __construct($name) 
    {
        $this->name = $name;
    }
    public function __toString() 
    {
        return $this->name;
    }
}

Because assigning a property name is a string context, PHP will automatically use the Car's name property now when you try to use the Car instance in a string context. There is no sane way to infer the name from the variable name instead, e.g. you cannot do

$bmw = new Car;

and hope to get bmw out of it. The name has to be in the object.

I have provided an example that works with the code you gave at https://3v4l.org/TjC89

Upvotes: 1

Related Questions