starting object oriented php
this lab will make a start with object oriented (oo) php. this lab has three exercises.
- creating some simple classes so you're happy with the syntax etc
- making a database class to access the record store database
- creating an oo version of a file upload script
1. basic classes
a note on naming conventions: it is typical to use PascalCase for classes, camelCase for methods (& properties) and lower_case for variables & functions. Whatever conventions you use, try to use them consistently.
1.1 the basic definition is given in the php manual http://php.net/manual/en/language.oop5.basic.php create a class for an object of your choice (person, pet, planet - it's up to you). define a few attributes and methods. write a script that instantiates this class and invokes one of its methods.
1.2 add a constructor __construct() to your class to set some attributes when it is first created (see http://php.net/manual/en/language.oop5.decon.php)
1.3 inheritance in php is specified here: http://php.net/manual/en/language.oop5.inheritance.php extend your class in two ways, and show that you can use them.
1.4 overriding in php (modifying an inherited method) is easy: you just need to create method with same name in your child class which you want to override. Do this for your two new classes and demonstrate that you have created two different methods which are invoked the same way.
1.5 demonstrate that autoloading of your classes works. note that it is now recommended to use spl_autoload_register() rather than __autoload() http://php.net/manual/en/language.oop5.autoload.php. Here's an example of how it works:
spl_autoload_register(function ($class_name) {
$class_name = strtolower($class_name);
include $class_name . '.class.php';
});
Put this near the top of your script, not in the class itself.
2. database class
define a database class with the connection parameters (i.e. host, user, password, database name) are private attributes.
use __construct() to set the values for these so that a connection is made to your recordstore database.
define methods to open and close the database connection: something like public function openConnection()
which assigns the mysqli connection to $this->connection.
define a method to execute an sql query: something like public function executeSql($sql)
which returns the result of a mysqli_query
write a script to instantiate your class. open a database connection and execute a query to check it's all working properly.
3. oo upload
we're going to create an object oriented script that uploads images and displays them as a gallery. this is a stand-alone script and not part of the recordstore.
3.1 using the same process as the recordstore index page, create a minimal index page that can load two views; gallery and upload. the gallery should be the default.
3.1.1 the page will have two links; you can include these as a navigation template or view. make the links of the form <a href='index.php?page=gallery'>Gallery</a>
3.1.2 the index page will route to a view depending on which one was clicked. you can use code like this:
$userClicked = isset($_GET['page']);
if ( $userClicked ) {
$fileToLoad = $_GET['page'];
} else {
$fileToLoad = "gallery";
}
include_once "views/$fileToLoad.php";
create placeholders for the gallery and upload views to check it works.
3.2 as in our previous lab, the script for the upload view will display a form and process the form if $_POST is set. for now, just create the form to upload an image.
3.3 now we'll create an Uploader class.
3.3.1 this will have the following private attributes
private $filename;
private $fileData;
private $destination;
3.3.1 an important bit of information is the name that the upload form assigns to the uploaded file.
if that form element was <input type='file' name='image-data' accept='image/jpeg'/>
then 'image-data' is the key to the information stored in the $_POST array.
we'll use that in the __contstruct method to access the other information we need: so the constructor will look like:
public function __construct( $key ) {
$this->filename = $_FILES[$key]['name'];
$this->fileData = $_FILES[$key]['tmp_name'];
}
3.3.2 as before, we'll need a folder to save the image in. you can create a new one (remember permissions) or use the same one that the recordstore is using (remember relative paths).
3.3.3 set the file destination in the Uploader class to be this directory: e.g. with a method like
public function saveIn( $folder ) {
$this->destination = $folder;
}
3.3.4 now we'll create a method to move the uploaded file, using move_uploaded_file
. we'll also make use of the handy is_writable
function to check we got the directory permissions right.
here it is, wrapped up as a method:
public function save(){
$folderIsWritAble = is_writable( $this->destination );
if( $folderIsWritAble ){
$name = "$this->destination/$this->filename";
$success = move_uploaded_file( $this->fileData, $name );
} else {
trigger_error("cannot write to $this->destination");
$success = false;
}
return $success;
}
3.4 now you can go back to your upload view and write the code to process the form. you'll need to
- instantiate a new uploader object using 'image-data'
- tell it where to save the image
- execute the save method
3.5 now we've uploaded some images, we need the gallery view to display them. we can make use of one of php's built in classes, called DirectoryIterator, which you can read about here: http://php.net/manual/en/class.directoryiterator.php
here's a full version of the gallery view; experiment with it to make sure you understand how it works
return showImages();
function showImages(){
$out = "<h1>Image Gallery</h1>";
$out .= "<ul id='images'>";
$folder = "img";
$filesInFolder = new DirectoryIterator( $folder);
while ( $filesInFolder->valid() ) {
$file = $filesInFolder->current();
$filename = $file->getFilename();
$src = "$folder/$filename";
$fileInfo = new Finfo( FILEINFO_MIME_TYPE );
$mimeType = $fileInfo->file( $src );
if ( $mimeType === 'image/jpeg' ) {
$out .= "<li><img src='$src' /></li>";
}
$filesInFolder->next();
}
$out .= "</ul>";
echo $out;
}