Object oriented program is the only way to program as far as I’m concerned and a language as flexible as PHP let’s us do some really cool things. One of those things is created dynamic class members. This is made possible by PHP’s flexible use of key value arrays. Don’t know what I mean by dynamic classes? Let us proceed to some examples.
Let’s say that you are making a movie database, so you decide to make a Movie class to handle creating/saving/updating/etc of your movies that you enter through a form. Well, one thing you could do is this:
Class Movie{
var $name;
var $director;
var $rating;
//constructor
function Movie($mName, $mDirector, $mRating)
{
$this->name = $mName;
$this->mDirector = $mDirector;
$this->mRating = $mRating;
}
}
That’s definitely a viable option. You have all your members defined, you have a constructor that takes each value and stores it. You will definitely be able to create a Movie through that. However, let’s say you decide to add in another thing to movie database, like ‘genre’. Now you have to add another variable, pass another thing into the constructor and store it in the constructor. That’s three extra lines to add one thing. To be fair, you could just pass in an array to the constructor like this:
//constructor
function Movie($mData)
{
if (isset($mData['name'])) $this->name = $mData['name'];
if (isset($mData['director'])) $this->director = $mData['director'];
if (isset($mData['rating'])) $this->rating = $mData['rating'];
if (isset($mData['genre'])) $this->genre = $mData['genre'];
}
Now you don’t have to add something to the constructor’s parameters everytime, but you do have to add an extra line inside the constructor everytime. And technically you don’t have to add an ‘isset’ everytime, but if you don’t your asking for errors if you forget to pass something or you are letting users other than yourself (who don’t know the backend rules) fill it out. So really, it’s just good practice.
Let’s take a look at how we could make it dynamic now. It’s pretty simple actually, one way you could do it is as simple as this:
//constructor
function Movie($mData)
{
foreach($mData as $key => $val)
{
$this->$key = $val;
}
}
That’s it, that would take anything in the $mData array and store it in Movie class as a member. Accessing $this->name in that example would be no different than accessing $this->name in the first two. However, you have to make sure that a ‘name’ key is in the $mData array when it gets passed in. That’s really not the most safe way to do it though, because that would allow storing anything in the movie class, which isn’t really a good idea. So let’s go back to the entire class definition again.
Class Movie{
var $name = '';
var $director = '';
var $rating = '';
var $genre = '';
//constructor
function Movie($mData)
{
//..code here..
}
}
So this time I’ve given each member a default value that is simply an empty string. Now that they all have defaults, every ‘Movie’ object we create will definitely have each of those variables defined. When they don’t have defaults in them this code will produce a null result:
$badMovie = new Movie();
echo $badMovie->name;
//$badMovie->name does not exist if we do not give it a default value or assign
//a value before calling 'echo'
Let’s rewrite our constructor with an extra check in it this time:
//constructor
function Movie($mData)
{
foreach($mData as $key => $val)
{
if (isset($this->$key))
{
$this->$key = $val;
}
}
}
With the ‘isset’ check here we can check to see if the key in the array is a member that we have defined for our class. If so, then we store the value. With this check an array could be passed in with 100 fields and only ‘name’, ‘director’, ‘rating’, and ‘genre’ will be stored in our Movie object. Now when we want to allow a new value to be stored, all we have to do is add it to our Movie classes members and give it a default value.
Default values are also good because then we can access any member of any Movie object and we know that we won’t get an error from there not being a value stored.
In the end this doesn’t make your classes 100% dynamic, but I don’t think that would be a good idea in any situation because it just asks for trouble from users. But this can make your life easier if you are consistent with naming and whatnot. Also, when you start to look at possibilities like creating clean post, get, server, files classes that take everything in $_POST, $_GET, $_SERVER, or $_FILES accordingly and cleans that data then stores it as a member, maybe you can start to imagine why this can be helpful. Just one example.
Happy coding!
