|
| 1 | +--- |
| 2 | +layout: page |
| 3 | +title: PHP Tutorial 3 |
| 4 | +--- |
| 5 | + |
| 6 | +##### Requirements |
| 7 | + |
| 8 | +* PHP Installation with command-line (use our [guide](../using-php/simple.html) for help on this) |
| 9 | + |
| 10 | +* That you have taken one of the other programming language courses, like the Javascript, Ruby or Python courses so that you are familiar with some of the typical things you see in computer languages. |
| 11 | + |
| 12 | +##### Achievements |
| 13 | + |
| 14 | +You will explore the world of classes and objects in PHP, building an example musical database. |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## Using Script mode |
| 19 | + |
| 20 | +For this tutorial, we will be using the script mode of the PHP command-line (CLI). Please see our [guide](../using-php/simple.html#script-mode) for more information about using this mode. |
| 21 | + |
| 22 | +You need only work in one script file for this tutorial. |
| 23 | + |
| 24 | +## Introduction to Classes and Objects |
| 25 | + |
| 26 | +PHP follows similar languages and provides classes. They are used to represent some _thing_ in your project that has various bits of data and possibly code associated with it. It's a nebulous explanation because it's a very versatile tool in terms of what it can represent and how it can be used. |
| 27 | + |
| 28 | +The _class_ is the template or definition of the _thing_. But in your code, you create _instances_ (also known as _objects_, though _object_ is often used to cover the concept of both class and instance) of classes, where the data is filled in. An example class definition might be like below. When you type this into the interactive editor, it realizes you are entering a command that will span across multiple lines. |
| 29 | +```php |
| 30 | +class Song { |
| 31 | + public $title; |
| 32 | + public $artist; |
| 33 | + |
| 34 | + public function toMp3Path() { |
| 35 | + return $this->artist . '/' . $this->title . '.mp3'; |
| 36 | + } |
| 37 | +} |
| 38 | +``` |
| 39 | +The scene is set! This has defined a `Song` class for which we can create instances. It contains 3 public variables, `public` means that you can read and write to them directly without using functions. We've also defined a typical function for a song which is to get its' filename as though it was in your music folder. It uses the special variable `$this` that will refer to the instance it's called in, i.e. itself. Let's have a go at using it: |
| 40 | +```php |
| 41 | +$myTune = new Song(); |
| 42 | +$myTune->title = "Lullaby"; |
| 43 | +$myTune->artist = "The Cure"; |
| 44 | +echo $myTune->toMp3Path(); // displays The Cure/Lullaby.mp3 |
| 45 | +``` |
| 46 | +The first line has created the instance of a `Song` and assigned it to the `$myTune` variable. We've then accessed the _properties_ (internal variables, if you like) and set them in lines 2 & 3. Then we've called the function that we defined, and `$this` will be referring to the instance that we created. |
| 47 | + |
| 48 | +We can still modify the instance we created and re-run the function. E.g. |
| 49 | +```php |
| 50 | +$myTune->title = "Pictures of you"; |
| 51 | +echo $myTune->toMp3Path(); // displays The Cure/Pictures of you.mp3 |
| 52 | +``` |
| 53 | + |
| 54 | +We can also create more instances: |
| 55 | +```php |
| 56 | +$anotherTune = new Song(); |
| 57 | +$anotherTune->title = "Lovesong"; |
| 58 | +$anotherTune->artist = "The Cure"; |
| 59 | +echo $myTune->toMp3Path(); // displays The Cure/Lovesong.mp3 |
| 60 | +``` |
| 61 | +There is also another feature of classes, _inheritence_. This is the premise that the definition of a _thing_ may have subsets that have the same basic properties of that thing, but may have additional properties or functions. In our song example, we may identify a song as being the album version or the single. Let's define these: |
| 62 | +```php |
| 63 | +class Single extends Song { |
| 64 | + public $highestUKChartPosition; |
| 65 | + public $highestUSChartPosition; |
| 66 | + |
| 67 | + public function highestChartPosition() { |
| 68 | + if ($this->highestUKChartPosition < $this->highestUSChartPosition) { |
| 69 | + return ["chart" => "UK", "position" => $this->highestUKChartPosition]; |
| 70 | + } else { |
| 71 | + return ["chart" => "US", "position" => $this->highestUSChartPosition]; |
| 72 | + } |
| 73 | + } |
| 74 | +} |
| 75 | +class AlbumSong extends Song { |
| 76 | + public $album; |
| 77 | + public $trackNumber; |
| 78 | + |
| 79 | + public function toMp3Path() { |
| 80 | + return $this->artist . '/' . $this->album . '/' . $this->trackNumber. '. ' . $this->title . '.mp3'; |
| 81 | + } |
| 82 | +} |
| 83 | +``` |
| 84 | +For the single, we have added the chart positions in the UK & US, and a function that will tell us the highest position in which chart. For the album version of a song, we've added the album and track number. Because we have more information that we can make a better MP3 filename, we're able to redefine the function to take on this additional information. Let's use these: |
| 85 | +```php |
| 86 | +$greatSingle = new Single(); |
| 87 | +$greatSingle->title = "Jean Genie"; |
| 88 | +$greatSingle->artist = "David Bowie"; |
| 89 | +$greatSingle->highestUSChartPosition = 71; |
| 90 | +$greatSingle->highestUKChartPosition = 2; |
| 91 | +echo $greatSingle->toMp3Path(); // displays David Bowie/Jean Genie.mp3 |
| 92 | +$chartPosition = $greatSingle->highestChartPosition(); |
| 93 | +echo "Reached " . $chartPosition["position"] . " on " . $chartPosition["chart"] . " chart"; |
| 94 | + // displays Reached 2 on UK chart |
| 95 | + |
| 96 | +$songOnAlbum = new AlbumSong(); |
| 97 | +$songOnAlbum->title = "One"; |
| 98 | +$songOnAlbum->artist = "Ed Sheeran"; |
| 99 | +$songOnAlbum->album = "X"; |
| 100 | +$songOnAlbum->trackNumber = 1; |
| 101 | +echo $songOnAlbum->toMp3Path(); // displays Ed Sheeran/X/1. One.mp3 |
| 102 | +``` |
| 103 | + |
| 104 | +It's a bit of a pain having to set up the artist and song title each time on separate lines, and we have to set them up every time for every instance. Is there an easier way to do this? Yes! We can use a _constructor_. This is a piece of code that gets run when you create the instance as part of the `new` statement. It allows us to set arguments in the brackets on that line. |
| 105 | + |
| 106 | +Let's define an album class that takes advantage of this. We'll also define a way of easily adding songs to this album, because classes can also act as _containers_ for other instances. |
| 107 | +```php |
| 108 | +class Album { |
| 109 | + public $title; |
| 110 | + public $artist; |
| 111 | + public $songs = array(); |
| 112 | + |
| 113 | + public function __construct($title, $artist) { |
| 114 | + $this->title = $title; |
| 115 | + $this->artist = $artist; |
| 116 | + } |
| 117 | + |
| 118 | + public function addSong($title) { |
| 119 | + $song = new AlbumSong(); |
| 120 | + $song->title = $title; |
| 121 | + $song->artist = $this->artist; |
| 122 | + $song->album = $this->title; |
| 123 | + $song->trackNumber = count($this->songs) + 1; |
| 124 | + $this->songs[] = $song; |
| 125 | + } |
| 126 | +} |
| 127 | +``` |
| 128 | +Notice how we're able to use the information for the album to autocomplete our track information? Handy! We're using an array function `count` to tell us how big the songs array is (we add 1 because the first track will be added when the array is empty, so `count($this->songs)` will be 0). `__construct` is a special function name, represented by the double underscore. There are others which provide extra features |
| 129 | + |
| 130 | +So now all we need type to define a whole album is: |
| 131 | +```php |
| 132 | +$pfMeddle = new Album("Meddle", "Pink Floyd"); |
| 133 | +$pfMeddle->addSong("One of these days"); |
| 134 | +$pfMeddle->addSong("A pillow of winds"); |
| 135 | +$pfMeddle->addSong("Fearless"); |
| 136 | +$pfMeddle->addSong("San tropez"); |
| 137 | +$pfMeddle->addSong("Seamus"); |
| 138 | +$pfMeddle->addSong("Echos"); |
| 139 | +``` |
| 140 | +We'll borrow a statement from a later tutorial to display all the song MP3 names: |
| 141 | +```php |
| 142 | +foreach ($pfMeddle->songs as $song) { echo $song->toMp3Path() . "\n";} |
| 143 | +``` |
| 144 | +Which will display |
| 145 | +``` |
| 146 | +Pink Floyd/Meddle/1. One of these days.mp3 |
| 147 | +Pink Floyd/Meddle/2. A pillow of winds.mp3 |
| 148 | +Pink Floyd/Meddle/3. Fearless.mp3 |
| 149 | +Pink Floyd/Meddle/4. San tropez.mp3 |
| 150 | +Pink Floyd/Meddle/5. Seamus.mp3 |
| 151 | +Pink Floyd/Meddle/6. Echos.mp3 |
| 152 | +``` |
| 153 | + |
| 154 | +## Summary |
| 155 | + |
| 156 | +In this tutorial, you have gone through an introduction to classes and objects to build up a small data structure and seen ways to use and manipulate data with it. |
0 commit comments