PHPのオブジェクト指向とは
PHPは手続き型の書き方もできますが、オブジェクト指向プログラミング(OOP) を活用することでコードの再利用性や保守性が大幅に向上します。LaravelなどのモダンなPHPフレームワークもOOPを前提に設計されているため、基本を押さえておくことは非常に重要です。
この記事では「クラス」「継承」「インターフェース」「抽象クラス」という4つの柱を順番に解説します。
クラスとインスタンス
PHPでクラスを定義するには class キーワードを使います。クラスはオブジェクトの設計図であり、そこから生成される実体をインスタンスと呼びます。
<?php
class User
{
// プロパティ
public string $name;
public int $age;
// コンストラクタ
public function __construct(string $name, int $age)
{
$this->name = $name;
$this->age = $age;
}
// メソッド
public function greet(): string
{
return "こんにちは、{$this->name}さん({$this->age}歳)です。";
}
}
$user = new User('田中', 28);
echo $user->greet();
// こんにちは、田中さん(28歳)です。
アクセス修飾子
プロパティやメソッドには以下の3種類のアクセス修飾子を付けられます。
| 修飾子 | 説明 |
|---|---|
public | どこからでもアクセス可能 |
protected | クラス自身とサブクラスからアクセス可能 |
private | クラス自身からのみアクセス可能 |
<?php
class BankAccount
{
private float $balance;
public function __construct(float $initialBalance)
{
$this->balance = $initialBalance;
}
public function deposit(float $amount): void
{
$this->balance += $amount;
}
public function getBalance(): float
{
return $this->balance;
}
}
$account = new BankAccount(1000.0);
$account->deposit(500.0);
echo $account->getBalance(); // 1500
// $account->balance; // エラー!privateなのでアクセス不可
継承
既存のクラスを親クラスとして、その機能を引き継いだ子クラスを作ることを「継承」と言います。extends キーワードを使います。
<?php
class Animal
{
public function __construct(protected string $name) {}
public function speak(): string
{
return "{$this->name}が鳴いています。";
}
}
class Dog extends Animal
{
// 親のメソッドをオーバーライド
public function speak(): string
{
return "{$this->name}:ワンワン!";
}
public function fetch(): string
{
return "{$this->name}がボールを取ってきた!";
}
}
class Cat extends Animal
{
public function speak(): string
{
return "{$this->name}:ニャー!";
}
}
$dog = new Dog('ポチ');
$cat = new Cat('タマ');
echo $dog->speak(); // ポチ:ワンワン!
echo $dog->fetch(); // ポチがボールを取ってきた!
echo $cat->speak(); // タマ:ニャー!
parentキーワード
子クラスから親クラスのメソッドを呼び出すには parent:: を使います。
<?php
class AdminUser extends User
{
public function __construct(string $name, int $age, private string $role)
{
parent::__construct($name, $age); // 親のコンストラクタを呼び出す
}
public function greet(): string
{
return parent::greet() . "(役割:{$this->role})";
}
}
$admin = new AdminUser('佐藤', 35, '管理者');
echo $admin->greet();
// こんにちは、佐藤さん(35歳)です。(役割:管理者)
インターフェース
インターフェースは「このクラスは必ずこのメソッドを持つ」という契約を定義します。interface キーワードで宣言し、implements で実装します。
<?php
interface Notifiable
{
public function notify(string $message): void;
}
interface Loggable
{
public function log(string $event): void;
}
// 複数のインターフェースを同時に実装できる
class EmailService implements Notifiable, Loggable
{
public function notify(string $message): void
{
echo "メール送信: {$message}\n";
}
public function log(string $event): void
{
echo "ログ記録: {$event}\n";
}
}
$service = new EmailService();
$service->notify('注文が完了しました');
$service->log('order.completed');
インターフェースを型ヒントとして使うことで、どの具体クラスが来ても動く柔軟なコードが書けます。
<?php
function sendAlert(Notifiable $notifier, string $message): void
{
$notifier->notify($message);
}
// EmailServiceはNotifiableを実装しているので渡せる
sendAlert(new EmailService(), 'サーバーエラーが発生しました');
抽象クラス
抽象クラスはインターフェースと継承の中間的な存在です。共通の実装は持ちつつ、一部のメソッドはサブクラスに実装を強制したい場合に使います。
<?php
abstract class Shape
{
// 抽象メソッド:サブクラスで必ず実装する
abstract public function area(): float;
// 共通の具体的なメソッド
public function describe(): string
{
return get_class($this) . "の面積は " . $this->area() . " です。";
}
}
class Circle extends Shape
{
public function __construct(private float $radius) {}
public function area(): float
{
return M_PI * $this->radius ** 2;
}
}
class Rectangle extends Shape
{
public function __construct(
private float $width,
private float $height
) {}
public function area(): float
{
return $this->width * $this->height;
}
}
$shapes = [new Circle(5.0), new Rectangle(4.0, 6.0)];
foreach ($shapes as $shape) {
echo $shape->describe() . "\n";
}
// Circleの面積は 78.539816... です。
// Rectangleの面積は 24 です。
まとめ
PHPのオブジェクト指向の主要な概念を整理します。
| 概念 | キーワード | 用途 |
|---|---|---|
| クラス定義 | class | オブジェクトの設計図を作る |
| 継承 | extends | 既存クラスの機能を引き継ぐ |
| インターフェース | interface / implements | メソッドの契約を定義する |
| 抽象クラス | abstract | 共通実装+強制メソッドを定義する |
OOPを使いこなすことで、コードの重複を減らし、変更に強い設計が実現できます。LaravelのEloquentモデルやSymfonyのサービスクラスも、これらの概念の上に成り立っています。まずは小さなクラスを書くところから始めてみましょう!