Page 1 of 1

Class Help

Posted: Thu Jul 21, 2005 1:41 pm
by Jr
Ok, so I've worked on a site and thought I learned quite a bit until someone poses the question "did you use a class to do that?" and I say "no." I was just wondering if anyone knows where I can find a good "PHP Class" tutorial. I'm going through some tuorials online but I still dont see "WHY" you would use classes muchless "how" on top of that. help? please?

Thanks,
Jr-

Posted: Thu Jul 21, 2005 2:26 pm
by Roja
I'll answer in general terms. This is an incredibly contrived answer - totally wouldn't do this in the real world, but should highlight the "why" and some of the "how".

Lets say you wanted to do hello world.

Code: Select all

echo "Hello world!";
Now, it works. Thats procedural code. You decide that gosh, it would be nice to be able to define what you say instead of "Hello world" all the time. You'd also like to be able to make sure the html tags line up - True paragraphs or death!

So, you make a function.

Code: Select all

formatted_echo("Greetings, world!");
function formatted_echo($text)
{
echo "<p>" . $text . "</p>";
}
Not bad, but then you realize that Steve is going to want to use the formatted_echo in HIS programs too. He might even like your 'endpage' function. So, you write a class to make it easy for him:

Code: Select all

$test = new pagehandler;
$test->formatted_echo("Greetings, Steve!");
$test->endpage();

class pagehandler
{
    function formatted_echo($text)
    {
        echo "<p>" . $text . "</p>";
    }

    function endpage()
    {
        echo "</body></html>";
    }
}
Then, years later, you've written a massive 40,000 line program that *relies* on formatted_echo adding para-tags to text. So, you decide that you need unit testing, which sends text in (known input), and expects a known output.

Voila. Procedural code -> Function -> Class -> Unit testing, with a example of why you'd do each.

To summarize, in my opinion, much of the value of classes is the clean interface, the simple grouping of similar functions, and the ability to share the code for use in multiple apps easily - and with a defined interface.

Granted, the lifecycle in reality won't look anything like this. You might follow TDD, and start with writing tests. You might follow raw-OOP, and make an object first, and then design classes to handle them, and add tests. You might never use unit-testing, avoid classes, and focus on functions and procedural code because to you its easier. Different approaches for different folks.

Hope that clarifies some of how and why to make classes. :)

Posted: Thu Jul 21, 2005 2:39 pm
by Jr
hmm... think that kind of answers some questions. I'm just struggeling with this "Class" concept and want to learn it just to know it more then anything. I just figure if I have a reason why I would use it, it will help me figure out "how" and then "where" to use it.

I suppose I realize that it is mainly just for code reusability (as is any good programming). It's just one of those things you just don't get until you get completely (kind of like functions).

Thanks for the explination its much appriciated.

Posted: Thu Jul 21, 2005 7:37 pm
by timvw
Here is something you (or are about to) know: Inserting a row in a SQL database table...

Basically, you every time need to mysql_connect, mysql_select_db, generate sql, mysql_query. But the data you are using is also related to each other. The generated SQL is related to the concrete mysql server/table.

So you could write a class that holds all that data together.

Code: Select all

class Table
{
  // data that is unique for each instance
  var $dbhost;
  var $dbuser;
  var $dbpass;
  var $dbname;

  var $table;

  function insert($row)
  {
    // try to connect to the database
    if (!$this->connect()) return false;

    // build the query
    $sql1 = "INSERT INTO " . $this->table . " (";
    $sql2 = ") VALUES (";
    foreach($row as $column => $value)
    {
      $sql1 .= "`$column`, ";
      $sql2 .= "'" . mysql_real_escape_string($value) . "', ";
    }
    $sql1 = rtrim(", ");
    $sql2 = rtrim(", ");

    $query = $sql1 . $sql2 . ")";

    // try to execute the query
    if (!mysql_query($query))
    {
      return false;
    }

    // might want to retrieve the last_insert_id etc..

    // everything went well 
    return true;
  }
}

And now you have a project where you need to insert players...

Code: Select all

$table = new Table('localhost', 'user', 'pass', 'dbname');
$table->setTable('players');

$row = array('playername' => 'timvw', 'skills' => 1, 'email' => 'timvw@invalid.org');

$table->insert($row);
Or another project where you need to insert purchases

Code: Select all

$table = new Table('example.org', 'user', 'pass', 'dbname');
$table->setTable('purchases');

$row = array('product_id' => 'xqsdfa', 'qty' => 100, 'price' => '1200');

$table->insert($row);
It does not only makes life easier, because you don't have to keep the variables together, it also allows you to reuse code ;)

Imagine the case where you would need to insert players and purchases at the same time.. You have to make sure the right dbhost, dbuser, dbpass, dbname are used for the generated SQL. This is an example where OOP can make things easier. (Although it's also very common to put them in a "struct" or "hash" and then have a function insert($dbdata, $row))

Probably, you want also to test if things are really doing what you expect from them, and then you will get fed up with always writing echo statements and commenting them out afterwards... And when you change something, you have to restart everyting... So you want to stop repeating that too...

In that case i suggest you have a look at http://simpletest.sf.net which allows you to write unittests. Actually, it's another example of classes that you can (re)use to do common stuff (testing if your code does what it is supposed to do)