Location: PHPKode > projects > Modular Site Manager > htdocs/tutorials/PHP-22.php
Ever have that <strong>big</strong> project that you gotta do that requires alot of MySQL work? Well, I believe this is just the tutorial for you <img src="images/smileys/happy.gif" alt="" /><br />
<br />
Here's what you will have (hopefully) learned by the end of this tutorial. <ul>
<li>Create and use classes</li>
<li>Use MySQL (if you didn't know already)</li>
<li>Use define() for security</li>
</ul>Ok, might as well start huh?<br />
<strong>PART 1</strong><br />
Well, first we need to esablish or mysql user name, password, all that stuff. We're going to use the define() function so we can make things more secure, so that you don't have to worry about anything being overwritten by the user.<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight("<?php<br />
define(\"MYSQL_USER\", \"user\"); <br />
define(\"MYSQL_PASS\", \"password\");<br />
define(\"MYSQL_HOST\", \"localhost\");"); ?></div><br />
Change "user" to your MySQL username, "password" to your MySQL password, and "localhost" to your MySQL host. You can usually leave the host alone, since 90% of web hosts have MySQL on the same server as everything else.<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight("class mysql<br />
{<br />
"); ?></div><br />
Well, we establish the class name, and start it <img src="images/smileys/happy.gif" alt="" /><br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('    var $connected = false;<br />
    var $mdc = NULL;'); ?></div><br />
We establish our two class-wide variables <img src="images/smileys/happy.gif" alt="" /><br />
<br />
Remember, you can't do a ton here. And these can be overwritten in the functions (whch they are).<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('    function mysql($db, $nc=false)<br />
    {<br />
  if(!$nc)<br />
  {<br />
      $this->mdc = mysql_connect(\"localhost\", MYSQL_USER, MYSQL_PASS) or $this->error();<br />
      mysql_select_db($db);<br />
      $this->connected = true;<br />
  }<br />
  return true;<br />
    }'); ?></div><br />
Ok, this is what is called a "constructor". In PHP4, the constructor is always the name of the class that it's in. <br />
If you notice that some of the variables in the defining of the function are set, don't think it's weird. This simply allows you to leave them out when you call them later. I call these "default settings" :P Ok, onto the inner code of this function. <br />
<br />
First of all, we check to see if variable $nc is set to false, if it is, we run the code, if not, we just return true, but do nothing. If it's false, we connect to the MySQL server, or if that doesn't work out, we call a function that we'll later create. If you notice, we also assign the class-wide variable $mdc to the connection. Then we go on to select the database we want, then set the class-wide variable $connected, to true <img src="images/smileys/happy.gif" alt="" /><br />
Ok, I'll tell what each of the variables in the function line do. <br />
$db is the name of the database you want in a string. <br />
$nc can be set to true or false. if it's true, we don't connect to MySQL. This by default, is false. <br />
<br />
Now for the close function. <br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('function close()<br />
    {<br />
  if($this->connected !== true)<br />
  {<br />
      $ret = false;<br />
      echo \"You must connect before you close!\";<br />
  } else {<br />
      mysql_close($this->mdc);<br />
      $ret = true;<br />
  }<br />
  return $ret;<br />
    }'); ?></div><br />
What this function does is close the MySQL connection. It checks to see if the class-wide variable $connected is true or false. If it's anything BUT true, it reports that you aren't connected, and returns false, meaning that the function <em>didn't</em> succeed in it's task. But if $connected is set to true, it disconnects from the server and returns true, meaning that it <em>did</em> succeed in its task. <br />
<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('    function select($table, $columns=NULL, $ord, $sort = NULL, $limit = NULL)<br />
    {<br />
  // Again, check our connection<br />
  if($this->connected !== true)<br />
  {<br />
      $ret = false;<br />
      echo \"You have to connect before you can select!\";<br />
  } else {<br />
      if(!is_null($limit) && is_null($columns))<br />
      {<br />
    $ret = @mysql_query(\"SELECT * FROM \".addslashes($table).\" ORDER BY \".addslashes($ord).\" \".addslashes($sort).\" LIMIT \".$limit) or $this->error();<br />
      } elseif(is_null($limit) && is_null($columns)) {<br />
    $ret = @mysql_query(\"SELECT * FROM \".addslashes($table).\" ORDER BY \".addslashes($ord).\" \".addslashes($sort)) or $this->error();<br />
      } elseif(is_null($limit) && !is_null($columns)) {<br />
    $ret = @mysql_query(\"SELECT * FROM \".addslashes($table).\" WHERE \".$columns.\" ORDER BY \".addslashes($ord).\" \".addslashes($sort)) or $this->error();<br />
      } elseif(!is_null($limit) && !is_null($columns)) {<br />
    $ret = @mysql_query(\"SELECT * FROM \".addslashes($table).\" WHERE \".$columns.\" ORDER BY \".addslashes($ord).\" \".addslashes($sort).\" LIMIT \".$limit) or $this->error();<br />
      }<br />
  }<br />
  return $ret;<br />
    }'); ?></div><br />
Oh boy... hopefully you understand what I've said so far to understand some of this. Here is our select function. This allows you to quickly and securely select rows from a MySQL database. I understand this looks <strong>really</strong> hectic, but I assure you that it works <img src="images/smileys/happy.gif" alt="" /> First we define our function-wide variables, and set some of them to defaults. Then we go and check if the class-wide variable $connected is true again, and reports if it's not. If it is, we go ahead and check more stuff. Each one of those does things a tad differently. I'd be here forever explaining everything that it's checking. Basically it's checking to see if the function-wide variables are null (or empty/blank) and doing things accordingly. if you notice, I have an @ sign before the mysql_query() function. This hides any errors the function might report itself, and runs our own error function instead. Again, we make this later. <br />
Now for what the variables do/mean.<br />
$table is the MySQL table that you want to select from. <br />
$columns are the table columns that you want to select from, if any.<br />
$ord is the column you want to order everything by.<br />
$sort is the direction you want to sort things in (ascending, descending), if any.<br />
$limit is the maximum number of rows you want to "grab", if any.<br />
<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('    function update($table, $data, $where)<br />
    {<br />
  if($this->connected !== true)<br />
  {<br />
      $ret = false;<br />
      echo \"You have to connect before you can update!\";<br />
  } else {<br />
      $ret = @mysql_query(\"UPDATE \".$table.\" SET \".$data.\" WHERE \".$where.\" LIMIT 1\") or $this->error();<br />
  }<br />
  return $ret;<br />
    }'); ?></div><br />
Here's a simple update function. First we check and see if we're connected, then if we are, run the update query. There's not alot to explain in this one, as it's pretty straight-forward.<br />
The variables:<br />
$table is, again, the table we want to update.<br />
$data is the new column data we're putting in.<br />
$where is what column that you want to update, like if you only want certain ones updated.<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('    function delete($table, $where, $limit=\"1\")<br />
    {<br />
  if($this->connected !== true)<br />
  {<br />
      $ret = false;<br />
      echo \"You have to connect before you can delete anything!\";<br />
  } else {<br />
      $ret = @mysql_query(\"DELETE FROM \".$table.\" WHERE \".$where.\" LIMIT \".$limit) or $this-error();<br />
  }<br />
  return $ret;<br />
    }'); ?></div><br />
This is our delete function. Again, not too much to explain. <br />
$table ... I think you get the idea <img src="images/smileys/wink.gif" alt="" /><br />
$where is about the same as the last one. Basically what must be true for the row to be deleted (certain ID number, username, ect).<br />
$limit same as the select one. this one is defaulted to one, but if you want to loop through and delete alot of things at once, then set this to a higher number.<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('    function query($query)<br />
    {<br />
  if($this->connected !== true)<br />
  {<br />
      $ret = false;<br />
      echo \"You have to connect before you can run any queries!\";<br />
  } else {<br />
      $ret = @mysql_query($query) or $this->error();<br />
  }<br />
  return $ret;<br />
    }'); ?></div><br />
Ok, here's our all-purpose query function. Use this wisely. I use it for when I need to run advanced queries like selecting muliple tables.<br />
$query... sorry, but if you can\'t figure this out... This is what query you want to run.<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('    function insert($table, $cols, $vals)<br />
    {<br />
  $ret = \"INSERT INTO \".$table.\" ( \";<br />
  // check to see if the columns is an array or not..<br />
  if(is_array($cols))<br />
  {<br />
      // it is! so lets loop through them, and add them to the query<br />
      $t = count($cols);<br />
      $i = 0;<br />
      foreach($cols as $col)<br />
      {<br />
    $i++;<br />
    //checking to see if it\'s the last one in the array.<br />
    if($i !== $t) <br />
    {<br />
        $ret .= \"`\".$col.\"` , \";<br />
    } else {<br />
        $ret .= \"`\".$col.\"` \";<br />
    }<br />
      }<br />
  } else {<br />
      //it\'s not an array.. so lets just slap it in there<br />
      $ret .= \"`\".$cols.\"`\";<br />
  }<br />
  $ret .= \" ) VALUES (\";<br />
  //same thing as above, but with the insert values<br />
  if(is_array($vals))<br />
  {<br />
      $t = count($vals);<br />
      $i = 0;<br />
      foreach($vals as $val)<br />
      {<br />
    $i++;<br />
    if($i !== $t)<br />
    {<br />
        $ret .= \"\'\".$val.\"\', \";<br />
    } else {<br />
        $ret .= \"\'\".$val.\"\'\";<br />
    }<br />
      }<br />
  } else {<br />
      $ret .= \"\'\".$vals.\"\'\";<br />
  }<br />
  $ret .= \")\";<br />
  return @mysql_query($ret) or die($this->error());<br />
    }'); ?></div><br />
"Ho...ly...crap.." I hear you non-advanced php users saying. Don't worry, I commented the crap out of this one. This is fairly advanced stuff. It's mostly array reading. Since the insert MySQL command is really touchy, the code has to be fancy. First we establish the first part of the query, then we jump into the array thing. It checks to see if the variable $cols is an array or not. If it is, loop through them and add them to the query. Since the last column you put in the query has to be different, I threw in that check, and <strong>made</strong> it different :P. The second part is almost the same as the first, but <em>it</em> loops through the $vals variable. After all that, we finish off the query, then return it <img src="images/smileys/happy.gif" alt="" /><br />
Variables used:<br />
$table, you get the point...<br />
$cols is the columns that you are inserting into.<br />
$vals is the data that you are inserting into the columns. make sure that they corrospond!<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('    function error()<br />
    {<br />
  global $REMOTE_ADDR, $_SERVER;<br />
  echo \"Uh oh, looks like we got an error in MySQL! <br />
<br />
The error returned was <br />
<div style=\\\"margin-left: 10px; border: 1px solid #000;\\\">\".mysql_error().\"</div><br />
Logging this and emailing the admin<br />
<br />
\";<br />
  $fp = fopen(\"logs/error.mysql.log\", \"a\");<br />
  fwrite($fp, $d.\" \".$REMOTE_ADDR.\" ERROR: \".mysql_error().\"\\n\");<br />
  mail(\"hide@address.com\", \"MySQL Error\", $d.\" \".$REMOTE_ADDR.\" ERROR: \".mysql_error().\", \"FROM: hide@address.com\");<br />
  return false;<br />
    }'); ?></div><br />
Finally, our error function. What this does is handle any MySQL error that could come up. First it tells the user what happened, then that it sent you an email and logs it. Then it sends you an email, with the users IP address, and what the MySQL error was. I find this is good so if a user tries to hack it, and they slip and make it wrong, you can see what they tried to do, and you have thier IP address so you can report them to their ISP. <br />
<br />
Don't forget to close the class! <br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight("} <br />
?>"); ?></div> <img src="images/smileys/happy.gif" alt="" /><br />
<br />
<strong>PART 2</strong> - Using the class<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('<?php<br />
include \"path/to/mysql/class/file.php\";<br />
$mysql = new mysql(\"mydb\");'); ?></div> <br />
this includes the file that the mysql class is in, and then 'initiates' the class.<br />
<div class="code"><strong>CODE:</strong><br />
<hr /><?php xhtml_highlight('
$mysql->delete(\"mytable\", \"username=\'\".$_POST[\'user\'].\"\'\");<br />
$mysql->insert(\"mytable\", \"username\", $_POST[\'user\']);<br />
$mysql->insert(\"mytable\", array(\"id\", \"username\", \"password\"), array(\"22\", $_POST[\'user\'], md5($_POST[\'password\']));<br />
$mysql->close();<br />
?>'); ?></div><br />
and that's it. pretty easy huh?<br />
---<br />
If you have any questions or comments, leave them! <br />
learn more about <a href="http://us2.php.net/manual/en/ref.classobj.php">classes</a>, <a href="http://us2.php.net/manual/en/function.define.php">define()</a>, <a href="http://us2.php.net/manual/en/ref.mysql.php">MySQL functions</a>, <a href="http://www.mysql.org">MySQL itself</a>
Return current item: Modular Site Manager