Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP for PHP tuts 3 and 4 #471

Draft
wants to merge 1 commit into
base: gh-pages
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions php/lesson3/tutorial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
---
layout: page
title: PHP Tutorial 3
---

##### Requirements

* PHP Installation with command-line (use our [guide](../using-php/simple.html) for help on this)

* 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.

##### Achievements

You will explore the world of classes and objects in PHP, building an example musical database.

---

## Using Script mode

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.

You need only work in one script file for this tutorial.

## Introduction to Classes and Objects

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.

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.
```php
class Song {
public $title;
public $artist;

public function toMp3Path() {
return $this->artist . '/' . $this->title . '.mp3';
}
}
```
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:
```php
$myTune = new Song();
$myTune->title = "Lullaby";
$myTune->artist = "The Cure";
echo $myTune->toMp3Path(); // displays The Cure/Lullaby.mp3
```
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.

We can still modify the instance we created and re-run the function. E.g.
```php
$myTune->title = "Pictures of you";
echo $myTune->toMp3Path(); // displays The Cure/Pictures of you.mp3
```

We can also create more instances:
```php
$anotherTune = new Song();
$anotherTune->title = "Lovesong";
$anotherTune->artist = "The Cure";
echo $myTune->toMp3Path(); // displays The Cure/Lovesong.mp3
```
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:
```php
class Single extends Song {
public $highestUKChartPosition;
public $highestUSChartPosition;

public function highestChartPosition() {
if ($this->highestUKChartPosition < $this->highestUSChartPosition) {
return ["chart" => "UK", "position" => $this->highestUKChartPosition];
} else {
return ["chart" => "US", "position" => $this->highestUSChartPosition];
}
}
}
class AlbumSong extends Song {
public $album;
public $trackNumber;

public function toMp3Path() {
return $this->artist . '/' . $this->album . '/' . $this->trackNumber. '. ' . $this->title . '.mp3';
}
}
```
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:
```php
$greatSingle = new Single();
$greatSingle->title = "Jean Genie";
$greatSingle->artist = "David Bowie";
$greatSingle->highestUSChartPosition = 71;
$greatSingle->highestUKChartPosition = 2;
echo $greatSingle->toMp3Path(); // displays David Bowie/Jean Genie.mp3
$chartPosition = $greatSingle->highestChartPosition();
echo "Reached " . $chartPosition["position"] . " on " . $chartPosition["chart"] . " chart";
// displays Reached 2 on UK chart

$songOnAlbum = new AlbumSong();
$songOnAlbum->title = "One";
$songOnAlbum->artist = "Ed Sheeran";
$songOnAlbum->album = "X";
$songOnAlbum->trackNumber = 1;
echo $songOnAlbum->toMp3Path(); // displays Ed Sheeran/X/1. One.mp3
```

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.

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.
```php
class Album {
public $title;
public $artist;
public $songs = array();

public function __construct($title, $artist) {
$this->title = $title;
$this->artist = $artist;
}

public function addSong($title) {
$song = new AlbumSong();
$song->title = $title;
$song->artist = $this->artist;
$song->album = $this->title;
$song->trackNumber = count($this->songs) + 1;
$this->songs[] = $song;
}
}
```
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

So now all we need type to define a whole album is:
```php
$pfMeddle = new Album("Meddle", "Pink Floyd");
$pfMeddle->addSong("One of these days");
$pfMeddle->addSong("A pillow of winds");
$pfMeddle->addSong("Fearless");
$pfMeddle->addSong("San tropez");
$pfMeddle->addSong("Seamus");
$pfMeddle->addSong("Echos");
```
We'll borrow a statement from a later tutorial to display all the song MP3 names:
```php
foreach ($pfMeddle->songs as $song) { echo $song->toMp3Path() . "\n";}
```
Which will display
```
Pink Floyd/Meddle/1. One of these days.mp3
Pink Floyd/Meddle/2. A pillow of winds.mp3
Pink Floyd/Meddle/3. Fearless.mp3
Pink Floyd/Meddle/4. San tropez.mp3
Pink Floyd/Meddle/5. Seamus.mp3
Pink Floyd/Meddle/6. Echos.mp3
```

## Summary

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.
57 changes: 57 additions & 0 deletions php/lesson4/example/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<title>Wild Owl - The Owl Park</title>
</head>
<body>
<header>
<h1>Wild Owl - The Owl Park</h1>
</header>
<nav>
<ul>
<li>Home</li>
<li>Owls at the Park</li>
<li>Contact</li>
</ul>
</nav>
<section class="content">
<section class="intro">
Welcome to Wild Owl, the first owl park of its&squot; kind. Have a look round the site to see what we have to offer when you visit. We give a hoot about you!
</section>
<section class="top-owls">
<header>
<h2>Top Owls to See</h2>
</header>
<main>
<ul>
<li><strong>Barn Owl</strong></li>
<li><strong>Eastern Grass-Owl</strong></li>
<li><strong>Golden Masked-Owl</strong></li>
<li><strong>Barking Owl</strong></li>
<li><strong>Buffy Fish-Owl</strong></li>
</ul>
</main>
</section>
<section class="opening-times">
<header>
<h2>Opening Times</h2>
</header>
<main>
<ul>
<li>
<span class="period">May - September 2018</span>
<span class="hours">6pm - 3am</span>
</li>
<li>
<span class="period">October - April 2018</span>
<span class="hours">4pm - 1am</span>
</li>
</ul>
</main>
</section>
</section>
<footer>
<span class="copyright">Copyright Owl Park 2013-2016 All Rights Reserved</span>
</footer>
</body>
</html>
128 changes: 128 additions & 0 deletions php/lesson4/tutorial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
layout: page
title: PHP Tutorial 4
---

##### Requirements

* PHP Installation with web server (use our [in-depth guide](../using-php/using-php) for help on this)

* This builds on the previous lessons in this tutorial on PHP.

* You should be familiar with HTML, as we will be modifying it. We provide tutorials on HTML.

##### Achievements

You will explore the features of PHP, showing it's typical uses for making small improvements to make web pages dynamic.

---

## PHP In Web Pages

One of PHP's greatest features is that it integrates with HTML. When you use the `<?php` start and `?>` end markers, you are breaking into PHP mode from within HTML markup. We're going to demonstrate PHP's features by building a page that is dynamic.

*Fetch the example files*

### Variables

PHP can store information for retrieval elsewhere. It stores numbers, strings, arrays and objects. All variables start with a `$` followed by at least 1 letter of the alphabet, followed by combination of letters and numbers to make up the name, e.g. `$name`, `$emailAddress`, `$address2`. It can also include underscores.

#### Strings

Let's have a go at creating a string to save some repetition on our page. We have repeated the page title twice so that it appears consistently in the tab and as the main heading on the page. Let's make it so that we only set it once.

At the very top of the page, above the doctype declaration, type in the following to assign a value to the variable we'll use to store our page title.

```php
<?php
$pageTitle = "Wild Owl - Owl Park";
?>
```

Now in the two locations in the page where we have used the title, i.e. between the `<title>` and `<h1>` tags, replace it with:

```php
<?php echo $pageTitle; ?>
```

Now when you run the page, you should see no change. But now if you change the text in the string we assigned to `$pageTitle`, you should see it change in both locations.


#### Dates

We have a copyright notice at the bottom of the page, and it's so laborious that each year we have to update it. We can fix that!

Internally, PHP handles dates by working with a value called the UTC timestamp, the number of seconds since the new year in 1970 in Grenwich, London. It then provides tools that converts this to a format more palettable. This means it can easily support time zones (offsets from GMT, including summertimes), and locales (different expressions of time around the world).

PHP actually has 2 date/time tools. A set of [functions](http://php.net/manual/en/ref.datetime.php), and some [utility classes](http://php.net/manual/en/class.datetime.php). We'll use the more up-to-date class implementation.

To get a Date object that represents the time now, we can add this line (best we do this at the top of our script, under where we set `$pageTitle`):
```php
$now = new DateTime();
```
This creates a new `DateTime` object and stores it in a variable called `$now`. Because we gave it no arguments, it assumes we want the current date. Later we'll see how you can create date objects for other dates.

Now, let's get just the current year and display it in the copyright notice. Replace the 2nd year in the copyright notice with the following:
```php
<?php echo $now->format('Y'); ?>
```
The `->` is how we access a method in the DateTime class that's stored in `$now`. `format` is the name of the method we want to access. `Y` is a string representing the [format of the date](http://php.net/manual/en/datetime.formats.php) stored in `$now`, where Y is just the year as 4 digits.

#### Arrays

The list of top owls changes quite frequently. Changing them in-situ in the page can be a pain. Let's make it easier by using an array.
Let's declare the array, again at the top of the page just under where we set `$now`. We're using the _shorthand_ way of defining the array, it only works beyond PHP v5.4.
```php
$topOwls = [
"Barn Owl",
"Eastern Grass-Owl",
"Golden Masked-Owl",
"Barking Owl",
"Buffy Fish-Owl"
];
```
Individual items in the array can be accessed like this: `$topOwls[4]`, which would return the value `Barking Owl`.

Now let's render the list. Delete all the `<li>` tags under the `<ul>` in the _top-owls_ section. Replace them with:
```php
<?php
foreach ($topOwls as $owl) {
echo "<li>$owl</li>";
}
?>
```
`foreach` is a version of a `for` loop that loops through each item in `$topOwls`, setting `$owl` to the value of the item (note, this is usually a copy of the value, but in some cases could be a reference to the value in `$topOwls`). We then write out the list item tag with the name of the owl inside it. Double speech marks allow us to include variable names within the string.

#### Associate Arrays

Arrays in PHP have a special feature, they can also behave like hash objects. A hash is a variable with sub keys to store different bits of information. Let's have a go at trying to make our opening times a bit easier to work with. Here's how we can represent them with an array of associative arrays:
```php
<?php
$openingTimes = [
[
"season_start" => new DateTime('2018-05-01'),
"season_end" => new DateTime('2018-09-31'),
"opening_time" => DateTime::createFromFormat("HH", "18"),
"closing_time" => DateTime::createFromFormat("HH", "03"),
]
];
?>
```
The associative array is defined by a comma-separated list of the construct `key => value`. The values can be accessed like this: `$openingTimes[0]["season_start"]`.

We're now also defining the dates in a new way. The string argument to a DateTime constructor (a constructor is a method that's called when an object is created) is a date string. PHP tries to make the best guess at understanding the date from the string, but this is not always possible. This is why we define the hours using the `createFromFormat()` method. This method doesn't act on the data stored in a DateTime class, but is defined in the DateTime class. This is known as a static, and uses the class name plus `::` to call it without accessing the instance (we use `->` to access instance methods, but `::` to access static methods). The createFromFormat class allows to specify exactly how to understand the string we're giving it. In this case, we're only providing the hours, so we need to be aware that the DateTime class has stored an actual date of 6pm 1st January 1970.

Let's try rendering the opening times from this array. As before, replace the list item tags in the opening-times section with this snippet:
```php
<?php
foreach ($openingTimes as $season) {
echo "<li><span class=\"period\">{$season['season_start'].format('F')} - " .
"{$season['season_end'].format('F Y')}</span> " .
"<span class=\"hours\">{$season['season_start'].format('ga')} - " .
"{$season['season_start'].format('ga')}</span></li>";
}
?>
```
The `format()` method uses slightly [different format strings]() to createFromFormat. We enclose the variables in curly braces to more easily distinguish it from normal printables in the string. We've also used single quotes surrounding the key for clarity. Because we've included speech marks inside the string too, we have to _escape_ them, by adding a `\` in front of it.


Loading