0
0

僕なりの PHP 備忘録

Last updated at Posted at 2024-06-16

言語リファレンス

クラスとオブジェクト

コンストラクタとデストラクタ

<?php
class BaseClass {
    function __construct() {
        print "In BaseClass constructor\n";
    }
}

class SubClass extends BaseClass {
    function __construct() {
        parent::__construct();
        print "In SubClass constructor\n";
    }
}

class OtherSubClass extends BaseClass {
    // BaseClass のコンストラクタを継承します
}

// In BaseClass constructor
$obj = new BaseClass();

// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();

// In BaseClass constructor
$obj = new OtherSubClass();
?>
<?php
class Point {
    protected int $x;
    protected int $y;

    public function __construct(int $x, int $y = 0) {
        $this->x = $x;
        $this->y = $y;
    }
}

// 引数を両方渡す
$p1 = new Point(4, 5);
// 必須の引数のみを渡す。$y はデフォルト値0になります。
$p2 = new Point(4);
// 名前付き引数(PHP 8.0 以降):
$p3 = new Point(y: 5, x: 4);
?>
<?php
class Point {
    public function __construct(protected int $x, protected int $y = 0) {
    }
}
  • コンストラクタのプロモーション(昇格)という。
<?php
class Product {

    private ?int $id;
    private ?string $name;

    private function __construct(?int $id = null, ?string $name = null) {
        $this->id = $id;
        $this->name = $name;
    }

    public static function fromBasicData(int $id, string $name): static {
        $new = new static($id, $name);
        return $new;
    }

    public static function fromJson(string $json): static {
        $data = json_decode($json, true);
        return new static($data['id'], $data['name']);
    }

    public static function fromXml(string $xml): static {
        // Custom logic here.
        $data = convert_xml_to_array($xml);
        $new = new static();
        $new->id = $data['id'];
        $new->name = $data['name'];
        return $new;
    }
}

$p1 = Product::fromBasicData(5, 'Widget');
$p2 = Product::fromJson($some_json_string);
$p3 = Product::fromXml($some_xml_string);
  • 異なる入力を使い、 異なるやり方でオブジェクトを生成させたい。
  • その場合に上記がおすすめ。
  • staticメソッドをコンストラクタのラッパーとして使う。

配列には旅をさせない

https://speakerdeck.com/uzulla/throw-away-all-php-array-now?slide=1

重要なこと

不完全なインスタンスを作らない。

  • オブジェクトが「生まれる」場所を集約する。
  • そのために、「生まれる」場所にたどり着くまで、引数で連れまわす。

namespaceを使う。

  • 「良い名前」より「違う名前」をつける意識
  • 名前は「特性・役割」ではなく、「実現する機能」で切る
    • Request\UserPointDtoではなく、UserPoint\RequestDto
    • 前者はUserPointという特性・役割になっていて、後者はRequestを返すよという機能になっている

ライブラリはWrapする。

  • ライブラリには配列でオプションを渡したり、受け取ったりする仕様のものがある。
  • Wrapperは、愚直に詰め替えを書いて良い。
  • ライブラリを満足させるために設計しない方が良い。

OOPとか考えない。

  • ファイル数やコード行数が増えるのは仕方ない。その代わり、初心者に書きやすく、ルールにしやすく、静的解析が効くのでリファクタリングしやすい。
  • 構造化プログラミングもどきで十分
  • 素朴かつ疎かにする

静的解析に頼ろう。

DTO

どんなもであるか

Data Transfer Object の略。

データを転送するためのクラスのこと。

配列より厳格・静的・透明性が高い・型の名がある・静的解析と相性〇

定義方法

初めの段階でプロパティを決め切っちゃう。

  • 名前は、UserStructUserDto等にする

  • 使われうるプロパティをもつ

    • 不要なフィールドは持たない
    • 足りなければ足す
    • 実行時の追加は許さない
  • getter/setterは無くてよい

class UserDto {
    public function __construct(
    	public int $id,
        public string $name,
        public int $lastLoginAdEpoch,
        public bool $isLongTimeMissed = false,
        public bool $isAdmin = false,
    ){}
}

使い方

データを取得したら、すぐにDTOにする。

function getUser(int $id): UserDto
{
    $pdo = new PDO('sqlite::memory:');
    // 省略
    $stmt->execute();
    
    return new UserDto(...$stmt->fetch(PDO::FETCH_ASSOC));
}
  • 引数にPHPの配列はやめて、何を渡しているか明示する
  • 返値がUserDtoであることを明示する
  • ただし、nullの場合もあるので例外処理はする。例外処理が面倒な場合は返値にnullを許容するのもあり。例外処理の方が、安全よりであることを忘れない。

fetch all の例

# foreach例
$list = [];
while(false !== $row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    $list[] = new UserDto(...$row);
}
return $list;
// or
return $stmt->fetch(PDO::FETCH_CLASS, UserDto::class);

# array_map例
return array_map(
	fn(array $row) => new UserDto(...$row),
    $stmt->fetchAll(PDO::FETCH_ASSOC)
);
//or
return $stmt->fetchAll(PDO::FETCH_CLASS, UserDto::class);

注意

getUser()のスコープ内部で、配列が役割を終えていることが大切=旅させない。

UserDtoのプロパティはテーブルのカラムと一致しなくても良い。

1つの「データソース」が、複数の異なる形状の DTO にマップされても良い。UserPublicDtoUserInternalDto等の派生をつくるのもあり。

ファクトリで作ってもよいが、DTOを1つにしたら意味がない。またデフォルト値は動的な余地を残すので避ける。

バージョンの確認方法

  • 既にインストールされているバージョンを表示し、そこから選択できる

    $ sudo update-alternatives --config php
    

設定ファイル(php.ini)について

画像アップロードの際に影響を与える設定値

  • upload_max_filesize
    • 単一のファイルの最大アップロードサイズを定義する。これ以上のサイズのファイルはアップロードできない。
  • post_max_size
    • POSTリクエストを通じて送信できるデータの最大量を定義する。この設定は upload_max_filesize よりも大きい値に設定する必要がある。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0