Lesson Weekend

Lesson goals:

  • Learn about objects, properties, classes
  • Learn about object instantiation, and the object operator

Intro: Why do we need objects?

We've worked with two types of collections for storing data: numerically indexed arrays and associative arrays. But say we have an associative array that we're using as an address book. We have 500 entries in it, where each one is a phone number stored with a name. What if we want to store a street address as well as the phone number? And maybe a picture too? To do that we need to make something called an object.

What is an object? It stores properties.

Objects do a lot of things, but the simplest thing that they do is store information. Let's make a Contact object for our address book. Instead of just tying a phone number to a name, we're going to say that a Contact object includes a name, a phone number, and an address. These pieces of information are called properties and they are just another kind of variable. Type this into a text file between <?php ?> tags and save it to your document root as Contact.php.

Contact.php
class Contact
{
    public $name;
    public $phone;
    public $address;
}

What is a class?

There are 2 unfamiliar keywords here: public and class. For now, ignore the word public because the important keyword is class. A class is like a classification for your objects. Similarly to the way that all words enclosed in quotes are called strings and all numbers with a decimal point are called floats, each object created from this class is called a Contact.

What is a class declaration?

When we use the keyword class, as we did above, we are declaring the class - explaining how it is going to work before we use it - just like we do when we declare functions. We are explaining that each object of the class Contact will hold 3 properties: a name, a phone number and an address. Let's create some contacts with different names, phone numbers and addresses. Add these lines to your Contact.php file.

Contact.php
$hendrix = new Contact();
$hendrix->name = "Jimi Hendrix";
$hendrix->phone = "503-826-9371";
$hendrix->address = "208 SW 5th st. Portland, OR 97204";

$elvis = new Contact();
$elvis->name = "Elvis Presley";
$elvis->phone = "617-356-3571";
$elvis->address = "Graceland";

$einstein = new Contact();
$einstein->name = "Albert Einstein";
$einstein->phone = "415-738-4935";
$einstein->address = "3718 MLK blvd. Oakland, CA 94609";

Instantiation: You can store objects in variables and then use them.

Each Contact object can be stored in a variable, just like any other kind of data. When you create an object it is called instantiation because that object is called an instance of its class. Each individual person we created above ($hendrix, $elvis, $einstein) is an instance of the class Contact.

Object operator

To store a value in a property of an object, you use a new operator: ->, called the object operator. It means "look inside of the object to the left of this symbol for the name to the right of this symbol". So when we say $hendrix->name = "Jimi Hendrix"; We are saying "Find the object stored inside the variable $hendrix, then look inside that object for a property called name. Then set the value of that property equal to the right side of the equals sign: the string "Jimi Hendrix."

What do we do with our objects, now that we've created them?

Now we have 3 Contact objects. Let's make an address book website for them and print all the contact details for each person out. Here's what the whole Contact.php page looks like now:

Contact.php
<?php 

    class Contact
    {
        public $name;
        public $phone;
        public $address;
    }

    $hendrix = new Contact();
    $hendrix->name = "Jimi Hendrix";
    $hendrix->phone = "503-826-9371";
    $hendrix->address = "208 SW 5th st. Portland, OR 97204";

    $elvis = new Contact();
    $elvis->name = "Elvis Presley";
    $elvis->phone = "617-356-3571";
    $elvis->address = "Graceland";

    $einstein = new Contact();
    $einstein->name = "Albert Einstein";
    $einstein->phone = "415-738-4935";
    $einstein->address = "3718 MLK blvd. Oakland, CA 94609";

    $address_book = array($hendrix, $elvis, $einstein);
?>
<!DOCTYPE html>
<html>
    <link rel="stylesheet" type="text/css" href="styles.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <title>Address Book</title>
</head>
<body>
    <div class="container">
        <h1>Address Book</h1>
        <ul>
            <?php 
                foreach ($address_book as $contact) {
                    echo "<li>";
                    echo $contact->name;
                    echo "<ul>";
                    echo "<li> $contact->phone </li>";
                    echo "<li> $contact->address </li>";
                    echo "</ul>";
                    echo "</li>";
                }
            ?>
        </ul>
    </div>
</body>
</html>

In the last line of our PHP code we store our 3 objects in a numerically indexed array: $address_book = array($hendrix, $elvis, $einstein); Then down in the HTML body we can use a foreach loop to print the information stored in each object. Our loop says "take each object in address_book and temporarily store it in the variable $contact. Then, we can use the object operator to get the value of the $name property for the current object the same way we would if we were setting it to something. So echo $contact->name; means "Look inside of the current object stored in $contact. Get the property called name and return its value. Then print it out with echo." Lastly, we print some HTML tags to format the object data.

Add a property to a class to store the path to an image.

Let's add another property for our Contact object - an image path so we can display a photo of each of our contacts. First we have to change the class declaration.

Contact.php
class Contact
{
    public $name;
    public $phone;
    public $address;
    public $image_path;
}

Syntax of property declaration.

To declare a property, it is exactly the same as declaring any other variable. Just put it inside of those curly brackets and put the word public to the left of the property name. Like variables, property names should use the $ at the beginning, use all lower case letters, and separate words with underscores.

Then, set the property value when we instantiate each Contact object.

Contact.php
...
$hendrix->image_path = "images/hendrix.jpg";
...
$elvis->image_path = "images/elvis.jpg";
...
$einstein->image_path = "images/einstein.jpg";

Rule of the $

It's important to note that when we are using the object operator to get or set properties, as we do above, we don't use $ to refer to the property name. Properties are defined with the $ before the name, just like a normal variable, but when you use them you only need to use $ before the object variable. For example, we don't look up a Contact's phone number by saying $contact->$phone. Instead, we say $contact->phone. This is because the variable we are really using is $contact. The phone property is just a part of the $contact object.

How do we make these images display?

To make these paths actually load images on your machine, download an image for each contact and put them all in an images folder in your document root. Name the image files as shown above, or if you name them something different, be sure to make the path match the actual file name. Now, to display these images we need to modify our loop. Let's put each picture in underneath the person's name. So, we add a line to print an <img> tag as the first list item in the unordered list for contact details inside the loop:

Contact.php
<ul>
    <?php 
        foreach ($address_book as $contact) {
            echo "<li>";
            echo $contact->name;
            echo "<ul>";
            echo "<li><img src='$contact->image_path'></li>";
            echo "<li> $contact->phone </li>";
            echo "<li> $contact->address </li>";
            echo "</ul>";
            echo "</li>";
        }
    ?>
</ul>

This will print out an <img> tag for each Contact object, and the value of the Contact's image_path property is plugged into the src attribute of the <img> tag, so we can now see each Contact object's image with its other properties in our address book. When setting attributes or classes on HTML tags like we did on the <img> tag, be sure to use single quote inside of echo's double quotes. This makes sure that echo doesn't think you are ending the string too early. We wouldn't want to print "<li><img src=". We want to print <li><img src='$contact->image_path'></li>.

Look how useful objects are!

Now, you might be thinking - what's the point? We could have just made a bunch of variables for all the names and phone numbers. Conceptual organization aside, we would not be able to use an array of our objects in a loop! We would have had to write out an echo command for each property in every object. Let's add a few more contacts to our address book to see how useful this is. This time we don't need to modify our class, or our loop! All we need to do is instantiate some more objects and add them to our array. So, add these lines to the end of the PHP code before the HTML, and modify the line adding all the objects to the array.

Contact.php
$marie = new Contact();
$marie->name = "Marie Curie";
$marie->phone = "432-154-3523";
$marie->address = "1911 West 1st Ave. Fictional, OR 44556";
$marie->image_path = "images/marie.jpg";

$janis = new Contact();
$janis->name = "Janis Joplin";
$janis->phone = "415-124-2445";
$janis->address = "Haight Ashbury, San Francisco, CA 94117";
$janis->image_path = "images/janis.jpg";

$address_book = array($hendrix, $elvis, $einstein, $marie, $janis);

Now, if you reload your page (and download a couple more images named marie.jpg and janis.jpg to put in your images folder) then you will see 2 more Contacts appear on your website!

Example 2: Cars - more on the difference between objects and classes

Let's do another example. Congrats, you now own a used car dealership. On your website, you need to display each car on your lot with its exact make and model, its price, and the number of miles on it. So let's make a Car class, and instantiate some Car objects. Remember that the idea of a Car as "a transportation device with a price and a certain amount of miles" is the class. An "individual BMW with a particular license plate number" is an object that is an instance of the class Car.

Put this in a new file called Car.php in your document root.

Car.php
<?php
class Car
{
    public $make_model;
    public $price;
    public $miles;
}


$porsche = new Car();
$porsche->make_model = "2014 Porsche 911";
$porsche->price = 114991;
$porsche->miles = 7864;

$ford = new Car();
$ford->make_model = "2011 Ford F450";
$ford->price = 55995;
$ford->miles = 14241;

$lexus = new Car();
$lexus->make_model = "2013 Lexus RX 350";
$lexus->price = 44700;
$lexus->miles = 20000;

$mercedes = new Car();
$mercedes->make_model = "Mercedes Benz CLS550";
$mercedes->price = 39900;
$mercedes->miles = 37979;

$cars = array($porsche, $ford, $lexus, $mercedes);
?>

Syntax of class declarations.

Now that you understand the basics, let's make sure that we know the style rules of classes. To declare a class, use the keyword class first, followed by a name. The name should have each word capitalized and contain no spaces or underscores. It should look like a function name, except the first word of a function name should not be capitalized. Then, just like a function declaration, put in opening and closing curly brackets on the first and last line of the declaration.

Now, back to our car dealership. Let's display these cars in a list with all their info. Here's the HTML. Add this to the bottom of Car.php:

Car.php
<!DOCTYPE html>
<html>
<head>
    <title>Your Car Dealership's Homepage</title>
</head>
<body>
    <h1>Your Car Dealership</h1>
    <ul>
        <?php 
            foreach ($cars as $car) {
                echo "<li> $car->make_model </li>";
                echo "<ul>";
                    echo "<li> $$car->price </li>";
                    echo "<li> Miles: $car->miles </li>";
                echo "</ul>";
            }
        ?>
    </ul>
</body>
</html>

Now let's build a form for your car dealership allowing users to search for cars under a certain price. Put this into a new file called car_form.html in your document root.

car_form.html
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <title>Find a Car</title>
</head>
<body>
    <div class="container">
        <h1>Find a Car!</h1>
        <form action="Car.php">
            <div class="form-group">
                <label for="price">Enter Maximum Price:</label>
                <input id="price" name="price" class="form-control" type="number">
            </div>
            <button type="submit" class="btn-success">Submit</button>
        </form>
    </div>
</body>
</html>

The user enters a number for the maximum price they are looking for, then the form is submitted and it calls our Car.php file. Let's modify that so that it only shows cars that match the search parameter defined by our form. Add this to the end of the PHP section above the HTML body.

Car.php
$cars_matching_search = array();
foreach ($cars as $car) {
    if ($car->price < $_GET["price"]) {
        array_push($cars_matching_search, $car);
    }
}

First we make a new array to hold all the Car objects we find which are under the given price. Then we loop through all the Car objects, which are stored in the $cars array. For each object in the array, we store it in the variable $car and then check to see if its price property is less than the maximum price submitted by the user. If it is cheaper than the price from the form, then add the Car object to the new array $cars_matching_search. At the end of the loop, we will have an array of Car objects matching the search, and we can display it in the HTML by just using this array in our loop instead of $cars.

Car.php
<html>
<head>
    <title>Your Car Dealership's Homepage</title>
</head>
<body>
    <h1>Your Car Dealership</h1>
    <ul>
        <?php 
            foreach ($cars_matching_search as $car) {
                echo "<li> $car->make_model </li>";
                echo "<ul>";
                    echo "<li> $$car->price </li>";
                    echo "<li> Miles: $car->miles </li>";
                echo "</ul>";
            }
        ?>
    </ul>
</body>
</html>

Objects store information. Each piece of information is a property. They are variables. A class is a classification for an object, for example, you could have a class called Bicycle and a particular object of that class that is my violet bicycle or your red bicycle. A class declaration is a blueprint explaining how each object of that class will behave, like a function declaration - it defines which properties the object will hold.

class Contact
{
    public $name;
    public $phone;
    public $address;
}

When you create an object it is called instantiation because that object is called an instance of its class. You can get or set the value of an object's properties using the object operator: ->

//instantiate
$hendrix = new Contact();

//set properties
$hendrix->name = "Jimi Hendrix";
$hendrix->phone = "503-826-9371";
$hendrix->address = "208 SW 5th st. Portland, OR 97204";

//get properties
echo $hendrix->name; //Prints "Jimi Hendrix"

$ Rule: When declaring properties, use the $. When accessing them inside of an object with -> don't. $hendrix->name