5章 配列
配列の書き方は、[]を使って短く書くことも可能
$days = array('gasket' => 15.29, 'wheel' =>75.25, 'tire' => 50.0);
//上記はこうも書ける
$days =['gasket' => 15.29, 'wheel' =>75.25, 'tire' => 50.0];
range()で、文字列が指定された場合、最初の文字を使って範囲を作成する
echo range("aaa","zzz"); //これはrange("a","z")と同じ
配列の要素数を数えるcount()・sizeof()だが、値がないものは数えない。
$days = array('gasket' => 15.29, 'wheel' =>75.25, 'tire' => 0 );
unset($days['tire']); //値を削除してみた
echo count($days); //出力は2 (unsetがなければ3)
多次元配列の配列は変数展開に波括弧を使う。
$row0 = array(1,2,3);
$row1 = array(4,5,6);
$row2 = array(7,8,9);
$multi = array($row0,$row1,$row2);
echo ("2行目、0列目の値は{$multi[2][0]}です。");
//2行目、0列目の値は7です。と出力
あるキーが存在するかのチェックについて、値がどうであるかに関わらず、キーが有るかどうかを調べる場合はarray_key_exists()を使う。isset()だと、値がNULLの場合Falseが返るので注意。
$a = array('php' => NULL);
if (isset($a['PHP'])){
echo 'isset:'true';
}
if (array_key_exists($a['PHP'])){
echo 'array_key_exists:'true';
}
6章 オブジェクト
黒本にはない「トレイト」というのがある
「クラス階層の枠を超えてコードを再利用するための仕組み」ということ
これを使うとクラス階層で共通の先祖を持たないクラス同士でも機能を共有できる
//トレイト
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
特に難しいところはないはず。
サブクラスとかでもないクラスでトレイトを使用しており、再利用もできている。
ちなみに、既存のトレイトを使って新しいトレイトを作ることも可能。
ただし、名前空間がない場合、同名のメソッドは使えない
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 エイリアス名(自由に名前をつけられる)
上記2つを使う場合、 use トレイト名1,トレイト名2{}の中に入れていくことにも注意。
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();