Reputation: 1783
Im pretty new to OOP PHP, and so I'm trying to learn.
I have a class called "Awesome_Car" that i define like so
class Awesome_Car {
public $attributes;
public $name;
function __construct($name, $atts) {
$this->name = $name;
$this->attributes = $atts;
}
} // end of class
And I instantiate this class x times somewhere in the code:
$car1 = new Awesome_Car('ford', array( 'color'=>'blue', 'seats' => 6 ));
$car2 = new Awesome_Car('bmw', array( 'color'=>'green', 'seats' => 5 ));
Now I would like to make a normal function that allows me to get - and manipulate - a specific instance of that class by name. Something like
function get_specific_car_instance($name) {
//some code that retrives a specific instance by name
//do stuff with instance
//return instance
}
I have seen people storing each instance in a global variable as an array of object, but I've also read that global variables are considered bad practice? And I do find them a bit annoying to work with as well.
What would be a better way of doing this? preferably an OOP approach?
Upvotes: 0
Views: 83
Reputation: 1057
You can create your own repository; a class whose only purpose is to create, track, and recover these cars. That'll allow you to avoid using a global variable. Of course, you'll need a way to access the repository then. You could always make it Static, but then you're basically back to a global in a way.
class CarRepository {
private $cars = array();
public function makeCar( $name, $atts ) {
$this->cars[] = new Awesome_Car($name, $atts);
}
public function findByName($name) {
foreach( $this->cars as $car ) {
if( $car->name == $name ) {
return $car;
}
}
}
}
// you'll need a way to obtain the repository to find cars; but it means you can have different repositories in your code
$repo = new CarRepository;
$repo->makeCar( 'ford', array( 'color'=>'blue', 'seats' => 6 ) );
$repo->findByName( 'ford' );
Or a fully static version:
class CarRepository {
private static $cars = array();
public static function makeCar( $name, $atts ) {
self::$cars[] = new Awesome_Car($name, $atts);
}
public static function findByName($name) {
foreach( self::$cars as $car ) {
if( $car->name == $name ) {
return $car;
}
}
}
}
// you can access this from ANYWHERE, but you can only ever have a single repository
CarRepository::makeCar( 'ford', array( 'color'=>'blue', 'seats' => 6 ) );
CarRepository::findByName( 'ford' );
Upvotes: 0
Reputation: 6946
If you are creating the instances dynamically, then storing them in an array is the generally accepted way. It doesn't have to be global however.
$cars = array();
$cars['ford'] = new Awesome_Car('ford', array( 'color'=>'blue', 'seats' => 6 ));
$cars['bmw'] = new Awesome_Car('bmw', array( 'color'=>'green', 'seats' => 5 ));
$ford = $cars['ford'];
This ofcourse can be abstracted by a function such as:
function get_car(&$cars, $name) {
if (! isset($cars[$name])) {
throw new \InvalidArgumentException('Car not found');
}
return $cars[$name];
}
$ford = get_car($cars, 'ford');
Or with more advanced container classes such as:
// Requires doctrine/common
use Doctrine\Common\Collections\ArrayCollection;
$cars = new ArrayCollection();
$cars->set('ford', new Awesome_Car('ford', array( 'color'=>'blue', 'seats' => 6 )));
$cars->set('bmw', new Awesome_Car('bmw', array( 'color'=>'green', 'seats' => 5 )));
$ford = $cars->get('ford');
How you store them for later use depends quite a bit on how you are dynamically creating them though.
Upvotes: 3