Lesson Weekend

Lesson goals:

  • Learn to add methods to your objects
  • Learn about $this variable

What are we going to learn here and why?

We've learned about how objects can help us store and organize related information by storing it in properties. But the real power of objects is that in addition to holding information, they can also do things with that information.

The idea of objects taking actions.

Let's look abstractly at our Car class from last lesson. A Car has several properties - a price, a make and model, the number of miles on it, etc. But this does not really encompass the point of a Car, which is that it drives. This is an action that we can tell the Car object to take. We can define an action to be part of a class by creating what we call a method. Instead of calling a method like a normal function, we say that we call a method on an object, meaning we are telling our object to do something. Telling a car to drive is not a method we can implement in a web app, but the idea is that we can now tell our objects to do things by calling methods on them. We could create a method that makes the car tell us if it is worth buying or not based on its price and mileage properties. We could make the car tell us how much gas it has left. A method is essentially a function that is part of an object.

To see how this works, let's make a little geometry tool whose job is to tell us if a rectangle is a square or not. We'll make a Rectangle class with 2 properties: its length and its width. Then we can create a method where we tell the Rectangle object to look into its properties and tell us if it is a square or not.

First, let's make a form where the user can enter a length and a width. Put this into a file called rectangle_form.html in your document root.

rectangle_form.html
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <title>Make a rectangle!</title>
</head>
<body>
    <div class="container">
        <h1>Geometry Checker</h1>
        <p>Enter the dimensions of your rectangle to see if it's a square.</p>
        <form action="Rectangle.php">
            <div class="form-group">
              <label for="length">Enter the length:</label>
              <input id="length" name="length" class="form-control" type="number">
            </div>
            <div class="form-group">
              <label for="width">Enter the width:</label>
              <input id="width" name="width" class="form-control" type="number">
            </div>
            <button type="submit" class="btn-success">Create</button>
        </form>
    </div>
</body>
</html>

Now, let's make the receiving file, Rectangle.php.

Rectangle.php
<?php 
    class Rectangle 
    {
        public $length;
        public $width;

        function isSquare()
        {
            if($this->length == $this->width) {
                return true;
            } else {
                return false;
            }
        }
    }

    $my_rectangle = new Rectangle();
    $my_rectangle->length = $_GET["length"];
    $my_rectangle->width = $_GET["width"];
?>
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
    <title>Make a rectangle!</title>
</head>
<body>
    <div class="container">
    <?php 
        if ($my_rectangle->isSquare()) {
            echo "<h1>Congratulations! You made a square!</h1>";
        } else {
            echo "<h1>Sorry! This isn't a square.</h1>";
        }
    ?>
    </div>
</body>
</html>

Let's look at it in the browser

If you start your server and run rectangle_form.html in the browser, you can type in a length and a width and then after you hit the submit button, if they are equal, the page will tell you "Congratulations! You made a square!". If they are not equal, the page will say "Sorry! This isn't a square." Let's walk through this and see what's happening.

Declare class with method.

First, we declare the Rectangle class, which only needs two properties: $length and $width. Then, we declare our method, called isSquare. It checks to see if the object's length is equal to its width, and if it is, it returns true. Else, it returns false.

Instantiate object and call its method

After the class declaration, we instantiate a new object of class Rectangle and store it in the variable $my_rectangle. Next, we set the object's properties equal to the values entered into our form for length and width. Finally, we call our new method as the condition of an if statement down in the body of our HTML. If $my_rectangle->isSquare() returns true, then a set of <h1> tags is printed with the message "Congratulations! You made a square!". If it is false, then you have not made a square, so we print "Sorry! This isn't a square."

More detail on how to create a method: Styling rules of methods.

Although the method declaration is within the curly brackets of the class declaration, it is styled exactly like a function definition. Use the keyword function, followed by a space, then a name for the method, and then a pair of parentheses for any arguments. Then skip to the next line and add the opening and closing curly brackets on separate lines with the method code between them. Methods should also be named like functions: capitalize the first letter of each word, except for the first one, and do not use spaces or underscores.

The method uses the $this variable to get the property value to print.

In this method, we are using a new word to get the value of the $length and $width properties. It's a variable called $this. $this is basically an object we can use within a method declaration to represent the current instance of the class. We can use the object operator on $this to fetch the values of the object's properties, the same way we would fetch the property values of any object. The code $this->length; means "Look inside of the current object, which will be $my_rectangle, for a property called $length, and return its value."

Add a method to calculate area

Let's write a method to calculate the area of the Rectangle object by multiplying its $length and $width. Add this method to your class declaration in Rectangle.php:

Rectangle.php
function getArea()
{
    return $this->length * $this->width;
}

When getArea is called on a Rectangle object, it will look inside of itself for the values of its properties $length and $width, multiply them, and then return the result.

Now, let's modify our HTML on Rectangle.php to display the area. Add this line right after the if statement inside of the <?php ?> tags in the body of the HTML.

Rectangle.php
echo "<p>The area is: " . $my_rectangle->getArea() . "</p>";

Now if we reload the browser, it will display the product of the length and width values entered into the form.

Using the object operator for both properties and methods

As you can see, the object operator is used to find both properties and methods inside of an object. Whether we are writing a class declaration and using $this as our object, or a variable we have created to hold the object, the formatting is the same.

$this->length;
$this->width;
$my_rectangle->length;
$my_rectangle->width;
$this->isSquare();
$this->getArea();
$my_rectangle->isSquare();
$my_rectangle->getArea();

The only difference is that when you're using it to call a method, you must use parentheses at the end of the method name (with no spaces before them). And of course, remember to end the line with a semicolon.

$ rules. Here are the complete rules to keep in mind involving $.

  • $ is always used at the beginning of a variable name, whether that variable is an object, a word, a number, or any other type of data. For example, $my_rectangle or $some_number.
  • $ is always used when you are declaring a property inside of an object: public $property_name;
  • When accessing an attribute contained within a PHP object only use $ at the beginning of the statement. Do not include it after the object operator. For example: $my_rectangle->length = 5; or echo $my_rectangle->length; or $my_rectangle->getArea();

Example 2: Expand on cars - using method with arguments

Let's revisit our car dealership and see if we can improve it by adding methods to the Car class. Here is what your car dealership files should look like right now:

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>

Then we have the answering file, which holds our class declaration, called Car.php.

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);

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

<!DOCTYPE html>
<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>

The Car class has 3 properties: its make/model, its price, number of miles. Then, we instantiate 4 Car objects, set their properties, and put them in an array called $cars. Next, we create an empty array called $cars_matching_search, which will hold all the cars matching the user's search parameter so that we can display them on the page. Then, we use a loop to fill that array. It checks to see if the price on each Car object is less than the price specified in the form, and if they are, then add the Car to $cars_matching_search to display. Finally, we use another loop in the HTML to show each chosen Car's properties.

Let's create a method called worthBuying which compares the Car's price to the value entered into the form. Add this to the Car class declaration in Car.php:

Car.php
function worthBuying($max_price)
{
    return $this->price < $max_price;
}

Calling methods with arguments

This method is called with an argument - the price chosen by the user which we are comparing to the Car object's price. Arguments in methods are treated exactly the same way as in regular functions. When we call the method worthBuying, we will pass in the price as an argument, which will be assigned to the variable $max_price. The variable that takes on the value of an argument is called a parameter. This parameter can then be used in our code just like a normal variable.

This method will return the result of the comparison between the price argument and the Car's price - true if the car is less expensive and therefore worth buying, or false if it is more expensive. Method parameters like $max_price must be named using the $, with lowercase letters and all words separated by underscores.

Now we can simplify the loop we run assigning cars to the $cars_matching_search array.

So, instead of this:

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

We can write this:

Car.php
foreach ($cars as $car) {
    if ($car->worthBuying($_GET['price'])) {
        array_push($cars_matching_search, $car);
    }
}

For each Car, we call the worthBuying method, passing it a value for price that we get from our form. If it returns true, then the Car gets put into the array we use to display. If it's false, we do nothing.

It's a lot more readable, and a lot easier to modify. Say that we want to change our site to show Cars that are cheaper than the chosen price, but Cars that cost up to $100 over the chosen price are close enough that they should be shown too. If this was a real website, it might be really difficult to dig through all the code and find that one loop searching through the Car objects. Instead we can just go directly to the class declaration and change the method:

Car.php
function worthBuying($max_price)
{
    return $this->price < ($max_price + 100);
}

We can define an action to be part of a class by creating a method. A method is essentially a function that is part of an object. Instead of calling a method like a normal function, we say that we call a method on an object, meaning we are telling our object to do something.

Declaring a method:

class MyClassName
{
    public $a_property;
    function myFunctionName()
    {
        return $this->a_property;
    }
}

Use $this to access the current object from inside of its own methods.

The object operator is used to call methods too. Just add parentheses.

$my_thing = new MyClassName;
$my_thing->myFunctionName();

We can pass arguments to methods just like we do with functions that are outside of objects.

class MyClassName
{
    function myNewFunctionName($parameter, $another_parameter)
    {
        return $parameter . " and " . $another_parameter;
    }
}

$my_thing = new MyClassName;
$argument1 = "A number";
$argument2 = "A different number";
echo $my_thing->myNewFunctionName($argument1, $argument2);

The variables that we declare to hold the argument data are called parameters. $parameter is set equal to $argument1 and $another_parameter is set to $argument2. The above will print "A number and A different number".

$ rules

  • USE IT: At the beginning of all variable names, including objects, and when declaring properties.
  • DON'T USE IT: With -> when accessing an object's properties or methods.