タイトル: 基本的なルール
SEOタイトル: PHP 基本構文ルール完全ガイド (PSR-12 / strict_types / クォート)
この本文には実行可能なタグ等が含まれるため、安全のため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>PHP は <strong><code><?php ?></code></strong> タグで囲む。短縮タグ <code><? ?></code> は非推奨</li><li><strong>文末セミコロン <code>;</code> 必須</strong>。変数は <strong><code>$name</code></strong> 形式</li><li>関数名は<strong>大文字小文字鈍感</strong>、変数名は<strong>敏感</strong> ($Name と $name は別)</li><li>シングルクォート <code>"..."</code> は変数展開しない、ダブルクォート <code>"..."</code> は変数展開する</li><li>推奨コーディング規約は <strong>PSR-12</strong>、型厳密化は <code>declare(strict_types=1);</code></li></ul></td></tr></table>
<h2>PHP ファイルの基本構造</h2>
<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\Services;
use App\Models\User;
use App\Exceptions\NotFoundException;
class UserService
{
public function findByEmail(string $email): ?User
{
return User::where('email', $email)->first();
}
}
// ★ 終了タグ ?> は付けない (出力が紛れ込むのを防ぐ)</code></pre>
<h2>PHP タグの種類</h2>
<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>標準</td><td><code><?php ... ?></code></td><td>★ 標準</td></tr>
<tr><td>短縮 echo</td><td><code><?= $var ?></code></td><td>OK (テンプレートで多用)</td></tr>
<tr><td>短縮タグ</td><td><code><? ... ?></code></td><td>非推奨 (設定依存)</td></tr>
<tr><td>ASP 風</td><td><code><% ... %></code></td><td>PHP 7 で廃止</td></tr>
<tr><td>script タグ</td><td><code><script language="php"></code></td><td>PHP 7 で廃止</td></tr>
</tbody>
</table>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php"><!-- Blade / プレーン PHP テンプレート -->
<h1>Hello, <?= htmlspecialchars($name) ?>!</h1>
<?php foreach ($users as $user): ?>
<li><?= $user->name ?></li>
<?php endforeach; ?></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">$name = "Alice"; // 変数は $ 始まり
$user_id = 1; // _ で区切る (snake_case)
$isAdmin = true; // PSR-12 は camelCase 推奨
// ❌ 数字始まりは NG
// $1abc = "x";
// 大文字小文字は区別される
$Name = "Bob";
echo $name; // "Alice"
echo $Name; // "Bob"
// 定数
const APP_VERSION = "1.0";
define("PI", 3.14);
// クラスの定数
class Status {
public const ACTIVE = 1;
public const INACTIVE = 0;
}
Status::ACTIVE;</code></pre>
<p>関数名は<strong>大文字小文字を区別しない</strong>のが歴史的仕様。クラス名・名前空間は区別する。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">function greet() { return "hello"; }
greet(); // OK
Greet(); // OK (関数名は鈍感)
GREET(); // OK
class User { ... }
// USER のような呼び出しは NG (クラス名は敏感)</code></pre>
<h2>文字列リテラル: クォートの違い</h2>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>種類</th><th>変数展開</th><th>エスケープ</th><th>速度</th></tr></thead>
<tbody>
<tr><td>シングル <code>'...'</code></td><td>×</td><td><code>\\</code> <code>\'</code> のみ</td><td>★ わずかに速い</td></tr>
<tr><td>ダブル <code>"..."</code></td><td>○ (<code>$var</code> 展開)</td><td><code>\n</code> <code>\t</code> <code>\\</code> <code>\$</code> <code>\"</code></td><td>遅い</td></tr>
<tr><td>Heredoc <code><<<TAG</code></td><td>○ (ダブル相当)</td><td>不要</td><td>同じ</td></tr>
<tr><td>Nowdoc <code><<<'TAG'</code></td><td>×</td><td>不要</td><td>同じ</td></tr>
</tbody>
</table>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">$name = "Alice";
echo 'Hello, $name'; // Hello, $name (展開されない)
echo "Hello, $name"; // Hello, Alice
echo "Hello, {$name}!"; // Hello, Alice! (中括弧で範囲明示)
// 配列要素・オブジェクトプロパティ
echo "{$user['name']}"; // 配列
echo "{$user->name}"; // オブジェクト
// Heredoc (ダブル相当)
$msg = <<<EOT
Hello, $name!
今日は良い天気ですね。
EOT;
// Nowdoc (シングル相当、展開なし)
$tpl = <<<'EOT'
$name は展開されません
\n もそのまま
EOT;</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">// 一行コメント (C/Java スタイル)
# 一行コメント (Perl スタイル)
/*
複数行
コメント
*/
/**
* ★ PHPDoc コメント (IDE が型情報として解釈)
*
* @param string $name ユーザー名
* @param int $age 年齢
* @return User
* @throws InvalidArgumentException
*/
function createUser(string $name, int $age): User { ... }</code></pre>
<h2>declare(strict_types=1)</h2>
<p>PHP 7+ の<strong>型厳密モード</strong>。ファイルの先頭で宣言すると、関数の引数・戻り値の型変換が許されなくなります。</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); // 3
add("1", 2); // ❌ TypeError (strict なしなら 3 になる)
add(1.5, 2); // ❌ TypeError
// strict_types=0 (デフォルト) は自動変換される</code></pre>
<h2>PSR-12 コーディング規約 (主要ルール)</h2>
<ul>
<li>インデントは<strong>スペース 4 つ</strong> (タブ禁止)</li>
<li>改行は<strong>LF のみ</strong> (Windows の CRLF NG)</li>
<li>ファイル末尾は<strong>空行 1 つ</strong>で終わる</li>
<li>クラス・関数の <code>{</code> は<strong>改行して次行</strong>に置く</li>
<li>制御構文の <code>{</code> は<strong>同じ行</strong></li>
<li><strong>名前空間 / use 文 の後に空行</strong></li>
<li><strong>クラス名 PascalCase</strong>, <strong>メソッド・変数 camelCase</strong>, <strong>定数 SNAKE_UPPER</strong></li>
<li>PHP 終了タグ <code>?></code> は<strong>PHP のみのファイルでは付けない</strong></li>
</ul>
<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\Services;
use App\Models\User;
use App\Repositories\UserRepository;
class UserService
{
public function __construct(
private readonly UserRepository $repo,
) {}
public function findActiveUsers(int $limit = 10): array
{
if ($limit <= 0) {
throw new \InvalidArgumentException('limit must be positive');
}
return $this->repo->findActive($limit);
}
}</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">// if / elseif / else
if ($x > 10) {
echo "big";
} elseif ($x > 0) {
echo "small";
} else {
echo "zero or negative";
}
// 代替構文 (テンプレートで便利)
if ($x > 10): echo "big"; elseif ($x > 0): echo "small"; else: echo "zero"; endif;
// switch
switch ($status) {
case 'active':
echo "active";
break;
case 'pending':
case 'review':
echo "in progress";
break;
default:
echo "?";
}
// match 式 (PHP 8+)
$label = match (true) {
$score >= 90 => 'A',
$score >= 80 => 'B',
$score >= 70 => 'C',
default => 'F',
};
// ループ
for ($i = 0; $i < 10; $i++) { ... }
foreach ($users as $user) { ... }
foreach ($users as $i => $user) { ... }
while ($cond) { ... }
do { ... } while ($cond);</code></pre>
<h2>PHP 8.x の主な新機能</h2>
<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#fff3e0"><th>バージョン</th><th>機能</th></tr></thead>
<tbody>
<tr><td>8.0</td><td>名前付き引数、コンストラクタプロパティ昇格、union 型、match 式、nullsafe <code>?-></code>、JIT</td></tr>
<tr><td>8.1</td><td>enum、readonly プロパティ、never 戻り値、Fiber、配列アンパック with string キー</td></tr>
<tr><td>8.2</td><td>readonly クラス、disjunctive normal form 型、null/false/true 型</td></tr>
<tr><td>8.3</td><td>typed class constants、<code>#[\Override]</code> アノテーション</td></tr>
<tr><td>8.4</td><td>property hooks、asymmetric visibility、new MyClass()->method() (新インスタンスの即時メソッド呼び)</td></tr>
</tbody>
</table>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-php">// 名前付き引数 (PHP 8.0+)
createUser(name: 'Alice', age: 25, isAdmin: true);
// コンストラクタプロパティ昇格 (PHP 8.0+)
class Point {
public function __construct(
public readonly float $x,
public readonly float $y,
) {}
}
// enum (PHP 8.1+)
enum Status: string {
case Active = 'active';
case Inactive = 'inactive';
public function label(): string {
return match($this) {
Status::Active => '有効',
Status::Inactive => '無効',
};
}
}
// nullsafe (PHP 8.0+)
$country = $user?->address?->country?->name;</code></pre>
<h2>FAQ</h2>
<p><strong>Q: <code>?></code> は必要?</strong><br />
A: PHP のみのファイルでは<strong>付けない</strong>のがベストプラクティス。末尾に余計な改行や空白が混じると HTTP ヘッダ送信前に出力されてしまうため。</p>
<p><strong>Q: シングルとダブル、どちらを使う?</strong><br />
A: <strong>変数展開しないならシングル</strong>が原則。<code>"hello"</code> と <code>'hello'</code> の性能差はマイクロ最適化レベルですが、明確に意図が伝わるのでシングル推奨。</p>
<p><strong>Q: <code>declare(strict_types=1)</code> は必須?</strong><br />
A: 新規プロジェクトでは<strong>付けるべき</strong>。型変換による潜在バグを防げます。既存コードへ後付けすると影響大なので段階的に。</p>