引用
「パーフェクトPHP」
用語/概要
- 「オブジェクト」はデータとデータを操作する関数を内部に持つ集合体。
- 「オブジェクト」を利用するには、「クラス」からオブジェクトを作成する。
- 「クラス」は設計図のため実体を持たない。
- 「オブジェクト」は実体を持つ。
- 「クラス」から生成される個別のオブジェクトを「インスタンス」と呼ぶ。
- クラスからインスタンスを作成することを「インスタンス化」と呼ぶ。
- オブジェクトで利用するデータや操作は、クラスの内部で定義する。
- 「データ」を「プロパティ」と呼び、クラス内で定義された「変数」で表す。
- 「操作」を「メソッド」と呼び、クラス内で定義された「関数」で表す。
- 「関数」はfunctionキーワードで定義する。
- オブジェクト内のプロパティ(変数)やメソッド(関数)を利用するには「->」演算子を使う。
- クラスから「インスタンス」を作成するには「newキーワード」を使う。
- 作成されたインスタンスを変数に代入する。
$obj = new Car();
「$obj」は「オブジェクト型」という特別なデータ型の変数。
以下のように記述してアクセスする。
「$obj->$変数名」 ※プロパティ(変数)
「$obj->$関数名」 ※メソッド(関数)
1.クラスの定義
class クラス名
{
[クラスの実装]
}
- クラス名には変数、関数、識別子を指定できる。
- クラス名はアッパーキャメルで記述することが主流。 例) class MyModue_Controller{ }
- PHP_EOLは、End of lineの略で、その行の終わりをあらわす
インスタンスの生成と使い方
<?php
class Employee
{
public function work()
{
echo ‘書類を整理しています’, PHP_EOL;
}
}
<?php
$yamada = new Employee();
$yamada->work(); //書類を整理しています
メソッドの呼び出しには、アロー演算子(->)を用いる。
変数$yamadaにはインスタンス化したEmployeeクラスのオブジェクトへの参照が入る。
参照
new演算子を用いてインスタンス化され、オブジェクトを変数に代入したり、関数の引数に指定したりする場合、オブジェクトへの参照を渡す。
$suzuki = $yamada;
複製
$suzuki = clone $yamada;
$yamadaオブジェクトの複製が、$suzukiに代入される。
$suzukiにした変更は、$suzukiだけのものになり、$yamadaには影響がない。
2.アクセス修飾子
アクセス修飾子とは、メソッドやプロパティがどこからアクセス可能かを表す修飾子。
PHPには3つのアクセス修飾子がある。
public クラスの外側から呼び出し、参照・呼び出しができる
private 自分のクラスの内側からのみ参照・呼び出しができる
protected 自分のクラスの内側または自分のクラスを継承したクラスの内側からのみ参照、呼び出しができる。
3.プロパティ
プロパティはクラスの中に保持している変数。
クラスの定義時に同時に定義する。
プロパティは、アクセス修飾子のあとに変数名をつけて宣言する。
必要であれば、続けてデフォルトの値を指定する。
<?php
class Employee
{
public $name; //名前を表すプロパティ
public $state = ‘働いている’; //状態を表すプロパティ
public function work()
{
echo ‘書類を整理しています’, PHP_EOL;
}
}
プロパティにアクセスする
<?php
$yamada = new Employee();
$yamada->name = ‘山田';
echo $yamada->state, $yamada->name, ‘さん:’;
$yamada-> work();
//働いている山田さん:
//書類を整理しています
クラスの内側からのみアクセス(private)
<?php
class Employee
{
public $name;
private $state = ‘働いている’; //クラスの内側からしかアクセスできない
public function work();
{
echo ‘書類を整理しています’, PHP_EOL;
}
}
<?php
echo $yamada->state,$yamada->name,'さん:';
$yamada->work(),PHP_EOL;
//上記は、$stateにはアクセスできないため、エラーになります。
4. this
•「オブジェクトのインスタンス化」を行うと、クラスのメソッドで利用できる$thisという変数が自動的に定義される。
• $thisは自分自身のオブジェクトの参照。
•自分自身のオブジェクトのプロパティやメソッドへ$thisを用いてアクセスする。
例) 従業員の状態を「取得するメソッド」と「変更するメソッド」を実装する
<?php
class Employee
{
public $name;
private $state = ‘働いている’;
public function getState()
{
return $this->state;
}
public function setState($state)
{
$this->state = $state;
}
public function work ()
{
echo ‘書類を整理しています’, PHP_EOL;
}
}
<?php
$yamada = new Employee();
$yamada->name = '山田';
$yamada->setState('休憩している');
echo $yamada->name,'さんは',$yamada->getState(),PHP_EOL;
//山田さんは休憩している
外側からでは取得・変更が不可能だった$stateプロパティへは、クラスの内側のメソッドから$thisを用いてアクセスすることが可能になる。
「クラス定義時にプロパティを宣言しない」(非推奨)
<?php
$yamada = new Employee();
$yamada->job = 'プログラマ';
※PHPでは、宣言していないプロパティへの読み書きも可能(publicプロパティが作成される)
※しかし、どのタイミングでどのプロパティが宣言されたかを追うことが困難になる為、宣言した方がよい。
5.staticプロパティ(静的なプロパティ)
プロパティの宣言時に「static」をつけると、そのプロパティはクラスがインスタンス化されていなくても、読み書きすることができる。
staticプロパティへは、クラス名にダブルコロン(::)をつけてアクセスする。
[通常のプロパティ]
インスタンス化されたオブジェクト固有の変数
[静的なプロパティ]
そのクラスに共通の変数
例) 従業員クラスに会社を表す$companyというstaticプロパティを追加する。
<?php
class Employee
{
public $name;
public static $company = ‘技評技術社’;
}
echo ‘従業員はみんな’, Employee::$company, ‘に勤めています’ , PHP_EOL;
6.selfキーワード
- そのクラス自身を指し示すキーワードとなる。
- ダブルコロン(::)と一緒に用いる
- メソッド、定数、プロパティにアクセスすることができる。
- new演算子とあわせて、自分自身のクラスのインスタンスを生成する目的で使うことができる。
<?php
class Employee
{
public static $company = ‘技評技術社';
public function getCompany()
{
return self::$company;
{
}
※「5.staticプロパティ」のEmployee::$companyと同義
parentキーワード
P133
使い方はselfキーワードと同様。
7.定数
class クラス名
{
const 定数名 = 値;
}
<?php
class Employee
{
const PARTTIME = 0x01; //アルバイト
const REGULAR = 0x02; //正社員
const CONTRACT = 0x04; //契約社員
}
//正社員を表すクラス定数を取得
Employee::REGULAR
※クラス定数はクラス名にダブルコロン(::)と定数名を用いてアクセス
8.メソッド
class クラス名
{
アクセス修飾子[final][static]function[&]メソッド名([引数,...])
{
メソッドの実装
}
}
- メソッドはそのクラスの持つある機能をひとまとめにした、クラスに属する関数のようなもの。
- メソッドにもプロパティと同様に、アクセス修飾子によるアクセス制限があり、どこから呼び出すことのできるメソッドなのかが決められている。
- メソッドは関数の定義と変わりない。(クラスの中に定義すること、アクセス修飾子などのキーワードを用いること以外)
- 引数や返り値に参照を用いる場合は、関数のときと同様に&を用いて定義する。
9.staticメソッド(静的なメソッド)
- staticをつけて宣言
- インスタンス化されていなくても外部から直接呼び出すことができる(staticプロパティと同様)
- staticメソッドの中では$thisは使用することができない
<?php
class Employee
{
private static $company = '技評技術社’;
public static function getCompany()
{
return self::$company;
}
public static function setCompany($value)
{
self::$company = $value;
}
}
echo Employee::getCompany(),PHP_EOL; //社名の出力
Employee::setCompany(‘技術評論社’); //社名が変わったとき
- staticと宣言されていないメソッドをstaticに呼び出すと、警告が発生する。
- staticに呼び出したいメソッドはstaticキーワードを用いて宣言するべき。
静的メソッドは「クラス名::静的メソッド名()」と記述する。
代表的な例として、PEAR MDB2によるデータベース接続がある。
MDB2クラスで定義されている静的メソッドconnect()を呼び出す。
require 'MDB2.php'
$db = MDB2::connect('mysql://user:password@hostname/database');
- 変数$dbはオブジェクト。
- connectメソッドはオブジェクト型のデータを返す。
- MDB2クラスのもつ様々なメソッドを利用してデータベースとやりとりをする。
10.コンストラクタとデストラクタ
コンストラクタは、オブジェクトを生成するうえで必要なパラメータや、そのクラスのオプションなどを引数として受取り、プロパティにセットするという役割を果たす。
アンダースコア2つ(__)で始まる特別なメソッドを、PHPではマジックメソッドと呼ぶ。(ある決められた条件で自動的に呼び出されるメソッド)
class クラス名
{
public[final]fuction __construct([引数,...])
{
メソッドの実装
}
public[final]function __destruct([引数,...])
{
メソッドの実装
}
}
※ふりかえり:「4.this」のクラスの例
<?php
class Employee
{
public $name;
private $state = ‘働いている’;
public function getState()
{
return $this->state;
}
public function setState($state)
{
$this->state = $state;
}
public function work ()
{
echo ‘書類を整理しています’, PHP_EOL;
}
}
<?php
$yamada = new Employee();
$yamada->name = '山田';
$yamada->setState('休憩している');
echo $yamada->name,'さんは',$yamada->getState(),PHP_EOL;
//山田さんは休憩している
<コンストラクタを使う場合の書き方>
<?php
class Employee
{
const PARTTIME = 0x01;
const REGULAR = 0x02;
const CONTRACT = 0x04;
private $name;
private $type;
public function __construct($name, $type)
{
$this->name = $name;
$this->type = $type;
}
}
$yamada = new Employee(‘山田’, Employee::REGULAR);
↑この書き方
(オブジェクトを生成するうえで必要なパラメータや、そのクラスのオプションなどを引数にとる。プロパティにセット)
11.継承
class クラス名 extends 親クラス名
{
}
オーバーライド
- 親クラスに定義されたメソッドやプロパティを、子クラスに同じ名前で定義すると、子クラスではそのメソッドの実装が上書きされる。
- 親クラスで定義したメソッドと引数が違うとダメ。(E_STRICTレベルの警告)
- デフォルト値を持つ引数を追加で定義することは許容される。
- コンストラクタは、インスタンスを構築するための特別なメソッドのため、親クラスに定義されたコンストラクタと引数は違ってもよい。
※ふりかえり:「4.this」のクラスの例
<?php
class Employee
{
public $name;
private $state = ‘働いている’;
public function getState()
{
return $this->state;
}
public function setState($state)
{
$this->state = $state;
}
public function work()
{
echo ‘書類を整理しています’, PHP_EOL;
}
}
<?php
$yamada = new Employee();
$yamada->name = '山田';
$yamada->setState('休憩している');
echo $yamada->name,'さんは',$yamada->getState(),PHP_EOL;
//山田さんは休憩している
<Employeeクラスを親クラスに持つ、Programmerクラスを定義する場合>
<?php
class programmer extends Employee
{
public function work()
{
echo 'プログラムを書いています',PHP_EOL;
}
}
<デフォルト値を持つオプション引数を追加する場合>
<?php
class Programmer extends Employee
{
public function work($how = 'コンピュータで')
{
//....
}
}
finalキーワード
finalキーワードをつけてメソッドを宣言するとそのメソッドは継承された派生クラスでオーバーライドできなくなる。
<?php
class Employee
{
public $salary = 20;
public final function getSalary() //給料を取得するメソッド
{
return $this->salary;
}
}
class Programmer extends Employee
{
//メソッドをオーバーライドしてプログラマの給料は2倍にしたいが、finalキーワードを
//使っているので、エラーになる。
public function getSalary()
{
return $this->salary * 2;
}
}
12.stdClass(プロパティやメソッドを一切持たない標準クラス)
- stdClassは普通のクラスのようにnewして使うこともできる
<?php
$obj = new stdClass(); //空のクラスを初期化
$obj->some_member = 1; //プロパティに値を代入する(プロパティの値の初期化)
- 整数型など他の型からオブジェクト型へキャストを行うとstdClassクラスのインスタンスとなる
<整数型や文字列型などのスカラー値をオブジェクト型にキャストした場合>
「scalar」というプロパティにその値を持つインスタンスになる。
<?php
$var = 1;
$var_obj = (object)$var;
echo $var_obj->scalar,PHP_EOL; //1
$array = array(
'foo'=>2,
'var'=>3,
);
$array_obj = (object)$array;
echo $array_obj_obj->foo,PHP_EOL; //2
13.abstractキーワード(抽象クラス)
abstract クラス名
{
abstract アクセス権 fuction メソッド名([引数,...]);
}
- 共通の機能を抽象的な親クラスで定義
- 特有の機能は、個々の子クラスでそれぞれ実装
- 抽象クラスを継承したクラスを定義し、すべてのabstractメソッドを実装する必要がある
<?php
abstract class Employee
{
abstract public function work();
}
class Programmer extends Employee
{
public function work()
{
//...
}
}
14.implementsキーワード (インターフェイスの定義)
- 機能の実装を規格するための仕組み
- 実体のあるメソッドを定義できない
- 複数のインターフェイスを同時に実装することができる
- インターフェイスに定義されているメソッドを実装しないと致命的なエラーとなる
- 1つのクラスに実装した複数のインターフェイスが同名のメソッドを持っているとエラーとなる
interface インターフェイス名
{
インターフェイスの定義
}
class クラス名 implements インターフェイス名[,インターフェイス名...]
{
クラスの定義
}
- 「値を書き込む操作」と「読み込む操作」を必要とするインターフェイスを定義
- 設定ファイルを管理するようなクラス
<?php
interface Reader
{
public function read();
}
interface writer
{
public function write($value);
}
class Configure implements Reader,Writer
{
public function writer($value)
{
//書き込みの処理
}
public function read()
{
//読み込みの処理
}
}
定義済インターフェイス (P138)
- iterator
- RecursiveIterator
- SeekableIterator
- ArrayAccess
- Serializable
- Countable
インターフェイスを定義し、実装することのメリット
- 特定の機能(メソッド)を必ず実装していることが保証される
- 普通に引数のリストを定義すると渡された変数が正しくそのインターフェイスの実装かどうかが保証されず、インターフェイスを定義することのメリットがない。
渡された変数が特定のインターフェイスを実装しているかどうかをチェックする方法
- タイプヒンティング
- 型演算子
(P138-139)
15.クラスとオブジェクトの機能と特徴(P139-148)
クラスとオブジェクトには、様々な機能が用意されている
マジックメソッドとオーバーロード
遅延静的束縛
オートロード
16.名前空間 (P149-156)
- 関数名やクラス名の衝突を防ぐ
- 機能の参照をわかりやすくする
namespace 名前空間;
namespace 名前空間\サブ名前空間;
名前空間の影響を受けるのは、
- クラス
- 関数
- 定数(constによって定義されるものに限る)
※変数やdefineによって定義される定数には名前空間は適用されない。(名前空間がない場合と同様に参照される)
use \クラス名;
use \名前空間;
use \名前空間 as 別名;
use \名前空間\クラス名;
17.例外 (P157-161)
- プログラム実行時のエラーを適切に処理する機能
throw new 例外クラス名([メッセージ,[エラーコード,[前の例外オブジェクト]]]);
try{
処理
}catch (例外クラス名 変数名){
例外処理
}
18.参照
- PHPにおける参照とは、ある値を指し示すものをいう
- 変数のもつある値の格納領域を指し示す、別の名前をもつ変数のことを参照という
オブジェクトの参照
<?php
$a = 10;
$b =& $a;
$c = $a;
$b = 20;
• 変数$aを整数値10で初期化
• 変数$bに参照代入演算子(&)を用いて$aの代入
• $bは、$aの参照となる
• $aと$bは同じ領域を指し示す変数となる
• $cには通常の代入演算子で$aの代入を行う為、値(10)が$cのもつ新しい領域にコピーされる
• $b = 20;により、$aも20に変更される
参照変数への再代入
<?php
$a = 10;
$ref =& $a;
$ref = 20;
echo $a, PHP_EOL; //20
<?php
$a = 10;
$c = 20;
$ref =& $a;
$ref =& $c;
$ref = 30;
echo $a,PHP_EOL; //10
echo $c,PHP_EOL; //30
$refは新しく$cへの参照を表す変数として作られる
配列と参照(P163)
<?php
function array_pass($array){
$array[0]*=2;
$array[1]*=2;
}
function array_pass_ref(&$array){
$array[0]*=2;
$array[1]*=2;
}
$a = 10;
$b = 20;
$array = array($a,&$b);
array_pass($array);
echo $a,PHP_EOL; //10
echo $b,PHP_EOL; //40
オブジェクトの参照
(※&を使うのは非推奨)
<?php
$a = new stdClass();
$b = $a;
$c =& $a;
- $aはnew演算子によってインスタンス化されたstdClassクラスのオブジェクトへの参照を受け取る
(オブジェクトを表すIDを保持する値への参照になっている)
- 「$b = $a;」は、そのIDが$bにコピーされる。結果として同じオブジェクトを指し示す変数となる
- 「$c =& $a;」は、$cは$aの値(オブジェクトのID1の持つオブジェクトへの参照)の格納領域を参照している変数となる。
結果として、$a、$b、$c、はどれも同じオブジェクトを指し示す。
どの変数に変更を加えても同じオブジェクトを変更することになる。
リファレンスカウントとオブジェクトの寿命(P166-168)
変数のリファレンスとコピーオンライト(P169-170)
インターフェイス
- クラスがどのように振る舞うかを定義するためのもの
- メソッドのプロトタイプと定数の定義を行い、インターフェイスを実装するクラス側でメソッドの実装を記述する。
[構文]
interface インターフェイス名
{
[function 関数名();
]
}
interface printable
{
function printoutput();
}
class ImageComponent implements printable
{
function printoutput()
}
echo "画像を印刷する";
}
}
- 別のインターフェイスを継承したインターフェイスも作れる
- 継承元のインターフェイスで宣言されているメソッドと同じ名前のメソッドの子インターフェイス側での 再宣言はできない。
トレイト
- トレイトはクラス階層の枠を超えてコードを再利用するための仕組み。
- クラス階層上で共通の先祖を持たないクラスどうしでも機能を共有できる。
[構文]
trait traitname[ extends baseclass]
{
[use traitname,[traitname,...];]
[visibility $property[=value];...]
[function functionname(args){
//code
}
...
]
}
抽象メソッド
コンストラクタ
- クラスのオブジェクトを作成する際に、クラス名の後に引数を指定できる。
- ここで指定した引数は、そのクラスのコンストラクタに渡される。
- コンストラクタとは、クラスのプロパティを初期化する特別な関数。
- コンストラクタは、クラス内で、__construct()という名前の関数として定義する。
class person
{
function __construct($name,$age)
{
$this->name = $name;
$this->age = $age;
}
}
class person
{
public $name, $address, $age;
function __construct($name, $address, $age)
{
$this->name = $name;
$this->address = $address;
$this->age = $age;
}
}
class Employee extends person
{
public $position, $salary;
function __construct($name, $address, $age, $position, $salary)
{
parent::__construct($name, $address, $age);
$this->position = $position;
$this->salary = $salary;
}
}
デストラクタ
- オブジェクトへの最後の参照が破棄されたり、スクリプトが終了した場合、デストラクタが呼び出される。
- PHPはスクリプトの終了時に自動的にリソースの後始末を行うのであまり使い道はない。
- オブジェクトが破棄されたことをログに記録したい場合などには便利。
class Building
{
function __destruct()
{
echo "ビルが破壊されつつある";
}
}
内部検査
- プログラムの中であるオブジェクトの性質を調べる機能のこと。
- 任意のクラスやオブジェクトを操作するコードを書く。
コードを書く際に、どんなメソッドやプロパティがあるのかを知っておく必要がない。
それらの情報は、実行時に取得できる。この機能を使い、汎用的なデバッガ、シリアライザ、プロファイラを作れる。
クラスの存在を調べる
class_exists()
文字列で指定された関数が存在するかどうかを論理値で返す。get_declared_classes()
定義されているクラスを配列で返すもので、
返された配列の中にクラスが存在するかを調べる。
クラスで定義されているメソッドやプロパティを取得する。
クラス名を受取って結果を配列で返す。
クラスを指定するには、その名前を直接書くか、文字列をして指定するか、変数で指定するかのいずれかになる。
get_class_method()
メソッド名を並べた配列を返すget_class_vars()
連想配列を返す。プロパティ名がその値に関連付けられる。親クラスから継承したプロパティも含まれる。
親クラスを取得する
get_parent_class()
宣言されている全クラスの表示
function displayClasses()
{
$classes = get_declared_classes(); //定義されているクラスを配列で返す,配列の中にクラスが存在するかを調べる
foreach ($classes as $class){
echo "{$class}についての情報<br />";
echo "クラスのメソッド <br />";
$methods = get_class_methods($class); //メソッド名を並べた配列を返す
if(!count($methods)){
echo "<i>なし</i><br />";
}
else {
foreach ($methods as $method){
echo "<b>{$method}</b>()<br />";
}
}
echo "クラスのプロパティ<br />";
$properties = get_class_vars($class);
if(!count($properties)){
echo "<i>なし</i><br />";
}
else{
foreach(array_keys($properties) as $property){
echo "<b>\${$property}</b><br />";
}
}
echo "<hr />";
}
}
オブジェクトの調査
- あるオブジェクトがどのクラスに属するのかを調べる
- それが本当にオブジェクトであるかどうかを、is_object()関数で調べる
そのクラスをget_class関数で取得する
get_object_vars()そのオブジェクトに設定されているプロパティの配列を返す
get_object_vars()は値が設定されているプロパティしか返さない
内部検査のサンプル
シリアライズ
- オブジェクトをバイトストリームに変換し、ファイルに保存できるようにすること。
- PHPのセッションは、オブジェクトの内容を自動的に保存したり取得したりする。
- シリアライズはPHPのセッションと組み合わせて用いられる。
- セッションがあなたに代わってシリアライズ処理を行ってくれる。
2つの関数を呼び出すだけでよい
- serialize()
- unserialize()
$encodes = serialize(something);
$encodes = unserialize(encoded);
どの変数をセッションに保存するのかをPHPへ指示する。後はセッションが自動的に持続してくれる。
PHPでは、オブジェクトのシリアライズや復元の際に、処理を挟み込むための仕組みが用意されている。
sleep()とwakeup()
__sleep()メソッド
オブジェクトがシリアライズされる直前に呼び出す
- データベースとの接続をクローズ
- 保存していないデータを書き出す
__wakeup()
- バイトストリームからオブジェクトを復元した直後に呼び出す。
- データベースとの接続を再度オープン
- 初期化作業