File Separation

Piecing Together Masterpieces with Included Files

Include, Require, Require Once, and Include Once. You might have seen these at the top of a file in someone else’s code, but what does each one of them mean? We’ll take a look at each later. For now, we’re just trying to split our file since it was quite huge last time.

https://blog.devgenius.io/php-p54-inheritance-chain-3cb62edcb373

We want to start off slowly and separate each class into its own individual file. Each of those files are then included whenever necessary. For the most part, each of these keywords do the same function, which is to include a file:

  • require
  • require_once
  • include
  • include_once

Some call specific types of errors upon failure and others check to see if the file has already been included. We’re going to be using the require_once helper function throughout the remainder of this article.

When we look at our existing code, you can see that it has 6 different classes: Vehicle, Car, Animal, Mammal, Dog, and GermanShepherd. Each one of these classes will have its own file and will be included where necessary.

The first class is the Vehicle class. We’ll create a new file called Vehicle.php and move our class there. We’re not going to go through subdirectories in this article.

<?php
class Vehicle {
    protected string $color;
    protected string $make;
    protected string $model;
    protected int $year;
    protected float $exterior_height;
    protected float $exterior_width;
    protected float $exterior_length;
    protected string $exterior_um;
    protected float $weight;
    protected string $weight_um;

    /**
     * @return string
     */
    public function getColor(): string
    {
        return $this->color;
    }

    /**
     * @param string $color
     */
    public function setColor(string $color): void
    {
        $this->color = $color;
    }

    /**
     * @return string
     */
    public function getMake(): string
    {
        return $this->make;
    }

    /**
     * @param string $make
     */
    public function setMake(string $make): void
    {
        $this->make = $make;
    }

    /**
     * @return string
     */
    public function getModel(): string
    {
        return $this->model;
    }

    /**
     * @param string $model
     */
    public function setModel(string $model): void
    {
        $this->model = $model;
    }

    /**
     * @return int
     */
    public function getYear(): int
    {
        return $this->year;
    }

    /**
     * @param int $year
     */
    public function setYear(int $year): void
    {
        if ( $year < 0 ) {
            echo "Not a valid year";
            return;
        }

        $this->year = $year;
    }

    /**
     * @return float
     */
    public function getExteriorHeight(): float
    {
        return $this->exterior_height;
    }

    /**
     * @param float $exterior_height
     */
    public function setExteriorHeight(float $exterior_height): void
    {
        $this->exterior_height = $exterior_height;
    }

    /**
     * @return float
     */
    public function getExteriorWidth(): float
    {
        return $this->exterior_width;
    }

    /**
     * @param float $exterior_width
     */
    public function setExteriorWidth(float $exterior_width): void
    {
        $this->exterior_width = $exterior_width;
    }

    /**
     * @return float
     */
    public function getExteriorLength(): float
    {
        return $this->exterior_length;
    }

    /**
     * @param float $exterior_length
     */
    public function setExteriorLength(float $exterior_length): void
    {
        $this->exterior_length = $exterior_length;
    }

    /**
     * @return string
     */
    public function getExteriorUm(): string
    {
        return $this->exterior_um;
    }

    /**
     * @param string $exterior_um
     */
    public function setExteriorUm(string $exterior_um): void
    {
        $this->exterior_um = $exterior_um;
    }

    /**
     * @return float
     */
    public function getWeight(): float
    {
        return $this->weight;
    }

    /**
     * @param float $weight
     */
    public function setWeight(float $weight): void
    {
        $this->weight = $weight;
    }

    /**
     * @return string
     */
    public function getWeightUm(): string
    {
        return $this->weight_um;
    }

    /**
     * @param string $weight_um
     */
    public function setWeightUm(string $weight_um): void
    {
        $this->weight_um = $weight_um;
    }

    protected function get_make_and_model(): string
    {
        return $this->make . " " . $this->model;
    }
}

Our Vehicle.php file now only contains the Vehicle class. Next, we’ll create the Car.php file and move our Car class there.

The main difference between the Car class and the Vehicle class is that the Car class inherits from the Vehicle class. Since they’re in separate files now, the Car class won’t have access to the Vehicle class. In other words, PHP won’t know how to extend Vehicle.

How do we tell where the Vehicle is coming from in the Car class? This is where we require the file to make sure that the Car class can see the Vehicle class. As long as the Vehicle.php and Car.php files are in the same directory, you’ll be able to add the following code to the top of your Car.php file:

require_once(‘file_name’);

require_once(‘Vehicle.php’);

The require_once statement is added before the class declaration. You usually want to place it right after the opening php tag, <?php.

<?php
require_once('Vehicle.php');

class Car extends Vehicle
{

    const HAS_HEADLIGHTS = true;
    const HAS_TAIL_LIGHTS = true;
    const HAS_TURN_SIGNALS = true;

    private int $fuel_type;
    private int $hp;
    private int $tq;
    private string $transmission;
    private string $vehicle_type;
    private bool $car_on;

    public function __construct(int $year,
                                string $make,
                                string $model,
                                string $color = "",
                                int $fuel_type = 93,
                                int $hp = -1,
                                int $tq = -1,
                                string $transmission = "5 Speed Manual",
                                string $vehicle_type = "",
                                float $exterior_height = -1,
                                float $exterior_width = -1,
                                float $exterior_length = -1,
                                string $exterior_um = "in",
                                float $weight = -1,
                                string $weight_um = "lbs",
                                bool $car_on = false
    )
    {
        $this->year = $year;
        $this->make = $make;
        $this->model = $model;
        $this->color = $color;
        $this->fuel_type = $fuel_type;
        $this->hp = $hp;
        $this->tq = $tq;
        $this->transmission = $transmission;
        $this->vehicle_type = $vehicle_type;
        $this->exterior_height = $exterior_height;
        $this->exterior_width = $exterior_width;
        $this->exterior_length = $exterior_length;
        $this->exterior_um = $exterior_um;
        $this->weight = $weight;
        $this->weight_um = $weight_um;
        $this->car_on = $car_on;

        echo "Connection Successfully Established";
    }

    /**
     * @return int
     */
    public function getFuelType(): int
    {
        return $this->fuel_type;
    }

    /**
     * @param int $fuel_type
     */
    public function setFuelType(int $fuel_type): void
    {
        $this->fuel_type = $fuel_type;
    }

    /**
     * @return int
     */
    public function getHp(): int
    {
        return $this->hp;
    }

    /**
     * @param int $hp
     */
    public function setHp(int $hp): void
    {
        $this->hp = $hp;
    }

    /**
     * @return int
     */
    public function getTq(): int
    {
        return $this->tq;
    }

    /**
     * @param int $tq
     */
    public function setTq(int $tq): void
    {
        $this->tq = $tq;
    }

    /**
     * @return string
     */
    public function getTransmission(): string
    {
        return $this->transmission;
    }

    /**
     * @param string $transmission
     */
    public function setTransmission(string $transmission): void
    {
        $this->transmission = $transmission;
    }

    /**
     * @return string
     */
    public function getVehicleType(): string
    {
        return $this->vehicle_type;
    }

    /**
     * @param string $vehicle_type
     */
    public function setVehicleType(string $vehicle_type): void
    {
        $this->vehicle_type = $vehicle_type;
    }

    /**
     * @return bool
     */
    public function isCarOn(): bool
    {
        return $this->car_on;
    }

    /**
     * @param bool $car_on
     */
    public function setCarOn(bool $car_on): void
    {
        $this->car_on = $car_on;
    }

    public function turnOn(): string
    {
        if ($this->car_on) {
            return "The " . $this->get_make_and_model() . " is already on.";
        }

        $this->car_on = true;
        return $this->get_make_and_model() . " has been turned on.";
    }

    public function turnOff(): string
    {
        if ($this->car_on) {
            $this->car_on = false;
            return "The " . $this->get_make_and_model() . " has been turned off.";
        }

        return "The " . $this->get_make_and_model() . " is already off.";
    }

    public function drive(): string
    {
        if ($this->car_on) {
            return "I'm driving";
        } else {
            return "You gotta turn me on";
        }
    }

    public function get_car_details(): array
    {
        return [
            "year" => $this->year,
            "make" => $this->make,
            "model" => $this->model,
            "color" => $this->color,
            "fuel_type" => $this->fuel_type,
            "hp" => $this->hp,
            "torque" => $this->tq,
            "transmission" => $this->transmission
        ];
    }

    public function __destruct()
    {
        echo "Connection Successfully Closed";
    }
}

When PHP looks at the Car class now, it will know how to extend the Vehicle class since the Vehicle class is included at the top of the file.

Next, we’ll grab our Animal class and move it to Animal.php. Since it doesn’t extend anything, that completes the move.

<?php
class Animal {
    const HAS_HEART = true;

    protected $dob;
    protected $kingdom = "Animalia";
    protected $phylum;
    protected $class;
    protected $order;
    protected $family;
    protected $genus;
    protected $species;
    protected $subspecies;

    /**
     * @return string
     */
    public function getDob(): string
    {
        return $this->dob;
    }

    /**
     * @param string $dob
     */
    public function setDob(string $dob): void
    {
        $this->dob = $dob;
    }

    /**
     * @return string
     */
    public function getKingdom(): string
    {
        return $this->kingdom;
    }

    /**
     * @return mixed
     */
    public function getPhylum()
    {
        return $this->phylum;
    }

    /**
     * @param mixed $phylum
     */
    public function setPhylum($phylum): void
    {
        $this->phylum = $phylum;
    }

    /**
     * @return mixed
     */
    public function getClass()
    {
        return $this->class;
    }

    /**
     * @param mixed $class
     */
    public function setClass($class): void
    {
        $this->class = $class;
    }

    /**
     * @return mixed
     */
    public function getOrder()
    {
        return $this->order;
    }

    /**
     * @param mixed $order
     */
    public function setOrder($order): void
    {
        $this->order = $order;
    }

    /**
     * @return mixed
     */
    public function getFamily()
    {
        return $this->family;
    }

    /**
     * @param mixed $family
     */
    public function setFamily($family): void
    {
        $this->family = $family;
    }

    /**
     * @return mixed
     */
    public function getGenus()
    {
        return $this->genus;
    }

    /**
     * @param mixed $genus
     */
    public function setGenus($genus): void
    {
        $this->genus = $genus;
    }

    /**
     * @return mixed
     */
    public function getSpecies()
    {
        return $this->species;
    }

    /**
     * @param mixed $species
     */
    public function setSpecies($species): void
    {
        $this->species = $species;
    }

    /**
     * @return mixed
     */
    public function getSubspecies()
    {
        return $this->subspecies;
    }

    /**
     * @param mixed $subspecies
     */
    public function setSubspecies($subspecies): void
    {
        $this->subspecies = $subspecies;
    }

    public function sleep(int $energy_level = 100)
    {
        if ($energy_level < 40) {
            echo "I'm sleeping";
        } else {
            echo "I don't want to sleep";
        }
    }
}

Next is the Mammal class. Let’s create the Mammal.php file and move the Mammal class into it. Since Mammal extends Animal, we have to require_once our Animal.php file.

<?php
require_once("Animal.php");

class Mammal extends Animal {

    protected $eye_color;

    /**
     * @return string
     */
    public function getEyeColor(): string
    {
        return $this->eye_color;
    }

    /**
     * @param string $eye_color
     */
    public function setEyeColor(string $eye_color): void
    {
        $this->eye_color = $eye_color;
    }

    public function walk(): string
    {
        return "I'm a walking Mammal";
    }
}

Moving down, the next class is Dog. The Dog class will be placed in the Dog.php file. If you’re wondering whether the files need to be named the same as the class, the answer is no. In certain frameworks, however, that is a requirement. We’ll get into that once we start discussing PHP frameworks.

The Dog class extends Mammal, so we’ll need to include the Mammal.php file.

<?php
require_once('Mammal.php');

class Dog extends Mammal
{
    const HAS_TAIL = true;

    protected $does_shed = true;
    protected $breed;
    protected $fur_color;

    /**
     * @return bool
     */
    public function isDoesShed(): bool
    {
        return $this->does_shed;
    }

    /**
     * @param bool $does_shed
     */
    public function setDoesShed(bool $does_shed): void
    {
        $this->does_shed = $does_shed;
    }

    /**
     * @return string
     */
    public function getFurColor(): string
    {
        return $this->fur_color;
    }

    /**
     * @param string $fur_color
     */
    public function setFurColor(string $fur_color): void
    {
        $this->fur_color = $fur_color;
    }

    public function get_scientific_classification(): array
    {
        return [
            "kingdom" => $this->kingdom,
            "phylum" => $this->phylum,
            "class" => $this->class,
            "order" => $this->order,
            "family" => $this->family,
            "genus" => $this->genus,
            "species" => $this->species,
            "subspecies" => $this->subspecies,
            "breed" => $this->breed
        ];
    }

    public function walk(): string {
        return "I'm a walking dog";
    }

    public function bark()
    {
        echo "I'm barking";
    }
}

Finally, we need to move our GermanShepherd class into its own file, GermanShepherd.php. It extends Dog, so we’ll require_once our Dog.php file.

<?php
require_once("Dog.php");

class GermanShepherd extends Dog
{

    static int $num_of_dogs_created = 0;

    public static function update_num_of_dogs_created() {
        self::$num_of_dogs_created++;
    }

    public function get_num_of_dogs_created_plus_two() {
        return 2 + self::$num_of_dogs_created;
    }

    public function __construct(string $eye_color,
                                string $dob,
                                string $fur_color)
    {
        $this->eye_color = $eye_color;
        $this->dob = $dob;
        $this->fur_color = $fur_color;

        self::update_num_of_dogs_created();
    }

    public function bark()
    {
        echo "Has heart: " . self::HAS_HEART;
        echo "Loud Barking";

    }

    public function walk(): string {
        echo "I am a walking German Shepherd";
        return parent::walk();
    }
}

Looking at our original code, the only code that’s left there is the code instantiation and a few method calls on the Car and GermanShepherd classes.

<?php

$chevy = new Car(1998, "Mitsubishi", "3000GT");
$chevy->setHp(600);
$chevy->setTq(800);

echo $chevy->getHp();
echo $chevy->getTq();

$chevy->setYear(1997);
echo $chevy->turnOn();
echo $chevy->drive();
echo $chevy->turnOff();

echo "<br>";

$gs_dog = new GermanShepherd("Black", "Oct 15, 2018", "Brown");
echo "Eye Color: " . $gs_dog->getEyeColor() . "<br>";
echo "DOB: " . $gs_dog->getDob() . "<br>";
echo $gs_dog->bark() . "<br>";

Running the code as is will not work. PHP has no idea of what the Car class is, and the same goes for GermanShepherd. We have to tell it where those classes live so that it knows how to make sense of the code. We do that by including the Car.php and GermanShepherd.php files.

The best way to think about the above is that PHP will construct our original file with all of the code from each class inside of one file. When we do require_once(“Car.php”), imagine that PHP just goes into the Car.php class, grabs all of the contents and pastes it on top of the file calling the code.

Managing our code now becomes much easier. You also get good separation of logic as a bonus.

Class Inheritance

TRACING THE LINEAGE OF FUNCTIONALITY IN INHERITANCE CHAINS

PHP – P54: INHERITANCE CHAIN

In the last article I mentioned briefly that you can’t extend multiple classes at once. But the parent class can itself be a child class and extend a class of its own.

File Separation

Piecing Together Masterpieces with Included Files

PHP – P55: file separation

Include, Require, Require Once, and Include Once. You might have seen these at the top of a file in someone else’s code, but what does each one of them mean?

Method Overriding

BREATHING FRESH LIFE INTO LOGIC WITH METHOD OVERRIDES

PHP – P56: METHOD OVERRIDING

PHP’s object oriented principles allow for both method overloading and method overriding. But what do these terms mean?

Leave a Reply