pyてよn日記

一寸先は闇が人生

PHP の勉強 その2 - オブジェクト指向の基礎

 引き続き PHP の勉強.Progate で勉強を進めている.前回の内容は下記.

pyteyon.hatenablog.com

 本記事では PHPオブジェクト指向を扱う.学習のために同じコードを少しずつ変化させているため冗長な部分が多々ある.

PHPオブジェクト指向を学ぶ

オブジェクト指向とは?

 オブジェクト指向とは「もの」単位でプログラムを扱う考え方.例えば,EC サイトが「商品」,「ユーザー」,「カート」などのオブジェクトで組み合わさってできていると考える.

 オブジェクト指向により,それぞれのオブジェクトに関するプログラムの役割が明確化し,それらを組み立てるようにプログラムを書くことができる.

 自分の中では,

  • インターフェースの共通化
  • プログラムの整理,構造化,再利用可能化

オブジェクト指向の目的だと解釈がしている(正しいのか?).

クラスとインスタンス

  • クラス:オブジェクトの設計図.
  • インスタンス:クラス(設計図)を実体化したもの.

クラスの定義,インスタンスの生成

  • クラス名は Camel Case で命名.先頭の $ は必要ない.
  • インスタンスの生成は $hoge = new ClassName();

大枠

<?php
// クラスの定義
class ClassName {
    // code
}

$myInstance = new ClassName();

?>

プロパティとメソッド

プロパティの定義,アクセス

  • public $hoge でプロパティを定義.
  • -> 演算子でプロパティへアクセス.インスタンス名->プロパティ名.このときプロパティ名の先頭に $ は不要

public については後述.

<?php
class Car {
    // property
    public $name;
}

$car1 = new Car();
$car1->name = 'SKYLINE';  // プロパティ名の先頭に $ は不要
?>

メソッドの定義,使用

  • public function hoge() {} でメソッドを定義.
  • プロパティ同様 -> 演算子でメソッドへアクセス.インスタンス名->メソッド名() で呼び出す.このときメソッド名の先頭に $ は不要.
<?php
class Car {
    // property
    public $name;

    // method
    public function hello() {
        echo '私は Car クラスのインスタンスです' . '<br />';
    }
}

$car1 = new Car();
$car1->name = 'SKYLINE';
$car1->hello();  // メソッド名の先頭に $ は不要

?>

$this:クラス定義内でプロパティ,メソッドにアクセスする

 メソッド内でインスタンスのプロパティ,メソッドにアクセスしたいとき,$this という特殊な変数を用いる.

 $this はクラス内のメソッドの定義の中でのみ使用できる.

 $this はメソッドが呼ばれたとき,そのメソッドを呼び出しているインスタンスに置き換えられる.

<?php
class Car {
    // property
    public $name;

    // method
    public function hello() {
        echo '車の名前は' . $this->name . 'です' . '<br />';
    }
}

$car1 = new Car();
$car1->name = 'SKYLINE';
$car1->hello();

?>

プロパティの初期値

 プロパティは初期値を設定することができる.また,変更することも可能である.

<?php
class Car {
    // property
    public $name = 'NOTE';

    // method
    public function hello() {
        echo '車の名前は' . $this->name . 'です' . '<br />';
    }
}

$car1 = new Car();
$car1->hello();  // NOTE
$car1->name = 'SKYLINE';  // name プロパティの変更
$car1->hello();  // 'SKYLINE';

?>

コンストラク

  • コンストラクインスタンス生成時に呼ばれるメソッド.new を用いてインスタンスを生成するときに自動的に呼ばれる.Python で言う __init__()
  • public function __construct() {} で定義する.
<?php
class Car {
    // property
    public $name;

    // constructor
    public function __construct() {
        echo '一つの車が生成されました' . '<br />';
    }

    // method
    public function hello() {
        echo '私の名前は' . $this->name . 'です' . '<br />';
    }
}

$car1 = new Car();  // constructor が自動で実行される
$car1->name = 'SKYLINE';
$car1->hello();

?>

コンストラクタとプロパティ

  • __construct() メソッドは引数を取ることができる.
  • new を用いてインスタンスを生成する際に引数を与えることができ,その引数が __construct() に渡される.
  • __construct() メソッド内で $this を用いることにより,インスタンス生成時にプロパティをセットすることができる.このことから,コンストラクタは初期化メソッドとも言われる.
<?php
class Car {
    // property
    public $name;

    // constructor
    public function __construct($name) {
        $this->name = $name;
    }

    // method
    public function hello() {
        echo '私の名前は' . $this->name . 'です' . '<br />';
    }
}

$car1 = new Car('SKYLINE');  // $name が設定される
// $car1->name = 'SKYLINE';
$car1->hello();

?>

HTML と PHP

  • HTML 中に <?php ?>PHP のコードを埋め込むことができる.
  • 重要)変数を表示したいときは,echo で出力する必要がある.

foreach 文の埋め込み:endforeach を使う

 HTML に foreach 文を埋め込む際に,

  • { の代わりに :
  • } の代わりに endforeach

と記述し,その間に PHP で処理を記述することで foreach 文を使える.処理部分に HTML タグを用いることができるため,コードの可読性が上がる.通常の foreach 文だとタグを文字列として書かなければならない.

 以下に endforeach を使った foreach 文 ,通常の foreach 文の例を示す.

endforeach を使った foreach 文

<?php
$fruits = array('appla', 'banana', 'orange');
?>

// ----- foreach 文 -----
<?php foreach ($fruits as $fruit): ?>

// 処理内容
<p><?php echo $word ?></p>  // タグを直接扱える

<?php endforeach?>
// ----- foreach 文 -----

通常の foreach 文

<?php
$fruits = array('appla', 'banana', 'orange');

foreach ($fruits as $fruit) {
    // タグを文字列として書く必要がある
    echo '<p>' . $word . '</p>';
}
?>

その他の制御構文

 他の制御構文にも以上のような記法がある.

if,endif

<?php
$age = 24;
?>

<?php if ($age >= 20): ?>
<p><?php echo $age ?> 歳:成人です</p>
<?php else: ?>
<p><?php echo $age ?> 歳:未成年です</p>
<?php endif ?>

for,endfor

<?php for ($i=0; $i < 100; $i++): ?>
<p><?php echo $i ?></p>

<?php endfor ?>

その他,endwhile,endwhich も使える.

ファイルの分割:require_once

 PHP では,require_once() という関数を使って他の PHP ファイルを読み込むことができる.これにより可読性保守性が大きく上がりソースコードの管理がしやすくなる.

 例として,PHP のコードを

  • クラスを定義するコード(class.php
  • データを定義するコード(data.php
  • HTML を使って内容を表示するコード(index.php

の 3 つに分割してみる.ここでは,全てのファイルが同じ階層(ディレクトリ)に存在するとする.

class.php

<?php
class MyClass {
    public $name;

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

?>

data.php

<?php
require_once('class.php')

$ins1 = new MyClass('hoge');
$ins2 = new MyClass('hogehoge');
$ins3 = new MyClass('hogehogehoge');

$data = array($ins1, $ins2, $ins3);

?>

index.php

<?php
require_once('data.php');
?>

<?php foreach ($data as $ins) ?>
<p><?php $ins->name ?></p>
<?php endforeach ?>

カプセル化オブジェクト指向の重要な機能

カプセル化の概要

 オブジェクト指向において重要な機能の一つ,カプセル化について学ぶ.

  • カプセル化クラスのプロパティ,メソッドへのアクセスを制限すること.クラスの外部からアクセスできるようにするには public,アクセスできないようにするには private を用いて設定することができる.プロパティは基本的にはアクセス権を private にする

 自分がクラスを設計する際,他の人がクラスを使いやすいように,使って欲しい機能は公開し,使って欲しくない機能を隠す,つまりカプセル化する.カプセル化によって,クラスの利用しやすさ,安全性(予期せぬプロパティの書き換えを防ぐなど)が高まる

public と private

 PHPカプセル化を行うためには,クラス定義内でプロパティ,メソッドの定義の先頭に public,または private を記述する必要がある.

プロパティを public に設定

 プロパティ を public に設定した場合,インスタンスから直接プロパティにアクセスできる.

<?php
class Person {
    public $name, $age;

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

$Bob = new Person('Bob', 17);
echo $Bob->name;
echo $Bob->age;

?>

プロパティを private に設定

 プロパティ を private に設定した場合,インスタンスからプロパティにアクセスできなくなる.-> 演算子でアクセスしようとするとエラーが発生する.

<?php
class Person {
    public $name;
    private $age;  // private に設定

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

$Bob = new Person('Bob', 17);
echo $Bob->name;  // name にはアクセスできる
echo $Bob->age;  // age にアクセスできない,エラーが発生

?>

ゲッター:private なプロパティにアクセスするメソッド

 プロパティのアクセス権を private に設定すると,プロパティの値にクラスの外部からアクセスできなくなる.そこで,プロパティの値を返すメソッドを定義する.

 プロパティの値を返すだけのメソッドゲッター getter という.ゲッターは,「getプロパティ名」と命名するのが一般的.

<?php
class Person {
    private $name, $age;  // private に設定

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

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

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

$Bob = new Person('Bob', 17);
echo $Bob->getName();
echo $Bob->getAge();

?>

セッター:private なプロパティを変更するメソッド

 プロパティのアクセス権を private に設定すると,プロパティの値をクラスの外部から変更できなくなる.そこで,プロパティの値を変更するメソッドを定義する.

 プロパティの値を変更するメソッドセッター setter という.セッターは,「setプロパティ名」と命名するのが一般的.

<?php
class Person {
    private $name, $age;  // private に設定

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

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

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

    // setter
    public function setAge($updateAge) {
        $this->age = $updateAge;
    }
}

$Bob = new Person('Bob', 17);
echo $Bob->getAge();  // 17
$Bob->setAge(19)
echo $Bob->getAge();  // 19

?>

補足1:オブジェクト指向の 3 つの要素

補足2:PHP の基本的な組み込み関数

  • count:配列の要素数を返す.
  • floor:小数点以下を切り捨てた値を返す.

 以下の公式サイトに組み込み関数一覧が載っている.

www.php.net

補足3:HTML タグの属性の設定と PHP の埋め込み

 index.php ファイル内の HTML 中に PHP を埋め込む際,PHP で定義した文字列変数を HTML タグの属性の設定に使用したい場合に注意点がある.

 タグの属性設定のダブルクオーテーション内に <?php ?>PHP のコードを埋め込むと,文字列としてでなく PHP のコードとして認識される.また,echo で出力する必要があることも注意.

<?php
$url = 'https://hoge.com/'
?>

<a href="<?php echo $url ?>">Home</a>

 上記の例では,HTML の <a> タグ内において,

"<?php echo $url ?>" という文字列

ではなく,

echo $url

という PHP のコードとして認識され,<a> タグの href 属性を PHP を用いて設定できる.

補足4:input タグの初期値

 以下のように,<input> タグの value 属性を用いると初期値を設定することができる.

<input value="0">

復習すべき点

  • フォームの作り方
    • <from> タグの action 属性:データの送信先
    • <from> タグの method 属性:データ送信の HTTP メソッド(GET,POST など)
    • PHP 側で POST の受け取り:連想配列 $_POST で受け取れる.<input> タグの name 属性が連想配列の key となる.

pyteyon.hatenablog.com

ポイントまとめ

オブジェクト指向の目的

  • インターフェースの共通化
  • プログラムの整理,構造化,再利用可能化

オブジェクト指向の基礎

  • クラス:オブジェクトの設計図.class ClassName {} で定義.
  • インスタンス:クラスを実体化したもの.$ins = new ClassName();インスタンス生成.
  • プロパティインスタンスが持つデータ.
  • メソッドインスタンスに関連する処理.インスタンスが持つ関数.
  • $this:クラス定義内でインスタンス自身にアクセスする方法.
  • コンスラクインスタンス生成時に実行されるメソッド.クラス定義内で public function __construct() {} と 書くことで定義できる.
  • -> 演算子でプロパティ,メソッドへアクセスできる.例えば,$ins->name
  • カプセル化:クラスのプロパティ,メソッドへのアクセスの制限.publicprivate で設定.
  • コードの分割,外部 PHP ファイルの読み込み:require_once('hoge.php') で他の PHP ファイルを読み込める.

感想

 Progate で学んだ後にちゃんと自分でアプリを作るなどしてクラスの設計やらをしないと身につかないだろうなと感じた.地道に学習を続けたい.

読んでおきたいオブジェクト指向に関する記事

qiita.com