あたも技術ブログ

セットジャパンコーポレーションの社員が運営しています。

PHPのよくある質問集

WEB構築用の言語としてはやや下火になってきた感がありますが、PHPのよくある質問をまとめてみました。

質問:if文の条件に「==」と「===」って使えるけどこれ何なの…。

回答:「==」は型までは比較しない比較演算子です。「===」の場合は型まで厳密にチェックします。「==」は内部で型の変換が行われるので遅くなります。速度面で速くなる「===」を使いましょう。

例:
$a = 1;
if ($a == ‘1’) {
  // 一致
}

if ($a === ‘1’) {
  // 一致しない
}


質問:文字列を定義するときに「’」と「”」の2通りあるけどこれ何なの…。

回答:「’」で定義したときは変数の展開はされません。「”」で定義したときは変数が展開されます。変数を展開したいときは「”」を、それ以外のときは「’」を使いましょう。変数展開するときに英字と混ざってわかりにくくなるときがあります。その場合「{}」で囲って記述します。

変数展開の例:
$name = ‘田中’;
echo “わたしは @{name} です”;

出力結果
わたしは 田中 です


質問:for文遅くね?これ何なの…。

回答:PHPのfor文は結構遅いです。あまりよろしくないコードだとcount関数でループの度に値を取得したりする人がいます。このようなダメコードを排除するためにもforeachを使いましょう。

悪い例:
$arr = array(1, 2, 3);
for ($i = 0; $i < count($arr); i++) {
  // 処理
}

良い例:
$arr = array(1, 2, 3);
foreach ($arr as $key => $value) {
  // 処理
}


質問:foreachだと最初と最後の要素わからなくね?それでもforeach使うの…。

回答:配列ポインタの先頭と最後に移動するreset関数とend関数があります。これを使いましょう。

例:
$arr = array(1, 2, 3);
// 先頭の要素を取り出す
echo reset($arr);

// 先頭の要素を取り出す
echo end ($arr);


質問:require, require_once, include, include_onceを書きすぎると遅くなってない?気のせいかな…。

回答:気のせいではありません。まずパスの指定が参照パスになっていないか確認しましょう。参照パスで指定したときは、そのファイルが見つかるまでinclude_pathを探しにいきます。その結果無駄なコストが発生しているのです。 require, require_once, include, include_onceは絶対パスで記述をしましょう。

例:
悪い例:
require_once ‘PEAR.php’

良い例:
require_once ‘/usr/share/pear/PEAR.php’


質問:PHPってメソッドのオーバーロード書けなくね?これ何なの…。

回答:PHPではオーバーロードはサポートされていません。その代わりに引数を省略可能とする引数のデフォルト値を定義することができますので、こちらを使用しましょう。またPHP5.6以降を使用するのでしたら可変長引数リストを使用することもできます。

引数のデフォルト値の例:
function hoge($arg = null) {
  if (!is_null(@arg)) {
    // 処理
  }
}

可変長引数リストの例:
function hoge(...$args) {
  foreach ($args as $arg) {
    // 処理
  }
}


質問:PHPでも春分秋分の日って日付型で計算できるの?

回答:PHPでも一般に公開されている計算式で算出できます。以下が春分秋分の日付を計算するサンプルとなります。

/**
 * 春分日を算出します。
 * @param  int      $year 算出対象となる年
 * @return DateTime 春分日
 */
public function CalcVernalEquinoxDay(@year) {
  // 2000年の太陽の春分点通過日
  @baseDate = 20.69115;

  // 春分点通過日の移動量 = (西暦年 - 2000年) * 0.242194
  @movement = (@year - 2000) * 0.242194;

  // 閏年によるリセット量 = (int)((西暦年 - 2000年) / 4)
  @leapYearOffset = (int)((@year - 2000) / 4.0);

  // 春分日 = (int)((1)+ (2) - (3))
  @vernalEquinoxDay = (int)(@baseDate + @movement - @leapYearOffset);

  $date = new DateTime();
  return $date->setDate(@year, 3, @vernalEquinoxDay);
}

/**
 * 秋分日を算出します。
 * @param  int      $year 算出対象となる年
 * @return DateTime 秋分日
 */
public function CalcAutumnalEquinoxDay(@year) {
  // 2000年の太陽の秋分点通過日
  @baseDate = 23.09; 

  // 秋分点通過日の移動量 = (西暦年 - 2000年) * 0.242194
  @movement = (@year - 2000) * 0.242194;

  // 閏年によるリセット量 = (int)((西暦年 - 2000年) / 4)
  @leapYearOffset = (int)((@year - 2000) / 4.0);

  // 秋分日 = (int)((1)+ (2) - (3))
  @autumnalEquinoxDay = (int)(@baseDate + @movement - @leapYearOffset);

  $date = new DateTime();
  return $date->setDate(@year, 9, @autumnalEquinoxDay);
}