PHPで忘れがちなこと(その2)

その1の続きです。
※忘れそうになりますが、これはProgateをやってメモしたい部分をまとめた記事です。

return array() という書き方

はじめ何に違和感を覚えたかというと、それが関数の中ではなく、return array()配列のみ書かれたファイルだったということです。

A.php

<?php
return array('apple', 'remon', 'banana', 'grape');

この書き方はconfigなど、設定ファイルで見られます。
設定値をまとめて管理したい場合、↑こう書いてincludeします。

B.php

<?php
$array = include 'A.php';  // $arrayの中に配列が入っている

これは、 A.php で変数に配列を入れて B.phpinclude するのと同じですが、外部ファイルに変数がある、というのがちょっと気持ち悪いので return がいいのかなぁと思いました。

インクルードファイルで変数に配列を入れる場合
A.php

<?php
$fruits = array('apple', 'remon', 'banana', 'grape');

B.php

<?php
include 'A.php';  // B.php内で$fruitsが使える

分かってきましたが気になったので以下検証してみました。

失敗例 〜変数に配列を入れたインクルードファイルをさらに変数に入れた場合〜
A.php

<?php
$fruits = array('apple', 'remon', 'banana', 'grape');

B.php

<?php
$array = include 'A.php';  // $arrayには数値の1が入っている

1とは??

値の返し方: include に失敗したときには FALSE を返し、警告を発生させます。 成功した場合の返り値は、インクルードしたファイル側で変更していない限りは 1 です。 インクルードしたファイルの中で return を実行すれば、 そのファイルの処理をそこで止めて呼び出し元に処理を戻せます。 読み込まれたファイルから値を返すことも可能です。

通常の include が成功したときの返り値は「1」なんですね。
return していると、その値を返すことができると。

インクルードファイルは、関数の使い方と似ていると思いました。

returnとincludeの引数を括弧でかこむこと

include('A.php') という書き方も気になってきたので調べました。
括弧については

include は「不要です」。
returnは「非推奨です」。

includeとreturnは関数ではなく言語構造です。
include() の書き方は、読み込んだファイルの戻り値の評価の際など、if文の中で使うとややこしくなりそうです。なるべく括弧なしで書いていきたいです。

このあたり、またつまづきそうなのでその都度ドキュメントを熟読しようと思います。

参考

phpの閉じタグ

脱線ついでにもう一丁!

ちなみに、閉じる ?> のないファイルをよく見ます。WordPressのfucntions.phpとか。

どういうことなのか調べました。

PHPの最後の終了タグ ?> は付けないでおこうねというお話 | ザ・サイベース

例として紹介するこのPHPファイルでは、PHPの終了タグ「?>」の後に改行コードが2つあります。[EOF]はEnd Of Fileの略で、ファイル内での終了箇所です。

無駄な改行コードが含まれるPHPファイルを使用すると、プログラムが誤作動する場合があります!!

ファイル全体が純粋なPHPコードの場合、phpの閉じタグを入れると改行コードが混入してしまうことがあるため、ない方がいいんですね。
?> で終わる行が「許容される改行」というのが面白いです。

phpの開始タグ

開始タグについても発見があったので追記です。
<?php<? に省略できるケースがあります。

https://www.php.net/manual/ja/language.basic-syntax.phptags.php

PHP では、短い形式の開始タグ <? も使えます (しかしこれはおすすめしません。というのも、この形式のタグは php.ini で short_open_tag を有効にするか --enable-short-tags オプションつきで PHP を configure した場合でないと使えないからです)。

php.iniはPHPの設定ファイルです。
short_open_tag = On とするそうです。
.htaccessなどでもshort_open_tagの設定はできるようです。

short_open_tag = Off になっているのに <? を使うとエラーになってしまうので、あまり推奨されない設定です。

クラスについて

ここからはクラスのお話です。

Progateでは食べ物の注文サイト制作を通してMenuクラス(子クラスにFoodクラス、Drinkクラス)、メニューに対するユーザーのレビューでUserクラス、Reviewクラスを作りました。

クラスの規模感(どこまででクラスとする、など)や継承の感覚について知ることができました。

インスタンスを作るときに、コンストラクタの引数として値を渡すことができる

オブジェクトの設計図であるクラス。インスタンスを作る際に最初に実行されるメソッド、コンストラクタには引数を渡すことができます。

// クラス
class User {
  private $userName;

  public function __construct($name) {
    $this->userName = $name;
  }
}

// インスタンスを作る
$user1 = new User('hanako');  // コンストラクタの引数に$name = 'hanako' が入る

「ゲッター」「セッター」メソッド

クラスのプロパティは、public ではなく、privateで定義してクラス外からは直接触れないようにしておきましょう、というのが出発点です。
これをカプセル化というそうです。

publicprivate、そして protectedアクセス修飾子といいます。

使える機能を制限することで他の人も使いやすくなる、安全に利用できるようになります。

そこでpublicのメソッドを使って
プロパティの値を取得する: ゲッター(頭に「get」を付ける)
プロパティの値を更新する:セッター(頭に「set」を付ける)

と定義すると分かりやすいです(絶対そうしなければいけないという決まりはないです)。

// 先程のUserクラスの中
class User {
  private $userName;
  private $userAge;

  public function __construct($name, $age) {  // コンストラクタ修正
    $this->userName = $name;
    $this->userAge = $age;
  }

  public function getName() {  // ゲッター
    return $this->userAge;
  }

  public function setName($age) {  // セッター
    $this->userAge= $age;
  }
}

// インスタンスを作る
$user2 = new User('kumiko', 20);

echo $user2->getAge();  // 20
echo $user2->UserAge; // 取得できない

WordPressでもget_the_title() でタイトルの取得です(表示は the_title())。
ちょっと覚えておくだけで、「get〜だから取得する関数だっけ?」と考える時間が減りそうです。

static

静的プロパティ静的メソッドについてです。
Progateでは「クラスプロパティ」「クラスメソッド」という名前で出てきましたが、あまり一般的ではないのかもしれません。

staticの働きはずばり

newせずに利用できるプロパティやメソッドのことです。

PHPのstaticプロパティとstaticメソッド、定数 (1/3):Web業界で働くためのPHP入門(15) - @IT

使い所は、「作られたインスタンスの数を数える」など、個々のインスタンスには関係のないもの、クラスのデータ管理のためのものです。

// 先程のUserクラスの中  
class User {
(省略)
  private static $count = 3;  // 静的プロパティの定義

  public static getCount() {  // 静的メソッドの定義。$thisではなくself
    return self::$count;
  }
(省略)
}

echo 'ユーザの数は' . User::getCount() . '人です。';  // 静的メソッドの呼び出し  
// ユーザーの数は3人です。

使い道が分かればstaticも怖くない!

最後に

ふんわりと知っているのは、あと「名前空間(namespace)」とtraitです(Progateでは出てきませんでした)。 名前空間は抑えておきたい...!
また問題に直面したらおさらいしたいと思います。

これらの知識をうまくフレームワークで落とし込みたいところです!