php classの教室
DESCRIPTION
PHPで関数は使えるけれどオブジェクト指向はよくわからないという人向けの勉強会の資料です。 Ustream録画 (1/5) http://www.ustream.tv/recorded/21256905 67分 (2/5) http://www.ustream.tv/recorded/21253084 80分 (3/5) http://www.ustream.tv/recorded/21254139 60分 (4/5) http://www.ustream.tv/recorded/21254817 24分 (5/5) http://www.ustream.tv/recorded/21255084 6分TRANSCRIPT
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
PHP classの教室8時間耐久
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
Who am I
id: yandoor yandod
流しのPHPerCandyCane
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
本日の対象者PHPを使っている
関数はなんとなくわかるclassを理解したい
プリンス
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
僕には理解不能だった
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
実際のコードからアプローチしてオブジェクト指向の機能を学びます
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
本日のメニュー
関数を使ったPHPオブジェクト指向の基礎コードの拡張性を上げるコードをメンテナンスする
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
関数を使ったPHPby jepoirrier
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
PHP超基礎
<?phpタグ変数
ダブルクオートシングルクオート
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
変数、クオート等<?phpecho 100; //ここはPHP?>ここはそのまま出力される<?php$a = 100;$b = "\t$a\n";$c = '\t$a\n';echo $b;echo $c;?>
<!-- 空白でハマるのでファイルの最後のタグは閉じない -->
変数展開は$bのみ
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
関数とは
処理に名前を付ける引数(ひきすう)を受け取る
好きな処理をする返り値(かえりち)を返す
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
function<?phpfunction hoge() { return date(‘Y-m-d’);}function fuga($w = null) { if (is_null($w)) { $w = date(‘w’); } $list = array(‘日’,’月’,’火’,’水’,’木’,’金’,’土’); return $list[$w];}echo hoge(); // ‘2012-03-21’ などと表示echo fuga(3); // ‘水’と表示
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
functionの細かいとこ
名前の大文字小文字スコープ
引数の順番2重定義
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
名前の大文字小文字<?phpfunction hoge() { return date('Y-m-d');}echo hoge(); // ‘2012-03-21’ などと表示echo Hoge();echo HOGE();echo hogE();$a = 'hoge';echo $a(); 全部同じ結果
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
スコープ
hoge()内で有効なのは$inのみ
<?php$out = '1000';function hoge() { $in = 'ABCD'; echo $out; echo $etc;}function fuga() { $etc = 'XYZ';}hoge();hoge();echo $in;
$inが有効なのはhoge()内のみ
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
引数の順番<?phpfunction hoge($a) {}function fuga($a, $b =0){}function moge($a=null,$b=null,$c) {}hoge(1); //OKfuga(1); //OKmoge(1,2,3); //OKhoge();fuga();moge(1,2);
必須の引数が指定されていないとエラー
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
二重定義
<?phpfunction hoge() {}function hoge() {} FATALエラー
真っ白になります
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習1関数を作ってください引数: 名前、性別
結果:男なら○○くん女なら○○ちゃん
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例1<?phpfunction getLabel($name, $sex) { if ($sex == '1') { $suffix = 'くん'; } else { $suffix = 'ちゃん'; } return $name . $suffix;}
echo getLabel('つとむ', 1); //つとむくんecho getLabel('やよい', 2); //やよいちゃん
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習2
練習1の機能は維持して年齢も引数で受け取り
12歳以上なら○○君/○○さん
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例2<?phpfunction getLabel($name, $sex, $age=0) { if ($sex == '1') { $suffix = 'くん'; if ( $age >= 12) { $suffix = '君'; } } else { $suffix = 'ちゃん'; if ( $age >= 12) { $suffix = 'さん'; } } return $name . $suffix . "\n";}echo getLabel('つとむ', 1,10); //つとむくんecho getLabel('やよい', 2,20); //やよいさん
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習3練習1,2の機能は維持して
男の子なら青女の子ならピンク
になるようにタグで囲む。(タグなしの機能も残す)
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例3<?phpfunction getLabel($name, $sex, $age=0, $coloring=false) { if ($sex == '1') { $suffix = 'くん'; $color = 'blue'; if ( $age >= 12) { $suffix = '君'; } } else { $suffix = 'ちゃん'; $color = 'pink'; if ( $age >= 12) { $suffix = 'さん'; } } $str = "<span style='color:$color'>". $name . $suffix . "</span>\n"; if (!$coloring) { $str = $name . $suffix . "\n"; } return $str;}
echo getLabel('つとむ', 1); //つとむくんecho getLabel('やよい', 2); //やよいちゃんecho getLabel('つとむ', 1,10); //つとむくんecho getLabel('やよい', 2,8); //やよいちゃんecho getLabel('つとむ', 1,12); //つとむ君echo getLabel('やよい', 2,20); //やよいさんecho getLabel('つとむ', 1,0,true);//<span style='color:blue'>つとむくん</span>echo getLabel('やよい', 2,0,true);//<span style='color:pink'>やよいちゃん</span>
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習4
練習1,2,3の機能は維持して学校種別を名前の後に表示することもできるように例: つとむくん(小)
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例4<?phpfunction getLabel($name, $sex, $age=0, $coloring=false, $school=false ) { if ($sex == '1') { $suffix = 'くん'; $color = 'blue'; if ( $age >= 12) { $suffix = '君'; } } else { $suffix = 'ちゃん'; $color = 'pink'; if ( $age >= 12) { $suffix = 'さん'; } } if ( $age >= 6 && $age <= 11 ) { $suffix .= "(小)"; } else if ( $age >= 12 && $age <= 14 ) { $suffix .= "(中)"; } else if ( $age >= 15 && $age <= 17 ) { $suffix .= "(高)";
} else if ( $age >= 18 && $age <= 21 ) { $suffix .= "(大)"; } $str = "<span style='color:$color'>". $name . $suffix . "</span>\n"; if (!$coloring) { $str = $name . $suffix . "\n"; } return $str;}
echo getLabel('つとむ', 1); //つとむくんecho getLabel('やよい', 2); //やよいちゃんecho getLabel('つとむ', 1,10); //つとむくんecho getLabel('やよい', 2,8); //やよいちゃんecho getLabel('つとむ', 1,12); //つとむ君echo getLabel('やよい', 2,20); //やよいさんecho getLabel('つとむ', 1,10,false,true); //つとむくんecho getLabel('やよい', 2,8,false,true); //やよいちゃんecho getLabel('つとむ', 1,12,false,true); //つとむ君echo getLabel('やよい', 2,20,false,true); //やよいさん
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
なんか
ヤバイ
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
長さがヤバイ
エディタに収まらなくなりつつある
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
マジックナンバー
この数字や文字を後で変更する時にミスりそう
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
多すぎる引数
呪文と化した引数
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
複数の関数に分割?
共通部分が多く引数も多い
簡単には分割できない
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
分割するにも
扱っている変数が多い
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
関数の弱点
引数と返り値は複雑なデータを扱うには貧弱(データが単純ならOK)
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
ダークサイドの誘惑
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
一見綺麗だが…このあたりの変数名が衝突した瞬間にアウト
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
再利用性に乏しいデータをセットしなおさ
す必要がある
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
つまりあのプラグインを入れた
ら真っ白に… ここでは動いているけど、あっちではダメ
似たような関数がたくさんコピペされている
手出しできない密林がコードにある
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
オブジェクト指向の基礎by wocrig
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
最初に覚える事
•クラス•プロパティ•定数•メソッド•インスタンス
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
クラス
classでクラスを宣言プロパティ、定数、メソッドをクラス内に宣言できる
<?phpclass MyClass { const HOGE =100; public $some_string = ‘こんにちは’; public $num; public function sayHello() { echo ‘Hello’; }}
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
インスタンス化
クラスとして宣言した処理を利用する為のオブジェクトを作成
アロー演算子(->)でメソッド等を指定
<?php$obj = new MyClass();$obj->sayHello();$obj->some_string = ‘AAAA’;
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
$this
自分自身を指すオブジェクトメソッド内で使える
<?phpclass MyClass { const HOGE =100; public $some_string = ‘こんにちは’; public function sayHello() { echo $this->some_string; }}
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
$this
プロパティはメソッドを跨って参照や更新ができる
<?phpclass MyClass { public $some_string = ‘こんにちは’; public function sayHello() { echo $this->some_string; } public function change() { $this->some_string = ‘こんばんわ’; }}
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
オブジェクトには
関数には出来なかった引数・返り値以外の
データを扱う方法がある!
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
これを整理してみる
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習5クラスを作ってくださいプロパティ: 名前、性別メソッド:下記を返す
男なら○○くん女なら○○ちゃん
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例5マジックナンバーがある
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
マジックナンバー
ソースコード内にある「1」後で見ても意味不明
別の意味の1かもしれない
<?php$obj = new MyClass();$obj->sex = 1;$obj->school = 1;
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
const
オブジェクトに属する定数を設定self:: か クラス名:: で参照できる
<?phpclass MyClass { const HOGE =100; public function sayHello() { echo self::HOGE; // MyClass::HOGE でもOK }}
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例5.1
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
初期化をどうするか
名前と性別の初期化が必要引数
直接セット初期化用メソッド
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
引数
破滅の予感
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
直接セット
面倒くさい
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
初期化用メソッド
忘れそう
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
コンストラクタ
__construct というメソッドを作成クラスをnewしてインスタンス化時に
必ず実行される!
<?phpclass MyClass { public $name; public __construct($name) { $this->name = $name; }}
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例5.2
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習6
コンストラクタで年齢も受け取りプロパティへ
12歳以上なら○○君/○○さん
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例6
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
その他の機能
•アクセス修飾子•オートロード•namespace•static
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
アクセス修飾子
メソッドやプロパティへのクラス外からのアクセスを制限できる
public / private / protected
<?phpclass MyClass { const HOGE =100; private $some_string = ‘こんにちは’; public function sayHello() { echo ‘Hello’; }}
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
アクセス修飾子
外部アクセスが不要なプロパティメソッド
をprivateにする事が多い
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
オートロード
クラス名とファイル名を整理しておくとクラスを自動的に読み込める
(クラス定義のみ別ファイルが理想)
<?phpfunction __autoload($class_name) { include $class_name . '.php';}
$obj = new MyClass1();$obj2 = new MyClass2();
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
namespace
さらには namespace という文法を使ってフォルダ階層とクラスを対応させる方法がPHP5.3以降で使えるように
<?phpnamespace my\name;class MyClass {}function myfunction() {}const MYCONST = 1;
$c = new \my\name\MyClass;
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
static
staticが指定されたメソッドはインスタンスを作らずに実行できる
<?phpclass MyClass { const HOGE =100; private $some_string = ‘こんにちは’; public static function sayHello() { echo ‘Hello’; }}echo MyClass::sayHello();
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
staticの落とし穴
staticが指定されたメソッドは$thisを使えない!
<?phpclass MyClass { const HOGE =100; private $some_string = ‘こんにちは’; public static function sayHello() { echo $this->some_string; }}echo MyClass::sayHello();
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
staticはステートレス
staticはインスタンス毎のデータが扱えず、実質グローバル関数と同じ
補助的な処理などに利用されるが、多用するとグローバル関数と同じ問題を引き起こします
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
コードの拡張性を上げるby MarkyBon
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
クラスを拡張する機能
•継承•抽象クラス•インターフェース•トレイト•マジックメソッド
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
継承
既存のクラスを再利用してクラスを作る
<?phpclass MyClass { public function hoge() { echo ‘a’; }}class MySubClass extends MyClass {}
$obj = new MySubClass();$obj->hoge();
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
parent:: <?phpclass MyClass { public function hoge() { echo ‘a’; }}class MySubClass extends MyClass { public function Hello() { parent::hoge(); }}
メソッドを再利用して新しい処理を作成
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
継承元のクラスは親クラス、スーパークラスと呼ぶparent:: で参照できる
既存のメソッドを上書きも可privateは触れない
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習7
クラスを作ってくださいKidを継承したHtmlKid
出力時に男子は青、女子はピンク
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習7
Kid.php - 先程のコードHtmlKid.php - 新規test.phpから実行
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例7
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
抽象クラス
親クラスになる為だけのクラス
<?phpabstract class BaseClass { abstract protected function fuga(); public function hoge() { echo ‘a’; }
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
インターフェース
特定のメソッドの保持を強制する
<?phpinterface iihito { public function sayHello();}
class Person implements iihito { public function sayHello(){ }}
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
トレイト
特定のメソッドをクラスに注入する
<?phptrait iihito { public function sayHello() { }}
class Person{ use iihito;}
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
最初に思う疑問継承
抽象クラスインターフェース
トレイトなぜ似たような機能が?
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
継承は1つのみ
インタフェーストレイトは柔軟
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
マジックメソッド
クラスに作ると特定のタイミングで自動的に実行され
るすごいメソッド
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
マジックメソッド
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
コードをメンテナンスするby flightlog
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
コードをメンテナンス
•バージョン管理•ユニットテスト•継続ビルド
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
バージョン管理
クラス名とファイル名が対応すると日付をファイル名に付ける等は無理
ファイルの履歴をgitなどに保持させる
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
ユニットテスト
クラスの各メソッドの正しい動作をプログラムとしてテストする
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
テストケース
テストケースと呼ばれるコードを作成
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
テスト実行 $ phpunit ./tests/PHPUnit 3.5.14 by Sebastian Bergmann.
..
Time: 0 seconds, Memory: 6.00Mb
OK (2 tests, 4 assertions)
phpunitのセットアップは環境によって様々
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
カバレッジ
テストされていない部分は危険性が高い
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
継続ビルド
ユニットテストをコミット毎に自動実行コードが壊れたらすぐに検知
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
まとめ
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
classは
•複雑なコードを整理•コードの拡張性を確保•コードをメンテナンスする
クラス=難しい ではなく難しい問題を解決する為の機能です