PHP5上級試験/準上級試験の上級合格に挑戦(15) プログラミングPHP第3版 5章〜6章

# 5章　配列

配列の書き方は、[]を使って短く書くことも可能

```index.php
$days = array('gasket' => 15.29, 'wheel' =>75.25, 'tire' => 50.0);
//上記はこうも書ける
$days =['gasket' => 15.29, 'wheel' =>75.25, 'tire' => 50.0];
```
range()で、文字列が指定された場合、最初の文字を使って範囲を作成する

```index.php
echo range("aaa","zzz"); //これはrange("a","z"）と同じ
```
配列の要素数を数えるcount()・sizeof()だが、値がないものは数えない。

```index.php
$days = array('gasket' => 15.29, 'wheel' =>75.25, 'tire' => 0 );
unset($days['tire']); //値を削除してみた
echo count($days); //出力は２　（unsetがなければ３）
```
多次元配列の配列は変数展開に波括弧を使う。

```index.php
$row0 = array(1,2,3);
$row1 = array(4,5,6);
$row2 = array(7,8,9);
$multi = array($row0,$row1,$row2);
echo ("２行目、0列目の値は{$multi[2][0]}です。");
//２行目、0列目の値は7です。と出力
```

あるキーが存在するかのチェックについて、値がどうであるかに関わらず、キーが有るかどうかを調べる場合はarray_key_exists（）を使う。isset()だと、値がNULLの場合Falseが返るので注意。

```index.php
$a = array('php' => NULL);
if (isset($a['PHP'])){
 echo 'isset:'true';
}
if (array_key_exists($a['PHP'])){
 echo 'array_key_exists:'true';
}
```

# 6章　オブジェクト

黒本にはない「トレイト」というのがある
「クラス階層の枠を超えてコードを再利用するための仕組み」ということ
これを使うとクラス階層で共通の先祖を持たないクラス同士でも機能を共有できる

```index.php
//トレイト
trait Logger{
  public function log($logString){
    $classname = __CLASS__;
    echo date("Y-m-d h:i:s", time()) . ":[{$classname}] {$logString} <br>";
  }
}

class User{
  use Logger; //トレイトを使う宣言
  public $name;
  function __construct($name = ''){
    $this->name = $name;
    $this->log("Created user '{$this->name}'"); //ここでトレイトの関数を使ってる
  }
  function __toString(){
    return $this ->name;
  }
}

class UserGroup{
  use Logger; //トレイトを使う宣言
  public $users = array();
  public function includesUser($user){
      return in_array($user,$this->users);
  }
  public function addUser(User $user){
    if (!$this->includesUser($user)){
      $this->users[]=$user;
      $this->log("Added user '{$user}' to group"); //ここでトレイトの関数を使ってる
    }
  }
}

$group = new UserGroup;
$group->addUser(new User("Franklin"));


```

出力
2021-03-30 02:55:03:[User] Created user 'Franklin'
2021-03-30 02:55:03:[UserGroup] Added user 'Franklin' to group

特に難しいところはないはず。
サブクラスとかでもないクラスでトレイトを使用しており、再利用もできている。

ちなみに、既存のトレイトを使って新しいトレイトを作ることも可能。
ただし、名前空間がない場合、同名のメソッドは使えない

```index.php
trait First{
  public function doFirst(){
    echo "First<br>";
  }
}

trait Second{
  public function doSecond(){
    echo "second<br>";
  }
}

trait Third{
  use First, Second; //他のトレイトを利用、複数useできる
  public function doAll(){
    $this->doFirst(); //普通に使える
    $this->doSecond();//普通に使える
  }
}


class Combined{
  use Third; //これだけでもOK
}

$object = new Combined;
$object -> doAll();

```
出力
First
second


同じ名前のコマンドがあっても、insteadofで、優先するコマンドを指定することができる。
FMTは下記の通り。
優先するトレイト名::メソッド名 insteadof 優先されるトレイト名

他にも、トレイトのメソッドをエイリアス化して使用することも可能。
この場合のFMTはトレイト名::メソッド名 as エイリアス名（自由に名前をつけられる）

上記２つを使う場合、 use トレイト名１,トレイト名2{}の中に入れていくことにも注意。
               

```index.php
trait Command{
  function run(){
    echo "コマンドを走らせます<br>";
  }
}

trait Marathon{
  function run(){
    echo "マラソンを走ります<br>";
  }
}

class Person{
  use Command, Marathon {
    Command::run as runCommand; //runメソッドが使われたら、Marathon::runを優先する
    Marathon::run insteadof Command; // runCommandはCommandのRunメソッドを実行
    } 
}

$person = new Person;
$person->run();
$person->runCommand();

```