独り言

プログラミングの講師をしています。新人研修で扱う技術の解説と個人の技術メモ、技術書の紹介など

【PHP】PHP入門(オブジェクト指向編)

PHPオブジェクト指向編です。
オブジェクト指向そのもそについての細かい説明は下記の記事で書いたので、ここでは簡単な説明に留めます。
ソースコードを絡めた説明をメインにします。

case10.hateblo.jp

PHPオブジェクト指向以前の内容については以下の記事を参考にしてください。

case10.hateblo.jp

オブジェクト指向の概要

オブジェクト指向の概要の説明はここでもしておきます。
オブジェクト指向は簡単にいえば、プログラミングを効率化するための手法・考え方になります。
プログラムをクラスという単位でまとめ、クラスを元にオブジェクト(インスタンス)を作成し、インスタンスのやりとりによってプログラムの流れを書いていきます。


クラスの利用

オブジェクト指向ではクラスという概念を使用し、クラスを元にオブジェクトを生成してプログラムを書くという仕組みです。
以下、クラスの宣言のサンプルです。

User.php

<?php

// クラス宣言
class User 
{
    
    // プロパティ
    public $id;
    public $age;
    public $name;

    // メソッド
    public function selfIntroduction() 
    {
        echo "名前は $this->name です。年齢は $this->age です。";
    }
}

クラスを利用するファイル index.php

<?php
require_once('User.php');
// インスタンスの生成
$user = new User();
// プロパティへの値のセット
$user->name = '綾鷹';
$user->age = 20;
// メソッドの呼び出し
$user->selfIntroduction();

実行結果を確認するにはWebサーバーを起動し、ブラウザ上からindex.phpを確認します。
ブラウザでの結果

名前は 綾鷹 です。年齢は 20 です。

解説

クラスを宣言は以下のようになります。

<?php
class クラス名 
{
    // プロパティ
    アクセス修飾子 変数名;

    // コンストラクタ
    public function __construct() 
    {
        // 初期化処理
    }

    // メソッド
    アクセス修飾子 function メソッド名()
    {
        // 処理
    }
}

クラス宣言

クラス名はそのクラスを表すものになります。
今回のサンプルではユーザーを表すクラスとしてUserクラスを作成しました。
クラス名は先頭を大文字で命名するのが一般的になっています。
クラス宣言後の中括弧({})の中には、オブジェクトの状態を表す「プロパティ」、振る舞いを表す「メソッド」、オブジェクト生成時の初期化を行う「コンストラクタ」を書くことができます。
コンストラクタについては後ほどサンプルで詳細を解説します。

プロパティ

プロパティはオブジェクトの状態を表すもので、簡単に言ってしまえば変数です。
変数と違うのは、アクセス修飾子を指定する必要があることです。
アクセス修飾子とは、クラスの外部からでもアクセス(参照、代入)ができるのか、あるいはクラス内からしかアクセスできないのか、といったアクセスのレベルを設定するものです。
アクセス修飾子は「public」「protected」「private」の3つがあります。
ざっくりと説明すると、
publicはどこからでもアクセス可能。
protectedは自クラス内と継承先のクラスからアクセス可能。
privateは自クラス内のみからアクセス可能。
となります。

今回の例ではユーザーが持つプロパティとして、id、名前、年齢という変数を作成しています。

メソッド

メソッドは処理を定義するもので、言わば関数です。
クラス(オブジェクト)が持つ関数というイメージです。
プロパティと同じく、アクセス修飾子を指定できます。
指定できるアクセス修飾子もプロパティと同じで、「public」「protected」「private」の3つが指定できます。
アクセス修飾子を省略した場合はpublicになります。

メソッドでは通常の関数を同じく処理をなんでも定義することができますが、一つ関数と違うポイントとして「$this」というキーワードが出てきます。
サンプルのコードではメソッドは

echo "名前は $this->name です。年齢は $this->age です。";

となっています。
thisは「自分自身」を表すキーワードです。
nameとageはプロパティの名前です。
「$this->name」「$this->age」はそのインスタンス(オブジェクト)のname, ageを表すものとなっています。
クラスの中ではnameとageというプロパティはそれぞれ1つずつしか宣言していません。
しかし、後述するnewというキーワードを使用すると、クラスを元にインスタンス(オブジェクト)を作成することができて、作成したインスタンスの分だけname, ageのプロパティも出来上がります。
$thisをつけると、そのインスタンス自身のname, ageを表す、という意味になります。
name, ageの前には$を付けないことに注意しましょう。

また、「$this」とプロパティの間に「->」(ハイフンと不等号)があります。
これは日本語で表すと「の」を意味する接続詞と考えると良いでしょう。
そのインスタンス「の」nameプロパティ。
のような感じです。
この記号はインスタンスを使用する場合に頻繁に出てきますので、覚えておくようにしましょう。
ちなみにJavaでは同じ表現を「.」(ピリオド)を使って表します。

外部ファイルの読み込み

ここからはindex.php(クラスを利用しているファイル)について解説します。
まず外部ファイルの読み込みからです。
ファイルの先頭に

require_once('User.php');

というコードがあります。
これはオブジェクト指向とは直接関係ないですが、PHPで別ファイルとして定義されたもの(外部ファイル)を読み込むための構文になります。
PHPでは外部ファイルを読み込むための構文は4つあります。
「require」「require_once」「include」「include_once」の4つです。
それぞれ、似てはいるものの微妙に動きが異なります。

require:指定されたファイルを読み込み、読み込みに失敗した場合(エラーが発生した場合)は処理が停止します。
require_once:requireとほぼ同じ意味ですが、違う点は、既に読み込まれているかどうかをチェックし、読み込まれている場合には読み込みません。
include:指定されたファイルを読み込み、読み込みに失敗しても処理は停止せずに、警告を出して処理を続行します。
include_once:includeとほぼ同じ意味ですが、既に読み込まれているかをチェックし、読み込まれている場合には読み込みません。

どれを使うかはケースバイケースですが、多くの場合、PHPのみのファイル(クラスが定義されたファイルなど)を読み込む場合はrequire_once、Webページに表示されるコンテンツの一部を表示する場合にはincludeを使う場合が多いです。
ここでは特に問題がない限りはrequire_onceを使用していきます。
ファイルを読み込むには引数に文字列で読み込むファイルのパスを指定する必要があります。
ファイルのパスは絶対パスによる指定と相対パスによる指定が可能です。
今回のサンプルではそれぞれのファイルが同じ階層にいることを前提としてファイル名のみを指定しています。
異なる階層にある場合には絶対パス相対パスでファイルの場所を指定する必要があります。

インスタンスの生成

クラスを元に作成されたオブジェクトのことをPHPではインスタンスと呼びます。
インスタンスを生成するのはnewというキーワードを使用します。
サンプルでは以下のようになっています。

// インスタンスの生成
$user = new User();

構文としては以下のようになります。

変数 = new クラス名();

この場合、クラス名の後の()は省略可能です。
ただし、コンストラクタを定義している場合はその引数に応じた値を渡してあげる必要があります。
この点については後述します。

プロパティ・メソッドへのアクセス

インスタンスは生成しただけではあまり意味はありません。
それを使うことに意義があります。
プロパティにアクセスするためには、
インスタンス名(変数名)->プロパティ名
インスタンス名(変数名)->メソッド名(); とすることでプロパティやメソッドを使用することができます。
サンプルでは以下のようになっています。

// プロパティへの値のセット
$user->name = '綾鷹';
$user->age = 20;
// メソッドの呼び出し
$user->selfIntroduction();

プロパティは変数とおぼ同じなので値を代入することができます。
参照して出力することも可能です。
メソッドは呼び出すことで実行可能です。
今回のサンプルではプロパティやメソッドを自由に使うことができますが、これはそれぞれのプロパティやメソッドのアクセス修飾子がpublicだからです。
privateやprotectedだった場合にはアクセスできずにエラーになってしまいますので注意が必要です。


コンストラク

プロパティとメソッドについては軽くサンプルを示しましたがコンストラクタについてはサンプルを示していなかったのでここで追記してみます。
User.phpを以下のようにします。

<?php

// クラス宣言
class User 
{
    
    // プロパティ
    public $id;
    public $age;
    public $name;

    // コンストラクタ
    public function __construct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    // メソッド
    public function selfIntroduction() 
    {
        echo "名前は $this->name です。年齢は $this->age です。";
    }
}

そしてindex.phpを以下のようにします。

<?php
require_once('User.php');
// インスタンスの生成
$user = new User('綾鷹', 20);
// メソッドの呼び出し
$user->selfIntroduction();

実行結果は最初の例と変更ありません。

コンストラクタの定義

コンストラクタは、インスタンス生成時(つまりnewというキーワードを使った時)に呼ばれる特殊なメソッドです。
メソッド名は「__construct」で固定となります。
サンプルのコードでは以下のようになっています。

// コンストラクタ
public function __construct($name, $age)
{
    $this->name = $name;
    $this->age = $age;
}

ちなみに、PHPでは特殊なメソッド、関数として(アンダースコア)2つから始まるものが定義されていることがあります。
自分でメソッドを定義する時にも
(アンダースコア)2つから始まるメソッドを定義することもできますが、自分で定義した名前なのか、PHPが予め用意しているメソッドの名前なのか区別がつきにくくなるため、メソッドを自分で定義する時に_2つから始まるものは避けるようにしましょう。
(このような関数はマジックメソッドと呼ばれています。他の言語でも似た特徴を持つものもあります。)

サンプルをみてわかるように、コンストラクタでは引数を持つこともできます。
この例ではサンプルで受け取った値をそのままプロパティの値にセットしています。
この例のように、コンストラクタではプロパティの値を初期化するために使用されることが多いです。

ちなみに、コンストラクタは一つしか定義することができません。
引数の数を変更して複数定義しようとしてもエラーになるので注意してください。
Javaなどの言語では、オーバーロードという仕組みがあり、引数が異なれば同じメソッド名を複数定義することも可能ですが、PHPでその機能はサポートされていないので注意してください。)

コンストラクタの使用

コンストラクタを使用するには、newでクラス名を指定した後にコンストラクタの引数に対応した実引数を渡してあげます。

// インスタンスの生成
$user = new User('綾鷹', 20);

クラスプロパティとクラスメソッド

クラス内で定義したプロパティやメソッドは、newを使用してインスタンスを作成するたびに、インスタンス毎に作成されていくようなイメージです。
一方、クラスで1つ(全てのオブジェクトで共有される)プロパティやメソッドを作成することも可能です。
このようなプロパティやメソッドとそれぞれクラスプロパティ、クラスメソッドと呼びます。
staticというキーワードをつけることで実現できます。
User.phpとindex.phpを以下のように修正します。

User.php

<?php

// クラス宣言
class User 
{
    
    // クラスプロパティ
    public static $count = 0;

    // プロパティ
    public $id;
    public $age;
    public $name;

    // コンストラクタ
    public function __construct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
        self::countUp();  // 追加
    }

    // クラスメソッド
    public static function countUp() 
    {
        self::$count++;
    }

    // メソッド
    public function selfIntroduction() 
    {
        echo "名前は $this->name です。年齢は $this->age です。";
    }
}

index.php

<?php
require_once('User.php');
// インスタンスの生成
$user = new User('綾鷹', 20);
echo 'カウント:' . User::$count . '<br>';

$user = new User('伊右衛門', 30);
echo 'カウント:' . User::$count . '<br>';

User::countUp();
echo 'カウント:' . User::$count . '<br>';

実行結果

カウント:1
カウント:2
カウント:3

クラスプロパティとクラスメソッドの宣言

クラスプロパティとクラスメソッドの宣言方法は、通常のプロパティとメソッドの宣言方法とほとんど同じです。
違いはstaticがつく点です。

// クラスプロパティ
public static $count;

// クラスメソッド
public static function countUp() 
{
    self::$count++;
}

新しく「self::」というキーワードが出てきました。
通常のプロパティやメソッドの場合、自クラス内からアクセスする場合は「$this」というキーワードを付けましたが、クラスプロパティやクラスメソッドにアクセスする場合にはそれが「self::」に変わるので覚えておきましょう。
また、プロパティにアクセスする時には変数名に$マークもつける点にも注意です。

クラスプロパティやクラスメソッドの利用

外部から、クラスプロパティ、クラスメソッドにアクセスする場合には、
クラス名::プロパティ名
クラス名::メソッド名
とします。

User::countUp();
echo 'カウント:' . User::$count . '<br>';

また、サンプルソースではコンストラクタの中でcountUpメソッドを呼び出していることに注意してください。
そうするとnewを使うたびに$countがカウントアップされます。
また、自分で「User::countUp();」を呼び出すことでもカウントアップされます。
結果として、インスタンス生成を2回、カウントアップメソッドの呼び出しを1回しているため、最終的に$countプロパティの値が3になっていることがわかります。
処理の流れを追うことができれば、インスタンス間で値が共有されて、クラスで1つのみであることがイメージできるかと思います。


定数

クラスの中には定数を定義することができます。
定数は再代入することができない変数です。
定数を定義するには、constというキーワードを使用します。
変数名には$マークを付けず、アルファベットの大文字で名前を付けます。

User.php

<?php

// クラス宣言
class User 
{
    // 定数
    public const MAX_SCORE = 100;
    
    // クラスプロパティ
    public static $count = 0;

    // プロパティ
    public $id;
    public $age;
    public $name;

    // コンストラクタ
    public function __construct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
        self::countUp();  // 追加
    }

    // クラスメソッド
    public static function countUp() 
    {
        self::$count++;
    }

    // メソッド
    public function selfIntroduction() 
    {
        echo "名前は $this->name です。年齢は $this->age です。";
    }
}

index.php

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

echo User::MAX_SCORE;

実行結果

100

定数宣言

定数宣言は以下のようになります。

// 定数
public const MAX_SCORE = 100;

使用する場合は、
クラス名::定数名
となります。

echo User::MAX_SCORE;

定数は再代入することができないので、代入する処理を書くとエラーになります。


継承

継承は元々あるクラスの特徴を引き継いで新しいクラスを作ることができる機能です。
User.phpをそのままに、同じ階層にExUser.phpを作成します。

ExUser.php

<?php

require_once('User.php');

class ExUser extends User
{
    // 新しいプロパティ追加
    public $score;

    public function __construct($name, $age, $score)
    {
        parent::__construct($name, $age);
        $this->score = $score;
    }

    // 新しいメソッドの追加
    public function scoreUp()
    {
        $this->score += 10; 
    }

    // メソッドのオーバーライド
    public function selfIntroduction()
    {
        parent::selfIntroduction();
        echo "scoreは $this->score です。";
    }
}

index.phpを以下に書き換えます。

<?php
require_once('ExUser.php');
// インスタンスの生成
$exUser = new ExUser('いろはす', 10, 70);
$exUser->scoreUp();
$exUser->selfIntroduction();

実行結果

名前は いろはす です。年齢は 10 です。scoreは 80 です。

extends

クラスの継承を行う時にはクラス宣言時にextendsというキーワードを使用します。
(拡張という意味があります。)

class ExUser extends User
{
    ...
}

こうすると、Userクラスを継承(拡張)してExUserクラスを作成したことになります。
この時、Userクラスのことを親クラス、あるいはスーパークラスなどと呼びます。
ExUserのことを、子クラス、あるいはサブクラスなどと呼びます。
継承を行うと、親クラスの機能は定義しなくてもそのまま使用することができます。
つまり、$nameプロパティや$ageプロパティなどはそのまま使えます。
もちろんメソッドも使用することができます。
親クラスの状態を受け継いだまま、新しい機能を追記することができます。
今回の例では$scoreプロパティとscoreUpメソッドを新しく追記しています。

parentキーワード

これまで自分自身のインスタンス、クラスを表すキーワードとして「this」や「self」がありましたが、継承を使う場合には新しく親クラス表す「parent」キーワードが登場します。
parent::プロパティ名
parent::メソッド名
で親クラスのプロパティやメソッドにアクセスすることができます。
今回のサンプルでは、コンストラクタの中で親クラスのコンストラクタを呼び出す場合などに利用しています。

多重継承

複数のクラスを同時に継承することを多重継承と呼びます。
PHPでは多重継承はできません。(多くのオブジェクト指向言語では多重継承はできない。一部できるものもある。)
その代わり、何世代にも渡って継承して新しいクラスを作成することは可能です。

オーバーライド

継承を行う上で重要な概念の一つにオーバーライドがあります。
オーバーライドはメソッドの上書きという意味があります。
今回の例ではselfIntroductionメソッド(自己紹介メソッド)がオーバーライドに該当します。
親クラス(Userクラス)でも全く同じ名前のメソッドが存在しますが、子クラス(ExUser)でも同じ名前のメソッドを定義しています。
これがオーバーライドです。
クラスを拡張したことでプロパティが増えた(score)ので、自己紹介メソッドで追加したプロパティも表示するようにしています。
親クラスのメソッドをparentを指定して呼び出しつつ、新しく追加する処理のみを追加しています。
これにより新しく追加したい部分のみの処理を定義すれば良いため、効率が上がります。

抽象クラスとインターフェース

継承を利用すれば、開発を行う際に役割分担をしやすくなるというメリットもあります。
親クラスをAさんが開発し、そのクラスを継承した子クラスをBさんが開発する、のような役割分担ができます。
しかし、役割分担するとミスも生じやすくなります。
例えば、Aさんが作成したクラスは、継承することを前提としており、特定のメソッドを必ずオーバーライドして欲しかったとします。
このとき、子クラスを作成したとしても、メソッドをオーバーライドし忘れたり、あるいはオーバーライドしたつもりでもメソッド名のスペルが間違っていてオーバーライドになっていないといったミスが発生する可能性があります。

このようなミスを発生させないための仕組みとして、抽象クラス、インターフェースという概念があります。

抽象クラス

抽象クラスは、継承することを前提としたクラスです。
抽象クラスは、宣言時にabstractキーワードを使用します。
また、抽象クラスは抽象メソッドと呼ばれる処理のないメソッドを定義することができます。
処理が書かれている通常のメソッドも定義することができます。
抽象クラスではない通常のクラスのことを、抽象クラスの対比として「具象クラス」と呼ぶことがあります。
以下はサンプルです。

抽象クラス
Employee.php

<?php

abstract class Employee 
{
    private $saraly;

    // コンストラクタ
    public function __construct($saraly)
    {
        $this->saraly = $saraly;
    }

    // 通常のメソッド
    public function getSalary()
    {
        return $this->saraly;
    }

    // 抽象メソッド
    public abstract function work();
}

具象クラス
Peogrammer.php

<?php

require_once('Employee.php');

class Programmer extends Employee 
{
    // オーバーライドしないとエラーになる
    public function work()
    {
        echo 'プログラミングする';
    }
}

index.php

<?php
require_once('Programmer.php');
// インスタンスの生成
// $employee = new Employee();  // ←エラーになる

$programer = new Programmer('200000') . '<br>';
echo $programer->getSalary();
$programer->work();

実行結果

200000
プログラミングする

Employeeクラスが抽象クラスです。
クラス宣言にabstractがつきます。
プロパティや通常のメソッドも持っています。(salaryプロパティとgetSalaryメソッド)
workメソッドが抽象メソッドです。
アクセス修飾子の後にabstractキーワードをつけます。
処理は書かず、中かっこ{}も書きません。
その代わりにセミコロン(;)で終了します。

Programmerクラスが抽象クラスを継承した具象クラスです。
抽象クラスを継承した場合、そのクラスに定義されている抽象メソッドをオーバーライドしないとエラーになります。
コメントアウトして実行するとどうなるか確認すると良いでしょう。)
※ただし、抽象クラスを継承したクラス自体を抽象クラスにしてしまえば(abstractをつける)、オーバーライドしなくてもエラーにはなりません。

index.phpで実行結果を確認しています。
抽象クラスは、継承されることを前提としたクラスであると言いましたが、その理由からnewでインスタンスを作成することがでないことに注意して下さい。

インターフェース

抽象クラスとは別にインターフェースという概念もあります。
インターフェースは抽象クラスよりもさらに抽象度の高い概念を定義する機能です。
インターフェースではプロパティや通常のメソッドを定義することができず、抽象メソッドと定数が定義可能です。
インターフェースを定義するときはclassではなくinterfaceというキーワードを使用します。
また、インターフェースは継承ではなく実装すると呼び、extendsではなくimplementsというキーワードを使用します。

インターフェース
Runnable.php

<?php

interface Runnable
{
    // 抽象クラス(absract不要)
    public function run();
}

実装したクラス
Programmer.php

<?php

require_once('Employee.php');
require_once('Runnable.php');

class Programmer extends Employee implements Runnable
{
    public function work()
    {
        echo 'プログラミングする';
    }

    public function run()
    {
        echo 'ゆっくり走る';
    }
}

index.php

<?php
require_once('Programmer.php');
// インスタンスの生成
$programer = new Programmer('200000');
$programer->run();

実行結果

ゆっくり走る

このサンプルではRunnnableがインターフェースです。
インターフェースでは抽象メソッドしか定義できないため、abstractは省略可能です。
ProgrammerクラスがRunnableを実装しているクラスです。
実装するにはimlementsキーワードを使用しています。
メソッドのオーバーライド方法は今までと変わりありません。

インターフェースは抽象クラスしか定義できないため、抽象クラスよりも使いにくいと感じるかもしれません。
しかし、実はインターフェースの抽象度が高いため、柔軟性も高くなります。
PHPではクラスを継承するときに多重継承はできないと書きましたが、インターフェースは複数実装することができます。
オブジェクト指向をうまく活用するときにはこの辺りが役に立ちます。
(クラスの継承の場合、継承元(親クラス)で同じ名前のメソッドがある場合、呼び出し時にどちらを呼び出すかが判断できなくなります。
しかし、インターフェースの場合はそもそも抽象メソッドしか定義できないため、メソッド名が重複してもどっちみちオーバーライドするので関係ありません。)

カプセル化

先に作成していたUserクラスを少しすっきりさせておきます。

User.php

<?php

// クラス宣言
class User 
{   
    // プロパティ
    public $age;
    public $name;

    // コンストラクタ
    public function __construct($name, $age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    // メソッド
    public function selfIntroduction() 
    {
        echo "名前は $this->name です。年齢は $this->age です。";
    }
}

実はこのクラスいくつか問題があります。
それは、プロパティのアクセス修飾子がpublicになっていることです。
publicでなければ外部からアクセスすることができないため、その方が良いと思うかもしれません。

index.phpを以下のようにしてみます。

<?php
require_once('User.php');
// インスタンスの生成
$user = new User('ポカリ', 20);
$user->age = 300;
$user->selfIntroduction();

実行結果

名前は ポカリ です。年齢は 300 です。

このサンプルでは、インスタンス作成後にプロパティの値を変更されています。
ageは年齢を表すプロパティのため、できれば0~100くらいの値でおさめられる方が望ましいです。
しかし、プロパティがpublicで誰でもアクセス可能となっているため、上記のようなことができてしまいます。
Userクラスを以下のようにするとやりたいことができるようになります。

User.php

<?php

// クラス宣言
class User 
{   
    // プロパティ
    private $age;
    private $name;

    // コンストラクタ
    public function __construct($name, $age)
    {
        $this->setName($name);
        $this->setAge($age);
    }

    // メソッド
    public function selfIntroduction() 
    {
        echo "名前は $this->name です。年齢は $this->age です。";
    }

    public function getAge()
    {
        return $this->age;
    }

    public function setAge($age)
    {
        if ($age >= 0 && $age <= 100) {
            $this->age = $age;
        } else {
            $this->age = 20;
        }
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }
}

index.php

<?php
require_once('User.php');
// インスタンスの生成
$user = new User('ポカリ', 20);
$user->setAge(300);
$user->selfIntroduction();

実行結果

名前は ポカリ です。年齢は 20 です。

プロパティのアクセス修飾子をpriavteにし、自クラス以外はアクセスできないようにしました。
そうすると、外部からのアクセスができなくなりますが、その代わりsetAge, getAgeなど、メソッドを用意し、メソッド経由でアクセスできるようにしています。
こうすることで、想定外の値が渡されてきた場合にも適切な値になるように処理したり、あるいはエラーが出るように処理することなどができるようになります。
メソッド経由でのアクセスにすることで、取得はできるがセットはできないようにする、など、柔軟に対応できるようになります。
このように、プロパティを直接アクセスできないようにし、メソッド経由でアクセスできようにすることをカプセル化と呼びます。
不要な情報は隠蔽し、必要な情報のみを公開する、というオブジェクト指向における重要な概念となります。

名前空間

作成するプログラムの規模が大きくなると、使用するクラスやファイルの数も多くなります。
使用するクラスやファイルの数が多くなると、プログラムの役割ごとにカテゴリ分けしておくと便利です。
また、クラスや関数の数が多くなると、既存のライブラリに用意されているクラスや関数の名前と重複してしまう可能性も出てきます。
このような、名前の重複を回避、かつ役割ごとにカテゴリ分けする仕組みとして用意されているのが名前空間です。
名前空間の定義はnamespaceというキーワードを使用します。
名前空間の定義されたファイルを使用する場合は、useキーワードを使用します。

User.php

<?php
// 名前空間の定義
namespace MyProject;

// クラス宣言
class User 
{   
    // プロパティ
    private $age;
    private $name;

    // コンストラクタ
    public function __construct($name, $age)
    {
        $this->setName($name);
        $this->setAge($age);
    }

    // メソッド
    public function selfIntroduction() 
    {
        echo "名前は $this->name です。年齢は $this->age です。";
    }

    public function getAge()
    {
        return $this->age;
    }

    public function setAge($age)
    {
        if ($age >= 0 && $age <= 100) {
            $this->age = $age;
        } else {
            $this->age = 20;
        }
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }
}

index.php

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

// 名前空間がついたクラスの利用
use MyProject\User;

// インスタンスの生成
$user = new User('ポカリ', 20);
$user->selfIntroduction();

名前空間の宣言はファイルの先頭(クラス定義や関数定義の前)に行う必要があるので注意してください。
使用する場合は「名前空間\クラス名」とすることで使用することができるのですが、毎回そう書くのは面倒なので、
use 名前空間\クラス名 でとすことでクラス名だけで使用することができるようになります。
名前空間の付け方は任意ですが、ベンダー名\プロジェクト名 のようにつけることが多いです。

型付け

メソッドの引数やプロパティには、型を指定することができます。
TODO

トレイト

コードの断片を共通化したいときに使える仕組み。
TODO