I started reading some tutorials about OOP, because I want to learn the basics.
I have a question about it. I understand how you can have a object “Car” and give it a color like this $oCar->setColor(“white”);
But there are some things unclear to me. Let’s say I have a database with all kinds of cars. What is the best way to create the object “car”? A SQL-query instead the class?
And the other question is: how can I output a list of all cars? Do I need to create a object called “Garage” with has only one method within that selects all the cars from the database? Or does this kind of method belong in the “Car” object?
1
Let’s say I have a database with all kinds of cars.
Yes, let’s say you have that database in the memory of your computer (in-memory-database) and let’s say that the interface to it are variables in PHP.
What is the best way to create the object “car”? A SQL-query instead the class?
Obviously an SQL query makes no sense here. First of all in PHP there is only one (and a half) way to create the object car and I’m sure you know that already:
new car;
Second SQL does not understand PHP directly. So using an SQL query would not make any sense.
Object orientation requires you to separate things. For example the object itself should not care about how (and when) it is stored into the memory, on disk, into an SQL database or printed out on paper to be typed in later again. If the car object would need to take care about all this, it would less be a car object but more the super-store-exchange-object called “car”.
So just take care that one class is responsible for what it is good with:
- Single responsibility principle
And create new objects with new. You can find many hints how to make your code more simple and still improving it when writing OOP code in the post Don’t be STUPID: GRASP SOLID! (Dec 2011; by NikiC).
2
when you iterate your sql records in loop you can create objects then and put it for example to array
$array = array();
$sql = 'select yourFunction(params...)';
$db = new PDO('pgsql:dbname=yourDBname');
$cmd = $db->prepare($sql);
while ($row = $cmd->fetch(PDO::FETCH_ASSOC))
{
$car = new Car();
$car->setColor($row['color']);
array_push($array, $car);
}
you can also fetch object as STD object( stdClass is php’s generic empty clas). In PDO you can fetch object also to class using
$stmt->setFetchMode(PDO::FETCH_CLASS, 'MyRow');
PDO::FETCH_CLASS: returns a new instance of the requested class, mapping the columns of the result set to named properties in the class. If fetch_style includes > PDO::FETCH_CLASSTYPE (e.g. PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE) then the name of the class is determined from a value of the first column.
http://php.net/manual/en/pdostatement.fetch.php
There is also one technology called ORM for mapping sql.
https://stackoverflow.com/questions/108699/good-php-orm-library
4
But there are some things unclear to me. Let’s say I have a database with all kinds of cars. What is the best way to create the object “car”? A SQL-query instead the class?
SQL queries and classes are two completely independent concepts and they are not interchangeable.
You can’t create objects out of SQL queries, but you can use an SQL query to retrieve the values for the properties of an object. There are two ways to go about this:
- The class knows about the database and retrieves the values itself when you create a new object.
- The class does not know about the database and relies on external code to provide the relevant values. These can come from a database or from elsewhere.
If you code it all yourself, the second way is easier, because you can split it up in more functions, which makes it easier to understand what each function does.
There are also lots of frameworks available that provide an ORM (Object Relational Model) component which does most of the hard work for you. There it depends on the framework architecture if the ORM component is based on the first or the second way.
And the other question is: how can I output a list of all cars? Do I need to create a object called “Garage” with has only one method within that selects all the cars from the database? Or does this kind of method belong in the “Car” object?
Although some ORM implementations do provide such methods as part of the “Car” class, they do not really belong there.
On the other hand, creating a “Garage” class just to provide a list of cars would also be overkill.
The pragmatic way is to have a method in the class that handles the database interaction for “Car” to retrieve a list of cars and if that happens to be “Car” itself, the so be it. IMO, it is more important to have all the code that deals with retrieving cars from the database close together than the purity of the solution. This method returns the cars as a list, array, hash or whatever collection type your language provides you.
the practical part of object oriented comes not so much from “Getting” things (like from a database). its when you are Changing things in a sequence over time. so for example – lets say you have an app where someone can call up a model of car – and then they can change the color, view, change the color again, view.
- they request a car model, you get it from database as an object $carModel with a default color.
- they request to see the color Red – you take that “instance” of $carModel, and run it through the changeBodyColor() method to change it to Red, then you pass the updated $carModel to your view and display it.
so obviously this could be a lot more complicated – different doors, tires, interior etc. but its all happening to the same object. AND that object is unique to the requester! here is where it gets amazing — with the same class code — you can have many simultaneous users — each one will have a $carModel object — AND that object is unique to them!!
thats why sometimes you will hear classes referred to as ‘blueprints’. with one set of blueprints you can make 50 houses. but even though they came from the exact same ‘blueprint’ (class), each house (object) is unique.
You still need to understand what the Object is and what does it represent.
What is the best way to create the object “car”? A SQL-query instead the class?
- Firstly, an SQL query doesn’t help you to create objects, you can use
its output to create objects. - OBJECTS RESIDE IN MEMORY. You must be aware that what represent the
Objects are their STATES. Now what are the states ? It’s nothing but
the values that object is having.
Say for example
Car Object –> name=’bmw’, color=’black’ // values of the both the
variable is state of car object.
I think you are clear enough about the objects now.
So think of your problem again.
You need to access list of cars. But the data that represents the cars is in the database.
ONE DB ROW = CAN CREATE ONE CAR OBJECT.
- How we will create objects from the database output ? Simple. Fire
query against the database, get the output and CONSTRUCT OBJECTS from
that data.
Now about LIST of the CARS. As you are having all your objects in the memory you can create list which will include all the objects in it. Again this list is also an object and its state is its values.
Hope this clears your understanding of Objects.
there are many ways to do this, one i did was:
- create a table
- create a class with the same name
- create in both the same attributes/column names
- create a mapper or a parent class for your car class and create functions to load in all objects. (with static class)
- create a standard getters and setters or use magic __call method
so you can do Car::Find() for example, to return al cars.
my code:
//Code for parent class:
abstract class databaseObject {
public static function getClassName(){
return get_called_class();
}
public static function find(){
mysql_query("SELECT * FROM ".static::getClassName().";");
$cars = array();
while($row = mysql_fetch_assoc())
{
$car = new Car();
$car->setAttributes($row);
$cars[] = $car;
}
return $cars;
}
public function setAttributes(array $values) {
foreach ($values as $attribute => $value) {
if ($this->{$attribute . 'Exists'}()) {
$this->{'set' . ucfirst($attribute)}($value);
}
}
return $this;
}
//this function gets called when a function of an object gets called which does not exist
public function __call($name, array $args) {
// get attribute
if (0 === strpos($name, 'get')) {
$property = lcfirst(substr($name, 3));
if (property_exists($this, $property)) {
return $this->$property;
} else {
return new Exception("Attribuate $property does not exist");
}
} elseif (0 === strpos($name, 'set')) {
$property = lcfirst(substr($name, 3));
if (property_exists($this, $property)) {
$this->$property = $args[0];
return $this;
} else {
throw new Exception("Cannot set attribute '{$property}', it does not exist");
}
}
return new Exception("Method $name does not exist");
}
}
class Car extends databaseObject {
protected $color;
}
offcourse you will probably want an already created database abstraction layer something like ORM/Doctrine
2