cv.cm

コーディング · プログラミング言語

PHP入門チュートリアル(初心者向け)

約9分で読めます

結論

PHPはWeb向けに作られたサーバーサイドのスクリプト言語で、PHPファイルはサーバー上で実行され、HTMLやJSONをブラウザに送ります。PHPをインストールし、<?php echo "Hello, world"; を hello.php として保存して php hello.php で実行するか、php -S localhost:8000 でローカルサーバーを起動します。$ 付きの変数、柔軟な配列、型宣言付きの関数、クラス、例外、ユーザー入力の安全な扱いが中心的な内容です。

JSONフォーマッタを開く

PHPとは何か、何に使われるか

PHPは1994年にRasmus Lerdorfが作った言語で、名前は現在「PHP: Hypertext Preprocessor」の略です。ほぼすべてのWebホスティングで動作し、WordPress、Drupal、WikipediaのMediaWikiなど、多くのWebサイトを支えています。コンテンツサイト、ネットショップ、REST API、LaravelやSymfonyなどのフレームワークを使った本格的なWebアプリケーションに使われます。現代のPHP 8には、型システム、JITコンパイラ、列挙型、アトリビュートがあり、古いバージョンよりも性能が大きく向上しています。

PHPのインストールと Hello, world の実行

php.netまたはパッケージマネージャーでPHPをインストールします(brew install php、sudo apt install php-cli、WindowsならXAMPPなどのバンドル)。php -v で確認します。PHPのコードは <?php と、省略可能な閉じタグ ?> の間に書きます。

<?php
echo "Hello, world\n";
php hello.php
# Hello, world
php -S localhost:8000    # serve the current folder at http://localhost:8000

PHPのコードだけを含むファイルでは、閉じタグ ?> を書かないでください。そうすれば、余計な空白がうっかりブラウザに送られることがありません。

変数と基本の型

変数名は $ で始まります。型は動的ですが、引数と戻り値の型を宣言でき、ファイルの先頭に declare(strict_types=1); を書くと、関数呼び出しでの自動的な型変換が行われなくなります。

型例備考
int$n = 42;多くの環境で64ビット
float$x = 3.14;倍精度
string$s = "hi $name";二重引用符では変数が展開され、単一引用符では展開されない
bool$ok = true;大文字小文字を区別しないキーワード
array$a = [1, 2];順序付きマップ:リストと辞書が1つになったもの
null$v = null;値なし
<?php
$name = "Ada";
$count = 7;
echo "$name has $count items\n";        // Ada has 7 items
echo 'No $interpolation here' . "\n";   // No $interpolation here
echo intdiv($count, 2), " ", $count / 2, "\n";  // 3 3.5
var_dump((int) "12" + 1);                // int(13)

. 演算子は文字列を連結します。+ は数値専用です。

制御構文

<?php
$score = 72;
if ($score >= 90) {
    echo "A\n";
} elseif ($score >= 70) {
    echo "B\n";                   // B
} else {
    echo "C\n";
}

for ($i = 0; $i < 3; $i++) {
    echo $i, " ";                 // 0 1 2
}
echo "\n";

foreach (["apple", "pear"] as $fruit) {
    echo $fruit, "\n";
}

$kind = match ($day = "SAT") {   // match is strict and returns a value
    "SAT", "SUN" => "weekend",
    default => "weekday",
};
echo $kind, "\n";                 // weekend

match(PHP 8.0以降)は === で比較し、どの分岐にも一致しない場合はエラーを投げます。従来の switch は緩く比較し、break がないと次のケースに落ちていきます。

関数

<?php
declare(strict_types=1);

function greet(string $name, string $greeting = "Hello"): string
{
    return "$greeting, $name!";
}

echo greet("Lin"), "\n";                    // Hello, Lin!
echo greet(greeting: "Hi", name: "Lin"), "\n"; // Hi, Lin!  (named arguments)

$square = fn(int $x): int => $x * $x;       // arrow function
echo $square(5), "\n";                      // 25

function total(int ...$nums): int           // variadic
{
    return array_sum($nums);
}
echo total(1, 2, 3), "\n";                  // 6

特徴的な機能:配列

PHPの配列は、リスト、辞書、スタック、キューとして使える1つの柔軟な型です。キーは整数または文字列で、挿入順が保持されます。配列を扱う組み込み関数も数多くあります。

<?php
$nums = [3, 1, 2];
$nums[] = 5;                       // append
sort($nums);
echo implode(", ", $nums), "\n";   // 1, 2, 3, 5

$ages = ["ann" => 31, "bob" => 25];
$ages["cy"] = 40;
foreach ($ages as $person => $age) {
    echo "$person is $age\n";
}
echo $ages["zed"] ?? 0, "\n";      // 0  (null coalescing)

$evens = array_filter($nums, fn($n) => $n % 2 === 0);
$squares = array_map(fn($n) => $n * $n, $nums);
echo json_encode(array_values($evens)), " ", json_encode($squares), "\n";  // [2] [1,4,9,25]
echo count($ages), " ", array_key_exists("bob", $ages) ? "yes" : "no", "\n"; // 3 yes

配列は、オブジェクト(ハンドルで渡されます)とは異なり、代入時にコピーされます(コピーオンライト)。

クラス、コンストラクタ昇格、列挙型

<?php
declare(strict_types=1);

enum Role: string
{
    case Admin = "admin";
    case Viewer = "viewer";
}

final class User
{
    public function __construct(
        public readonly string $name,
        public readonly Role $role = Role::Viewer,
    ) {}

    public function label(): string
    {
        return "{$this->name} ({$this->role->value})";
    }
}

$u = new User("Ann", Role::Admin);
echo $u->label(), "\n";               // Ann (admin)
echo Role::from("viewer")->name, "\n"; // Viewer

コンストラクタ昇格(PHP 8.0)では、コンストラクタのシグネチャでプロパティの宣言と代入を同時に行います。readonly プロパティ(8.1)は一度だけ設定でき、バックド列挙型(8.1)は各ケースを文字列や整数に対応付けます。インターフェース、抽象クラス、トレイトも使えます。

エラー処理

現代のPHPは、ほとんどのエラーで例外を投げます。想定内の失敗には Exception のサブクラスを catch します。Throwable なら、TypeError のようなエンジンのエラーも含みます。

<?php
function parseAge(string $text): int
{
    if (!ctype_digit($text)) {
        throw new InvalidArgumentException("invalid age: $text");
    }
    return (int) $text;
}

try {
    echo parseAge("41"), "\n";   // 41
    echo parseAge("abc"), "\n";
} catch (InvalidArgumentException $e) {
    echo $e->getMessage(), "\n"; // invalid age: abc
} finally {
    echo "done\n";
}

小さな完成プログラム:JSON APIのエンドポイント

これを api.php として保存し、php -S localhost:8000 を実行して、http://localhost:8000/api.php?name=Ann を開きます。クエリパラメータを読み取り、検証して、JSONを返します。

<?php
declare(strict_types=1);

header("Content-Type: application/json; charset=utf-8");

$name = trim($_GET["name"] ?? "");
if ($name === "" || mb_strlen($name) > 50) {
    http_response_code(400);
    echo json_encode(["error" => "name must be 1 to 50 characters"]);
    exit;
}

$response = [
    "message" => "Hello, $name!",
    "length" => mb_strlen($name),
    "time" => date(DATE_ATOM),
];
echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);

$_GET、$_POST、$_COOKIE はリクエストのデータを保持します。その中のすべての値を、信頼できないものとして扱ってください。

初心者がよくやる間違い

  • == で比較する。型変換が行われるので、=== と !== を使います。
  • 変数名の $ や、文末のセミコロンを忘れる。
  • パスワードを md5 や sha1 で保存する。password_hash と password_verify を使います。
  • UTF-8のテキストに strlen を使う。これはバイト数を数えます。文字数には mb_strlen を使います。
  • 古いバージョンのPHPを使い続ける。セキュリティ修正と最新機能のために、サポート中のPHP 8系を使いましょう。

次のステップ

php.netの公式PHPマニュアルには、言語リファレンスとユーザーノートを含め、すべての関数が載っています。パッケージマネージャーのComposerとPSRコーディング規約を学び、フレームワークを試しましょう。アプリケーションならLaravelかSymfony、小さなAPIならSlimがあります。テストの標準ツールはPHPUnitです。

よくある質問

PHPは今でも学ぶ価値がありますか?

はい。WordPressサイトを含め、Webの大きな部分を動かしており、PHP 8とLaravelやSymfonyの組み合わせは、Webアプリケーションを生産的に作れる手段です。PHPシステムの保守や開発の仕事も多くあります。

PHPはフロントエンドとバックエンドのどちらの言語ですか?

バックエンドです。PHPはサーバー上で動作し、完成したHTML、JSON、ファイルをブラウザに送ります。ブラウザがPHPのコードを見ることはありません。

echoとprintの違いは何ですか?

どちらもテキストを出力します。echo はカンマ区切りで複数の引数を取れて何も返さず、print は引数を1つだけ取り、1を返します。実際には、ほとんどのコードが echo を使います。

declare(strict_types=1)は何をしますか?

そのファイルから行う関数呼び出しで、スカラー型宣言を厳密にします。文字列 "5" を int 型の引数に渡すと、変換されずに TypeError が投げられます。

コーディング講座の一覧