diff --git a/php/lesson3/tutorial.md b/php/lesson3/tutorial.md new file mode 100644 index 00000000..2da4bb44 --- /dev/null +++ b/php/lesson3/tutorial.md @@ -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. diff --git a/php/lesson4/example/index.php b/php/lesson4/example/index.php new file mode 100644 index 00000000..2d54c445 --- /dev/null +++ b/php/lesson4/example/index.php @@ -0,0 +1,57 @@ + + + + Wild Owl - The Owl Park + + +
+

Wild Owl - The Owl Park

+
+ +
+
+ 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! +
+
+
+

Top Owls to See

+
+
+
    +
  • Barn Owl
  • +
  • Eastern Grass-Owl
  • +
  • Golden Masked-Owl
  • +
  • Barking Owl
  • +
  • Buffy Fish-Owl
  • +
+
+
+
+
+

Opening Times

+
+
+
    +
  • + May - September 2018 + 6pm - 3am +
  • +
  • + October - April 2018 + 4pm - 1am +
  • +
+
+
+
+ + + diff --git a/php/lesson4/tutorial.md b/php/lesson4/tutorial.md new file mode 100644 index 00000000..e036b3e9 --- /dev/null +++ b/php/lesson4/tutorial.md @@ -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 `` 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 + +``` + +Now in the two locations in the page where we have used the title, i.e. between the `` 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. + + diff --git a/php/using-php/advanced.md b/php/using-php/advanced.md new file mode 100644 index 00000000..3c8d1756 --- /dev/null +++ b/php/using-php/advanced.md @@ -0,0 +1,156 @@ +--- +layout: page +title: Running PHP - Advanced Guide +--- + +## Introduction + +This page covers more advanced styles of PHP setup and installation. PHP has been designed to work primarily in server environments where flexibility and performance are top requirements. The most typical server environment is known as a LAMP stack, where LAMP stands for Linux, Apache, MySQL, PHP, to describe the main software in the stack. It means there are many choices as to how you can install and use it, based on your needs. + +It has two main ways of operating - as a command-line tool, or as part of a web server to serve HTML. The command-line version is designed for running scripts that generally have no user interaction. so it's good for trying out PHP scripting or running a complex algorithm or some data processing. Running as part of a web server environment is when it really shows off with being able to dynamically write web pages. + + +## Online + +There are some online tools for trying out PHP. Unfortunately, a lot of these tools restrict the abilities of PHP, typically stopping it from producing HTML so making them operate like the command-line version. They give you the chance to try the language, but don't let you do the things it was really meant to do. However, below are a few exceptions: + +### Using PHPFiddle + +[PHPFiddle.org](https://phpfiddle.org/) is a simple way to get quick access to PHP, and is able to serve a full web page. It even provides MySQL database access if you set up a login. + +### Using cloud9 + +[cloud9](https://aws.amazon.com/cloud9/) is a full online IDE environment. It is now part of the AWS family of tools, so you need an Amazon AWS login to use it. It is extremely flexible as you can set up almost any kind of environment in it, and be able to use the full suite of AWS services. + +**Warning: This is not a free service. It may be free for a single machine for 1 year, but afterwards will incur +charges. With AWS services, always check what the situation is with pricing.** + + +## Installing on your machine + +Giving you the most flexible options for developing with PHP, but can be a bit more technical to set up. + +### All-in-one Builders + +There are several projects where they have attempted to build everything into one easy package for you to download. These are very convenient to install/uninstall, but can be limited in what they can do, and inflexible to add in those missing features. A few of these include: +* [XAMPP](https://www.apachefriends.org/index.html) - Cross-platform Apache/PHP/MySQL stack +* [WampServer](http://www.wampserver.com/en/) - Windows Apache/PHP/MySQL stack + +### Just the command-line tool + +There is another way of using the command-line tool, which is to use it to generate static HTML. This is an ideal way to serve a site with many people who just read the site, but is limiting for a site that updates frequently. + +#### Saving pages as static HTML + +But you have to save the generated web page to a static file to be able to see it in a web browser. E.g. run your script like this: +``` +php index.php > index.html +``` +If you open your browser and open `index.html`, you should see the generated page. If you make changes, you need to re-run the line above and refresh the page on your browser. + + +### Adding on a web server + +PHP is best when combined with a web server. PHP can integrate with browsers in a number of ways, including: +* SAPI - the web server runs PHP as though it was part of the web server, using its' resources +* CGI - the web server runs PHP as though it was an application on the machine. Not commonly used these days +* Fast CGI - PHP runs as its' own server, and the web server connects to it + +The choice of web servers is also plentiful, the main front runners are: +* Apache - classic stable workhorse of the Internet, very reliable and well documented +* nginx - Very fast web server. Configuration is conceptually different to apache and can gotcha quite easily +* lighthttpd/alpine - A stripped-down version of apache, whose configuration is compatible with apache's + +Unfortunately, you will have to read and follow lots of instructions to get these installed (mileage varies depending on your operating system). Some instructions are provided in the [PHP Installation Guide](https://secure.php.net/manual/en/install.php). + +### Adding on other services + +PHP is very versatile, and has integrations with a great many tools (here is the [full list of extensions and tools](http://php.net/manual/en/funcref.php), each extension has instructions on installing and integrating). Installation is usually in two steps, install the service software, then install and/or configure/enable the PHP extension. The more popular tools are already built-in, such as MySQL access. Often, your operating system can provide packages for performing these steps more easily. + +As an example, the most common service to add is a data service like [MariaDB](https://mariadb.com/downloads/), a variation of MySQL. This just needs to be installed and configured, then PHP is already enabled to access MySQL databases, so you go straight to accessing it in your scripts. + + +## Using Docker + +[Docker](https://www.docker.com/) is a tool for running virtualized environments that contain software and tools, without disrupting your own machine. Docker can be fiddly, but provides the most flexibility for easily setting up and chaining other software and tools together. + +Here is the [Docker installation guide](https://docs.docker.com/install/). We advise that you install Docker and ideally download the base images (e.g. with `docker pull php:apache`) you are using before attending a codebar session to avoid problems with wifi and large downloads. + +### Simple PHP and web server + +The absolute simplest way to get PHP running is from the [official PHP builds](https://hub.docker.com/_/php/) by the Docker team: +``` +docker run --rm -p 8080:80 -d -v `pwd`:/var/www/html php:apache +``` +This starts a web server running on http://localhost:8080/, that is looking at the current directory for its' webroot. + +### More advanced stack + +Docker has a great feature called *docker-compose* that's able to chain multiple containers together to make a complete stack. But for this PHP set up, this usually means altering the configuration of the PHP docker box to support additional features. + +Here is an intro to how you might go about doing this by adding on a MariaDB container, making Docker simulate a LAMP stack. + +Create a file called 'Dockerfile'. This should contain the following: +``` +FROM php:apache +RUN docker-php-ext-install mysqli +``` + +Then run the command: +``` +docker build -t php-with-mysql . +``` + +This has built a container called `php-with-mysql` (`-t` is for tag) that is the vanilla PHP/Apache build, but with the mysqli extension library installed. + +Next, create a file called 'docker-compose.yml'. +``` +version: "3" +services: + app_server: + build: + context: . + ports: + - "8080:80" + networks: + - webnet + volumes: + - .:/var/www/html + mysql_server: + image: mariadb:latest + environment: + MYSQL_ROOT_PASSWORD: my-secret-pw + networks: + - webnet + +networks: + webnet: +``` +If you now build the stack with (first time you run this it will need to do some downloads that may be quite large) +``` +docker-compose build +``` +You can then start it with +``` +docker-compose run +``` +This may leave the server running in the terminal you've used. You can now access the database by writing a script like: +``` +$mysql = new MySQLi('mysql-server', 'root', 'my-server-pw'); +$results = $mysql->query("SHOW DATABASES"); +foreach ($results as $result) { + echo "<p>{$result->name}</p>"; +} +``` + +## Using VMWare/Virtualbox/Vagrant + +If you are used to using these tools, it is also possible to install a LAMP stack in a virtual machine. The advantage of this technique is that you get complete control of the machine, to install whatever tools you need. There are pre-built images that are already configured and require minimal effort to get up and running. Some resources to look at are: + +### Vagrant + +The best way to find vagrant boxes is to use their [box search facility](https://app.vagrantup.com/boxes/search) and search for "LAMP" + +### Virtualbox/VMWare + +The recommended option is to use the [official ubuntu server build](https://www.osboxes.org/ubuntu-server/). This may require a little set up once the main install is running, but gives you the option of building the set up you want. There are plenty of help and information for ubuntu/debian builds. diff --git a/php/using-php/simple.md b/php/using-php/simple.md index dd7dc565..65ceb1a8 100644 --- a/php/using-php/simple.md +++ b/php/using-php/simple.md @@ -82,3 +82,10 @@ $ php -S 0.0.0.0:8080 * `-S` means built-in WebServer * `0.0.0.0` is the IP that the WebServer should listen on. By using `0` it will listen on everything - fine for development * `:8080` sets the port to listen on - fine for development but in production the default port is `80` and therefore not required when accessing a URL. The colon character is used after a hostname or IP address to indicate that you wish to specify the port number on that host + + +## Advanced setups + +PHP has been designed to work primarily in integrated server environments (also known as LAMP stacks, where LAMP stands for Linux, Apache, MySQL, PHP) where flexibility and performance are top requirements. + +If you are more advanced with your programming abilities, you may wish to also look at this [advanced guide](advanced.html). This goes into more detail about using PHP in other environments such as docker and virtual machines to create an environment that's closer to a production environment.