この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: 基本的なルール
SEOタイトル: PHP 基本構文ルール完全ガイド (PSR-12)

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong>PHP コードは <code><?php ?></code> タグで囲む</strong>。短縮 <code><?</code> は <code>short_open_tag</code> 設定依存で非推奨</li><li><strong>文末はセミコロン</strong> <code>;</code>。変数は必ず <code>$</code> プレフィックス、関数は大文字小文字を区別しない (Case-insensitive)</li><li><strong>コーディング規約は PSR-12</strong>(旧 PSR-2)。インデント 4 スペース / 行末 LF / UTF-8 (BOM なし)</li><li><strong>declare(strict_types=1)</strong> でファイル単位の厳密型チェック有効化。PHP 7+</li><li>PHP 8 系: <strong>match 式</strong> / <strong>Enum (8.1)</strong> / <strong>readonly (8.1)</strong> / <strong>Named Arguments</strong></li></ul></td></tr></table>
<h2>PHP タグ</h2>

<p>PHP コードは <strong><?php &nbsp; ?></strong> タグで囲みます。タグの外は HTML として出力されます。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php"><?php
echo "Hello, World!";
?>

<!-- HTML と混在 -->
<h1>Welcome</h1>
<p>Today is <?php echo date(&apos;Y-m-d&apos;); ?></p>

<!-- 出力専用ショートタグ(PHP 5.4+ 標準有効) -->
<p>User: <?= htmlspecialchars($name) ?></p>

<!-- ファイル全体が PHP の場合は閉じタグ ?> を省略するのが PSR-12 推奨 --></code></pre>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>タグ</th><th>説明</th><th>推奨</th></tr></thead>
<tbody>
<tr><td><code><?php ... ?></code></td><td>標準形</td><td>○ 必ず使う</td></tr>
<tr><td><code><?= ... ?></code></td><td>echo の短縮(PHP 5.4+ で常時有効)</td><td>○ Blade テンプレ等で多用</td></tr>
<tr><td><code><? ... ?></code></td><td>short_open_tag 依存</td><td>× 環境差で動かない</td></tr>
<tr><td><code><script language="php"></code></td><td>PHP 7 で廃止</td><td>× 使用禁止</td></tr>
</tbody>
</table>

<h2>変数と命名</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// ★ 変数は必ず $ で始める
$name = &apos;Taro&apos;;
$age = 30;
$isActive = true;

// 命名規則 (PSR-12)
$userName     = &apos;snake_case か camelCase(プロジェクトで統一)&apos;;
$user_name    = &apos;PSR は変数の表記法を規定しない。チーム慣習に従う&apos;;

// 定数: 大文字 + アンダースコア
define(&apos;MAX_RETRY&apos;, 5);
const PI = 3.14;          // クラス外 const は PHP 5.3+

// クラス: PascalCase
class UserService { }

// メソッド: camelCase
public function getUserById($id) { }

// 関数: snake_case(標準関数に合わせる慣習)か camelCase
function fetch_user($id) { }</code></pre>
<h2>Case Sensitivity (大文字小文字)</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#fff3e0"><th>要素</th><th>区別する</th><th>区別しない</th></tr></thead>
<tbody>
<tr><td>変数名 $foo / $Foo</td><td>★ 別物</td><td>-</td></tr>
<tr><td>定数 FOO / Foo</td><td>★ 別物(PHP 8+)</td><td>(PHP 7 まで define の第3引数で制御)</td></tr>
<tr><td>クラス名</td><td>-</td><td>★ 同一視(PSR で大文字小文字は厳密推奨)</td></tr>
<tr><td>関数名</td><td>-</td><td>★ 同一視 (<code>strlen</code> = <code>StrLen</code>)</td></tr>
<tr><td>メソッド名</td><td>-</td><td>★ 同一視</td></tr>
<tr><td>キーワード (if / while / class)</td><td>-</td><td>★ 同一視</td></tr>
</tbody>
</table>

<h2>コメント</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// 単行コメント (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 { }</code></pre>
<h2>PSR-12 コーディング規約</h2>

<p><a href="https://www.php-fig.org/psr/psr-12/">PSR-12</a> は PHP の事実上の標準スタイルガイド。<strong>PSR-1 を継承</strong>し、PSR-2 を置き換えました。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php"><?php

declare(strict_types=1);

namespace App\Service;

use App\Model\User;
use App\Repository\UserRepository;

class UserService
{
    public function __construct(
        private readonly UserRepository $repository,
        private readonly LoggerInterface $logger,
    ) {
    }

    public function findActiveUsers(int $limit = 100): array
    {
        if ($limit <= 0) {
            throw new InvalidArgumentException(&apos;limit must be positive&apos;);
        }

        return $this->repository
            ->where(&apos;active&apos;, true)
            ->limit($limit)
            ->get();
    }
}</code></pre>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>規約</th><th>内容</th></tr></thead>
<tbody>
<tr><td>インデント</td><td>4 スペース(タブ禁止)</td></tr>
<tr><td>行末</td><td>LF(CRLF 禁止)、末尾改行必須</td></tr>
<tr><td>エンコーディング</td><td>UTF-8 + <strong>BOM なし</strong></td></tr>
<tr><td>行の長さ</td><td>ソフト 80 文字、ハード 120 文字推奨</td></tr>
<tr><td>クラス / メソッドの中括弧</td><td>次の行</td></tr>
<tr><td>制御構文 (if/for) の中括弧</td><td>同じ行</td></tr>
<tr><td>関数引数のカンマ</td><td>カンマ後にスペース</td></tr>
<tr><td>名前空間 / use</td><td>declare の後、クラスの前</td></tr>
</tbody>
</table>

<h2>declare(strict_types=1)</h2>

<p>PHP 7+ で<strong>ファイル単位</strong>の厳密型チェックを有効化。第 1 行(コメント / shebang の次)に記述。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php"><?php
declare(strict_types=1);    // ★ ファイル先頭

function add(int $a, int $b): int {
    return $a + $b;
}

add(1, 2);        // OK: 3
add(&apos;1&apos;, &apos;2&apos;);    // ★ TypeError(strict_types=1 の場合)

// strict_types=1 が無いと暗黙キャスト
// add(&apos;1&apos;, &apos;2&apos;) → 3 が返る(PHP のゆるい型変換)</code></pre>
<h2>PHP 8.x の新機能</h2>

<h3>match 式 (PHP 8.0+)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// 旧: switch (フォールスルー / 緩い比較)
switch ($status) {
    case &apos;pending&apos;:
    case &apos;processing&apos;:
        $label = &apos;waiting&apos;;
        break;
    case &apos;done&apos;:
        $label = &apos;complete&apos;;
        break;
    default:
        $label = &apos;unknown&apos;;
}

// 新: match (式 / 厳密比較 / 値を返す)
$label = match ($status) {
    &apos;pending&apos;, &apos;processing&apos; => &apos;waiting&apos;,
    &apos;done&apos; => &apos;complete&apos;,
    default => &apos;unknown&apos;,
};</code></pre>
<h3>Enum (PHP 8.1+)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// 純粋 Enum
enum Status {
    case Active;
    case Inactive;
    case Suspended;
}

// Backed Enum (値付き)
enum Status: string {
    case Active     = &apos;active&apos;;
    case Inactive   = &apos;inactive&apos;;
    case Suspended  = &apos;suspended&apos;;

    public function label(): string {
        return match($this) {
            self::Active     => &apos;有効&apos;,
            self::Inactive   => &apos;無効&apos;,
            self::Suspended  => &apos;停止中&apos;,
        };
    }
}

$s = Status::Active;
echo $s->value;     // active
echo $s->label();   // 有効
$s2 = Status::from(&apos;inactive&apos;);    // 文字列から復元</code></pre>
<h3>readonly プロパティ (PHP 8.1+)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">class Money {
    public function __construct(
        public readonly int $amount,
        public readonly string $currency,
    ) {}
}

$m = new Money(1000, &apos;JPY&apos;);
echo $m->amount;       // 1000
// $m->amount = 2000;  // ★ Error: Cannot modify readonly property</code></pre>
<h3>Named Arguments (PHP 8.0+)</h3>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">function createUser(string $name, int $age = 0, bool $active = true, string $role = &apos;user&apos;) { ... }

// 位置引数(従来)
createUser(&apos;Taro&apos;, 30, true, &apos;admin&apos;);

// 名前付き引数(読みやすい、デフォルト値スキップ可能)
createUser(
    name: &apos;Taro&apos;,
    role: &apos;admin&apos;,
);    // age と active はデフォルト</code></pre>
<h2>空白文字とインデント</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// ✅ 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){ }          // ❌</code></pre>
<h2>自動整形ツール</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e8f5e9"><th>ツール</th><th>用途</th><th>導入</th></tr></thead>
<tbody>
<tr><td><strong>PHP-CS-Fixer</strong></td><td>整形 + 自動修正</td><td><code>composer require --dev friendsofphp/php-cs-fixer</code></td></tr>
<tr><td><strong>PHP_CodeSniffer (phpcs)</strong></td><td>規約チェック</td><td><code>composer require --dev squizlabs/php_codesniffer</code></td></tr>
<tr><td><strong>PHPStan</strong></td><td>静的解析(型エラー検出)</td><td><code>composer require --dev phpstan/phpstan</code></td></tr>
<tr><td><strong>Psalm</strong></td><td>静的解析(Vimeo 製)</td><td><code>composer require --dev vimeo/psalm</code></td></tr>
<tr><td><strong>Rector</strong></td><td>自動アップグレード / リファクタ</td><td><code>composer require --dev rector/rector</code></td></tr>
</tbody>
</table>

<h2>FAQ</h2>

<p><strong>Q: 閉じタグ <code>?></code> を書かないのはなぜ?</strong><br />
A: 閉じタグの後に空白や改行があると、HTTP ヘッダ送信前に出力されて「headers already sent」エラーになります。ファイル全体が PHP なら閉じタグ省略が PSR 推奨。</p>

<p><strong>Q: BOM 付き UTF-8 はなぜダメ?</strong><br />
A: BOM の 3 バイトが出力されてしまい、上記と同じ「headers already sent」が出ます。エディタの設定で必ず BOM なしに。</p>

<p><strong>Q: <code>declare(strict_types=1)</code> は付けるべき?</strong><br />
A: 新規プロジェクトは付ける推奨。型エラーが早期に発見でき、IDE 補完も効きます。既存コードはテスト整備後に段階導入を。</p>