Basics: Object Oriented PHP from a C# point of view
I've been slowly picking up PHP over the last 6 months or so to broaden my skillset. Up to now I've made procedural php pages and while that has worked it has felt a bit clunky. When I was asked to put together a simple LAMP stack to track GIT Hashes and map them to something similar to an SVN 'rev' I decided to dive head long into Object Oriented PHP. I did this for maintainability- this was for work, not some hacky page I put together on the side.
While things are still fresh in my mind I'd like to document what I had to do to get a simple class-based (Object Oriented) PHP project started from my perspective as a C# Developer (I spend most of my day in .NET land these days).
Updated: 27-July-2012
References:
- PHP General
- Object Oriented PHP for Beginners [killerphp.com]
- PHP Include and Require [w3schools.com]
- PHP: How to Get the Current Page URL [webcheatsheet.com]
- PHP: Installation of extensions on Windows [php.net]
- PHP & MySQL
- Connecting and prepared statements with the mysqli extension [databasejournal.com]
- PHP5 mysqli::query [us3.php.net]
- mysqli_result::fetch_assoc [php.net]
- mysqli_result::fetch_object [php.net]
- Call to a member function fetch_assoc() on a non-object [stackoverflow.com]
- Getting error: Cannot use object of type mysqli_result as array [stackoverflow.com]
- Nested looping with mysqli and fetch_object [stackoverflow.com]
- 3 Different MySQL APIs [php.net]
- MySQL Improved Extension [php.net]
- PHP Best Practices
Why write this article?
PHP is pretty ubiquitous once you get off of the Microsoft Stack. It's been aound for years and millions of websites are powered by it. Given my propensity to learn about (and expand) my understanding of technology, it definitely merits a look. But where to start? If I were coming from an entirely Microsoft background, what would I have to do to get some simple back-end code written in PHP? What about database connectivity?
First step: Install & Configure PHP / MySQL
To get PHP up and running on windows is fairly straightforward:
- Download a Windows build of PHP
- Unzip it to C:\php
- Other locations can be used if you set the appropriate configuration in the php.ini file
- Duplicate and rename one of the sample php.ini files (like php.ini-development ) to php.ini
- You'll want to run through this and make sure it is setup correctly
- For DB connectivity uncomment extension=php_mysqli.dll (or one of the other sql dlls)
- If you use PHPStorm [jetbrains.com], setup the interpreter and make sure it recognizes the PHP version:
- For MySQL I tend to just run it on a Linux box. I'm sure there is an MySQL Installer for Windows somewhere if you want to use that...
Next: How do I make a class?
.NET developers think in Classes and objects. We know how to define them, create them, consume them and destroy them. How is that done in PHP?
Here is what a sample class file looks like in PHP. This can be saved with a php extension (Person.php):
class Person
{
var $Name;
var $Address1; // Comments look like this
var $Addess2;
var $Telephone;
function SetName($name){
$this->Name = $name;
}
function GetName(){
return $this->Name;
}
function SetDetails($Address1, $Address2, $Telephone){
$this->Address1 = $Address1
$this->Address2 = $Address2;
$this->Telephone = $Telephone;
}
function GetTelephone(){
return $this->Telephone;
}
}
?>
A few things to note:
- You may be thinking, "Well, that's kind of strange.", and you'd be correct. What is up with that PHP Arrow operator -> (what I call it- not sure the official name)? The short answer is that it takes the place of the period when calling members of an object instance. A double-colon ( :: ) is used for static members
- PHP doesn't have strongly typed variables (that I am aware of). That is why the function definitions look a little 'bare'
- $this is like this in C#. When you instansify your class and get an object, $this means 'this instance'
You can see a class in PHP is pretty much like a class in C# (except for the goofy PHP syntax)
Ok, How do I use a class?
As in C#, your source file needs to know about a class before it can be used. In PHP this is accomplished with the require and include directives (See the references section above for details). If I wanted to use my Person class in a PHP program, I would make a PHP file that referenced the class file like this:
// Make sure the class is available
require('Person.php');
// Create a new Person
$person = new Person();
// Give the person some properties:
$person->SetName('Gregory');
$person->SetDetails('432 Elm Street', 'Soldier Summit, UT 84562', null);
// Print the person's name:
echo $person->GetName();
?>
There are a couple of things to take away from the above sample:
- require and include can accept relative paths to your PHP Class files
- Any require or include must appear *After* the opening statement
- If you want to call an Object Instance Method, you use the same PHP Arrow operator => as if you were accessing a property
Working with MySQL Database
There are at least 3 different ways you can interact with a MySQL Database using PHP. I've chosen the mysqli path as it is accessible via OO and seems fairly concise. As with many things on this site, I'll write the code first and then explain:
function AddPerson($table, $person){
$con = new mysqli('ip.address.toMySQLhost', 'username', 'password', 'cia_person_db');
$query = "INSERT INTO $table (Name, Telephone) VALUES ('$person->GetName()', '$person->GetTelephone()')";
$result = $con->query($query);
$con->close();
// return 'true' if the Add was successful. 'false' if it fails
if($result){
return true;
} else {
return false;
}
}
Here's an explanation of what is happening in the above function:
- We create a new mysqli connection (See references at the top for details) using DB Name, Username, Password and DB parameters
- A query string is put together. In this case we are inserting $person into whatever $table is passed in.
- PHP supports parameter expansions, so you can call properties and instance methods and the result will appear in the string. When I say $person->Getname() I am grabbing the name and placing it in the appropriate place in the SQL query string
- I then call the query method on the $con object. This runs the query and stores the result in $result.
- After the query executes, I call $con->close() to free the SQL connection. The results are saved into $result so I can disconnect without difficulty
- The final if block determines if the method returns true or false.
- When a query isn't executed properly $result will be equal to false. If it completes successfully it has a number of attributes and methods that can be used to extract the data
Retrieve data from a MySQL Database:
You can retrieve data from a MySQL database without much hassle. Depending on what you need to retrieve you can either use fetch_object() or fetch_assoc(). Here is a method which uses both methods to retrieve all data rows from all tables in a database and returns a JSON Array:
function GetAllDataFromAllTables($db_server, $db_user, $db_password, $db_name){ // Find all the tables in the database $con = new mysqli($db_server, $db_user, $db_password, $db_name); if (mysqli_connect_errno()) { printf("Connect failed: %s\n", mysqli_connect_error()); exit(); } $query = "SHOW TABLES"; $result = $con->query($query); // Iterate over each one and create JSON Objects out of each result row $json = array(); while($row = $result->fetch_assoc()){ $tableNameColumn = 'Tables_in_'.$db_name; $table = $row[$tableNameColumn]; // fetch_assoc syntax $query = "select * from `$table`"; $result_rows = $con->query($query); while($result_row = $result_rows->fetch_object()){ $id = $result_row->id; // fetch_object syntax $volt = $result_row->Voltage; $amps = $result_row->Current; $tbl = $table; $json[] = '{"SnapshotIndex":'.$id.',"Voltage":"'.$volt.'","Amperage":"'.$amps.'","Table":"'.$tbl.'"}'; } } // Close DB Connection $con->close(); // Implode with comma delimiter and wrap in square braces (JSON Array) $json_objects = implode(',', $json); $json_results = '['.$json_objects.']'; // Return JSON results return $json_results; }
In the above-method you can see examples of the following:
$obj = $result->fetch_object(); // Grab the result object (one row of data)
$version = $obj->Name; // Pull data from the Name column of the row retrieved using fetch_object()
$row = $result->fetch_assoc() // Grab a row of data as an array
$col_data = $row[$ColumnName]; // Pull data out based on array string key value rather than property name
You can do a while loop to keep grabbing objects or data rows
To get data that is oldest or newest you can do an order by column_name asc in your query.
Final word
I'm gaining a respect for PHP that I wasn't expecting to find. I know it is popular to belittle PHP (Especially if you are in to Ruby on Rails, Python, Node.JS, etc...), but it is a very servicable language. And it can be fairly fast if you get an opcode cache like APC installed.
Use the right tool for the right job: PHP is a useful tool that I'll be using in the future to complement my C# / .NET / Mono activities.