タイトル: 基本的なルール
SEOタイトル: PHP 基本構文ルール完全ガイド (PSR-12)
| この記事の要点 |
|
PHP タグ
PHP コードは タグで囲みます。タグの外は HTML として出力されます。
Welcome
Today is
User: = htmlspecialchars($name) ?>
| タグ | 説明 | 推奨 |
|---|---|---|
| 標準形 | ○ 必ず使う |
= ... ?> | echo の短縮(PHP 5.4+ で常時有効) | ○ Blade テンプレ等で多用 |
... ?> | short_open_tag 依存 | × 環境差で動かない |
| PHP 7 で廃止 | × 使用禁止 |
変数と命名
// ★ 変数は必ず $ で始める
$name = 'Taro';
$age = 30;
$isActive = true;
// 命名規則 (PSR-12)
$userName = 'snake_case か camelCase(プロジェクトで統一)';
$user_name = 'PSR は変数の表記法を規定しない。チーム慣習に従う';
// 定数: 大文字 + アンダースコア
define('MAX_RETRY', 5);
const PI = 3.14; // クラス外 const は PHP 5.3+
// クラス: PascalCase
class UserService { }
// メソッド: camelCase
public function getUserById($id) { }
// 関数: snake_case(標準関数に合わせる慣習)か camelCase
function fetch_user($id) { }
Case Sensitivity (大文字小文字)
| 要素 | 区別する | 区別しない |
|---|---|---|
| 変数名 $foo / $Foo | ★ 別物 | - |
| 定数 FOO / Foo | ★ 別物(PHP 8+) | (PHP 7 まで define の第3引数で制御) |
| クラス名 | - | ★ 同一視(PSR で大文字小文字は厳密推奨) |
| 関数名 | - | ★ 同一視 (strlen = StrLen) |
| メソッド名 | - | ★ 同一視 |
| キーワード (if / while / class) | - | ★ 同一視 |
コメント
// 単行コメント (C++ 形式)
# 単行コメント (シェル形式、PHP 固有)
/*
* 複数行コメント
* (PSR-12 では推奨されない、PHPDoc を使う)
*/
/**
* PHPDoc コメント(API ドキュメント生成・IDE 型推論用)
*
* @param string $name ユーザー名
* @param int $age 年齢
* @return User
* @throws InvalidArgumentException
*/
public function createUser(string $name, int $age): User { }
PSR-12 コーディング規約
PSR-12 は PHP の事実上の標準スタイルガイド。PSR-1 を継承し、PSR-2 を置き換えました。
repository
->where('active', true)
->limit($limit)
->get();
}
}
| 規約 | 内容 |
|---|---|
| インデント | 4 スペース(タブ禁止) |
| 行末 | LF(CRLF 禁止)、末尾改行必須 |
| エンコーディング | UTF-8 + BOM なし |
| 行の長さ | ソフト 80 文字、ハード 120 文字推奨 |
| クラス / メソッドの中括弧 | 次の行 |
| 制御構文 (if/for) の中括弧 | 同じ行 |
| 関数引数のカンマ | カンマ後にスペース |
| 名前空間 / use | declare の後、クラスの前 |
declare(strict_types=1)
PHP 7+ でファイル単位の厳密型チェックを有効化。第 1 行(コメント / shebang の次)に記述。
PHP 8.x の新機能
match 式 (PHP 8.0+)
// 旧: switch (フォールスルー / 緩い比較)
switch ($status) {
case 'pending':
case 'processing':
$label = 'waiting';
break;
case 'done':
$label = 'complete';
break;
default:
$label = 'unknown';
}
// 新: match (式 / 厳密比較 / 値を返す)
$label = match ($status) {
'pending', 'processing' => 'waiting',
'done' => 'complete',
default => 'unknown',
};
Enum (PHP 8.1+)
// 純粋 Enum
enum Status {
case Active;
case Inactive;
case Suspended;
}
// Backed Enum (値付き)
enum Status: string {
case Active = 'active';
case Inactive = 'inactive';
case Suspended = 'suspended';
public function label(): string {
return match($this) {
self::Active => '有効',
self::Inactive => '無効',
self::Suspended => '停止中',
};
}
}
$s = Status::Active;
echo $s->value; // active
echo $s->label(); // 有効
$s2 = Status::from('inactive'); // 文字列から復元
readonly プロパティ (PHP 8.1+)
class Money {
public function __construct(
public readonly int $amount,
public readonly string $currency,
) {}
}
$m = new Money(1000, 'JPY');
echo $m->amount; // 1000
// $m->amount = 2000; // ★ Error: Cannot modify readonly property
Named Arguments (PHP 8.0+)
function createUser(string $name, int $age = 0, bool $active = true, string $role = 'user') { ... }
// 位置引数(従来)
createUser('Taro', 30, true, 'admin');
// 名前付き引数(読みやすい、デフォルト値スキップ可能)
createUser(
name: 'Taro',
role: 'admin',
); // age と active はデフォルト
空白文字とインデント
// ✅ PSR-12 準拠
if ($a === 1 && $b === 2) {
foreach ($items as $key => $value) {
echo $value;
}
}
// ❌ 規約違反
if($a===1&&$b===2){
foreach($items as $key=>$value)
{
echo $value;
}
}
// 演算子周りはスペース必須
$x = $a + $b; // ✅
$x=$a+$b; // ❌
// 制御構文と括弧の間にスペース
if (cond) { } // ✅
if(cond){ } // ❌
自動整形ツール
| ツール | 用途 | 導入 |
|---|---|---|
| PHP-CS-Fixer | 整形 + 自動修正 | composer require --dev friendsofphp/php-cs-fixer |
| PHP_CodeSniffer (phpcs) | 規約チェック | composer require --dev squizlabs/php_codesniffer |
| PHPStan | 静的解析(型エラー検出) | composer require --dev phpstan/phpstan |
| Psalm | 静的解析(Vimeo 製) | composer require --dev vimeo/psalm |
| Rector | 自動アップグレード / リファクタ | composer require --dev rector/rector |
FAQ
Q: 閉じタグ ?> を書かないのはなぜ?
A: 閉じタグの後に空白や改行があると、HTTP ヘッダ送信前に出力されて「headers already sent」エラーになります。ファイル全体が PHP なら閉じタグ省略が PSR 推奨。
Q: BOM 付き UTF-8 はなぜダメ?
A: BOM の 3 バイトが出力されてしまい、上記と同じ「headers already sent」が出ます。エディタの設定で必ず BOM なしに。
Q: declare(strict_types=1) は付けるべき?
A: 新規プロジェクトは付ける推奨。型エラーが早期に発見でき、IDE 補完も効きます。既存コードはテスト整備後に段階導入を。