Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
PHP classの教室 | PDF
[go: Go Back, main page]

8時間耐久
PHP classの教室

 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
Who am I

 id: yando
 or yandod
流しのPHPer
CandyCane


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)
by jepoirrier




 関数を使ったPHP
8時間耐久PHP classのクラス / Yusuke Ando (@yando)
PHP超基礎

        <?phpタグ
           変数
       ダブルクオート
      シングルクオート


8時間耐久PHP classのクラス / Yusuke Ando (@yando)
変数、クオート等
<?php
echo 100; //ここはPHP
?>
ここはそのまま出力される
<?php
$a = 100;
$b = "t$an";
$c = 't$an';
echo $b;
echo $c;
?>                   変数展開は$bのみ

<!-- 空白でハマるのでファイルの最後のタグは閉じない -->

 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
関数とは

  処理に名前を付ける
引数(ひきすう)を受け取る
  好きな処理をする
 返り値(かえりち)を返す


8時間耐久PHP classのクラス / Yusuke Ando (@yando)
function
<?php
function 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)
名前の大文字小文字
<?php
function 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)
スコープ
<?php
$out = '1000';
function hoge() {
  $in = 'ABCD';
  echo $out;
                      hoge()内で有効なのは
  echo $etc;
}                           $inのみ
function fuga() {
  $etc = 'XYZ';
}
hoge();
hoge();                  $inが有効なのは
echo $in;                 hoge()内のみ

  8時間耐久PHP classのクラス / Yusuke Ando (@yando)
引数の順番
<?php
function hoge($a) {
}
function fuga($a, $b =0){
}
function moge($a=null,$b=null,$c) {
}
hoge(1); //OK
fuga(1); //OK
moge(1,2,3); //OK
hoge();
fuga();                   必須の引数が指定されて
moge(1,2);                     いないとエラー

 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
二重定義

<?php
function hoge() {
}
function hoge() {
}
                          FATALエラー
                         真っ白になります




   8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習1
   関数を作ってください
    引数: 名前、性別
       結果:
     男なら○○くん
    女なら○○ちゃん

8時間耐久PHP classのクラス / Yusuke Ando (@yando)
作例1
<?php
function 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
<?php
function 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)
<?php
                                             作例3
function getLabel($name, $sex, $age=0, $coloring=false) {    echo getLabel('つとむ', 1); //つとむくん
     if ($sex == '1') {                                      echo getLabel('やよい', 2); //やよいちゃん
            $suffix = 'くん';                                    echo getLabel('つとむ', 1,10); //つとむくん
            $color = 'blue';                                 echo getLabel('やよい', 2,8); //やよいちゃん
            if ( $age >= 12) {                               echo getLabel('つとむ', 1,12); //つとむ君
                  $suffix = '君';                               echo getLabel('やよい', 2,20); //やよいさん
            }                                                echo getLabel('つとむ', 1,0,true);
     } else {                                                //<span style='color:blue'>つとむくん</span>
            $suffix = 'ちゃん';                                   echo getLabel('やよい', 2,0,true);
            $color = 'pink';                                 //<span style='color:pink'>やよいちゃん</span>
            if ( $age >= 12) {
                  $suffix = 'さん';
            }
     }
     $str = "<span style='color:$color'>". $name . $suffix .
"</span>n";
     if (!$coloring) {
            $str = $name . $suffix . "n";
     }
     return $str;
}



             8時間耐久PHP classのクラス / Yusuke Ando (@yando)
練習4

練習1,2,3の機能は維持して
学校種別を名前の後に表示
 することもできるように
  例: つとむくん(小)


8時間耐久PHP classのクラス / Yusuke Ando (@yando)
<?php
                                           作例4                } else if ( $age >= 18 && $age <= 21 ) {
function getLabel($name, $sex, $age=0, $coloring=false,              $suffix .= "(大)";
$school=false ) {                                             }
     if ($sex == '1') {                                       $str = "<span style='color:$color'>".
           $suffix = 'くん';                                   $name . $suffix . "</span>n";
           $color = 'blue';                                   if (!$coloring) {
           if ( $age >= 12) {                                        $str = $name . $suffix . "n";
                  $suffix = '君';                                }
           }                                                  return $str;
     } else {                                             }
           $suffix = 'ちゃん';
           $color = 'pink';                               echo   getLabel('つとむ',   1); //つとむくん
           if ( $age >= 12) {                             echo   getLabel('やよい',   2); //やよいちゃん
                  $suffix = 'さん';                           echo   getLabel('つとむ',   1,10); //つとむくん
           }                                              echo   getLabel('やよい',   2,8); //やよいちゃん
     }                                                    echo   getLabel('つとむ',   1,12); //つとむ君
     if ( $age >= 6 && $age <= 11 ) {                     echo   getLabel('やよい',   2,20); //やよいさん
           $suffix .= "(小)";                                echo   getLabel('つとむ',   1,10,false,true); //つとむくん
     } else if ( $age >= 12 && $age <= 14 ) {             echo   getLabel('やよい',   2,8,false,true); //やよいちゃん
           $suffix .= "(中)";                                echo   getLabel('つとむ',   1,12,false,true); //つとむ君
     } else if ( $age >= 15 && $age <= 17 ) {             echo   getLabel('やよい',   2,20,false,true); //やよいさん
           $suffix .= "(高)";



            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)
クラス
<?php
class MyClass {
   const HOGE =100;
   public $some_string = こんにちは ;
   public $num;
   public function sayHello() {
      echo Hello ;
   }
}
       classでクラスを宣言
     プロパティ、定数、メソッド
      をクラス内に宣言できる
 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
インスタンス化
<?php
$obj = new MyClass();
$obj->sayHello();
$obj->some_string = AAAA ;




  クラスとして宣言した処理を
 利用する為のオブジェクトを作成
アロー演算子(->)でメソッド等を指定

 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
$this
<?php
class MyClass {
   const HOGE =100;
   public $some_string = こんにちは ;
   public function sayHello() {
      echo $this->some_string;
   }
}



    自分自身を指すオブジェクト
      メソッド内で使える
 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
$this
<?php
class 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)
マジックナンバー
<?php
$obj = new MyClass();
$obj->sex = 1;
$obj->school = 1;



ソースコード内にある「1」
  後で見ても意味不明
別の意味の1かもしれない
 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
const
<?php
class MyClass {
   const HOGE =100;
   public function sayHello() {
      echo self::HOGE; // MyClass::HOGE でもOK
   }
}



  オブジェクトに属する定数を設定
  self:: か クラス名:: で参照できる

 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)
コンストラクタ
<?php
class MyClass {
      public $name;
   public __construct($name) {
      $this->name = $name;
   }
}


__construct というメソッドを作成
クラスをnewしてインスタンス化時に
        必ず実行される!

 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)
アクセス修飾子
<?php
class MyClass {
   const HOGE =100;
   private $some_string = こんにちは ;
   public function sayHello() {
      echo Hello ;
   }
}

メソッドやプロパティへのクラス外から
    のアクセスを制限できる
  public / private / protected
 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
アクセス修飾子

 外部アクセスが不要な
      プロパティ
       メソッド
をprivateにする事が多い

8時間耐久PHP classのクラス / Yusuke Ando (@yando)
オートロード
<?php
function __autoload($class_name) {
    include $class_name . '.php';
}

$obj  = new MyClass1();
$obj2 = new MyClass2();

クラス名とファイル名を整理しておくと
   クラスを自動的に読み込める
 (クラス定義のみ別ファイルが理想)
 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
namespace
<?php
namespace myname;
class MyClass {}
function myfunction() {}
const MYCONST = 1;


$c = new mynameMyClass;

さらには namespace という文法を使っ
 てフォルダ階層とクラスを対応させる
  方法がPHP5.3以降で使えるように

 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
static
<?php
class MyClass {
   const HOGE =100;
   private $some_string = こんにちは ;
   public static function sayHello() {
      echo Hello ;
   }
}
echo MyClass::sayHello();


  staticが指定されたメソッドは
 インスタンスを作らずに実行できる
  8時間耐久PHP classのクラス / Yusuke Ando (@yando)
staticの落とし穴
<?php
class MyClass {
   const HOGE =100;
   private $some_string = こんにちは ;
   public static function sayHello() {
      echo $this->some_string;
   }
}
echo MyClass::sayHello();


     staticが指定されたメソッドは
           $thisを使えない!
  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)
継承
<?php
class MyClass {
   public function hoge() {
      echo a ;
   }
}
class MySubClass extends MyClass {}


$obj = new MySubClass();
$obj->hoge();

      既存のクラスを再利用して
         クラスを作る
 8時間耐久PHP classのクラス / Yusuke Ando (@yando)
parent::
<?php
class 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)
抽象クラス
<?php
abstract class BaseClass {
  abstract protected function fuga();
  public function hoge() {
     echo a ;
  }




   親クラスになる為だけのクラス



  8時間耐久PHP classのクラス / Yusuke Ando (@yando)
インターフェース
<?php
interface iihito {
   public function sayHello();
}


class Person implements iihito {
   public function sayHello(){
   }
}



  特定のメソッドの保持を強制する

  8時間耐久PHP classのクラス / Yusuke Ando (@yando)
トレイト
<?php
trait 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は

•複雑なコードを整理
•コードの拡張性を確保
•コードをメンテナンスする
クラス=難しい ではなく難しい問題
   を解決する為の機能です

8時間耐久PHP classのクラス / Yusuke Ando (@yando)

PHP classの教室