1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PythonエンジニアがPHPに入門してみた

1
Last updated at Posted at 2026-03-11

Qiita技術ブログ (38).png

はじめに

業務でPHPを触ることになったため、PHPについて調べてまとめてみました。
普段はPythonを使っているので、本記事ではPythonとPHPを比較しながら整理しています。

同じく「Pythonは触ってきたけど、これからPHPに入る」という方の参考になれば嬉しいです。

この記事のコード比較は、次のバージョンで確認しています。

  • Python 3.13
  • PHP 8.4

目次

  1. 基本構造
  2. 変数
  3. 定数
  4. 配列(データ構造)
  5. 制御構造
  6. 関数
  7. クラスとオブジェクト
  8. 名前空間
  9. 例外処理

1. 基本構造

1-1. PHPタグ

PHPコードは <?php で開始します。
この開始タグがないと、ファイル内のコードはPHPとして実行されません。

?> は「PHPコード終了タグ」ですが、終了タグの後に余分な空白や改行があると、予期せぬ挙動を引き起こす場合があるため、ファイルがPHPコードで終わる場合は通常省略するようです。

<?php

echo "hello" . PHP_EOL;

1-2. コメント

Pythonは#""" """, ''' '''でコメントを記載しますが、PHPでは//#, /* */でコメントを書きます。
#よりも//が推奨されるようです。

// PHP: 1行コメント
# PHP: 1行コメント(こちらでも可)
/*
  PHP: 複数行コメント
*/

1-3. 文の終端(セミコロン)

Pythonでは文末に;等は必要ないですが、
PHPは文末に;が必要です。

PHP_EOLは改行を表す定数です

$name = 'alice';
echo $name . PHP_EOL;

1-4. 文字列リテラル(シングル/ダブルクオート)

Pythonの'"は基本的に同じ意味を持ち、可読性や文字列内の引用符の有無で使い分けたりしますが、
PHPの場合'はそのまま文字列、"は変数展開ありの場合で使い分けたりします。

$name = 'alice';

echo 'hello $name' . PHP_EOL; // hello $name
echo "hello $name" . PHP_EOL; // hello alice

2. 変数

PHPの真偽値はtrue / false、PythonのNoneに相当する値はnullです。
(Pythonと違い、大文字小文字の両方でも定義可能ですが、小文字で統一が一般的のようです。)

python
name = "alice"
age = 30
is_active = True
note = None
php
$name = 'alice';
$age = 30;
$isActive = true; // Trueでも定義可能
$note = null;     // Nullでも定義可能

3. 定数

定数はconstを使って定義します。
Pythonと同じようにUPPER_SNAKE_CASEで定義するのが一般的です。

php
const MAX_RETRY = 3;
const DEFAULT_REGION = 'ap-northeast-1';

4. 配列(データ構造)

Pythonでは[]{}listdictが分かれていますが、PHPではarraylistdict両方を定義して扱うようです。

var_dumpは、変数の中身と型を詳しく表示するPHPのデバッグ関数です。

python
scores = [88, 92, 75]
profile = {
    "name": "alice",
    "language": "python",
}
php
$scores = [88, 92, 75];
$profile = [
    'name' => 'alice',
    'language' => 'php',
];

var_dump($scores);
/*
array(3) {
  [0]=>
  int(88)
  [1]=>
  int(92)
  [2]=>
  int(75)
}
*/

var_dump($profile);
/*
array(2) {
  ["name"]=>
  string(5) "alice"
  ["language"]=>
  string(3) "php"
}
*/

5. 制御構造

5-1. if / elseif

PHPではelifでなく、elseifになるのが注意点です。

python
score = 80
if score >= 80:
    print("great")
elif score >= 60:
    print("good")
else:
    print("bad")
# great
php
$score = 80;
if ($score >= 80) {
    echo 'great';
} elseif ($score >= 60) {
    echo 'good';
} else {
    echo 'bad';
}
// great

5-2. for / foreach / while / do-while

do-whileは条件判定の前に処理を1回実行します(最低1回は実行される)。
Pythonには do-while 構文がないため、while True + break で近い挙動を作ります。

forforeachの使い分け

  • for: インデックスを使って制御したい際に向いている
  • foreach: 配列の各要素を順番に取り出す際に向いている
python
values = [10, 20, 30]
for v in values:
    print(v)

i = 0
while i < len(values):
    print(values[i])
    i += 1

j = 0
while True:
    print(values[j])
    j += 1
    if j >= len(values):
        break
php
$values = [10, 20, 30];

for ($i = 0; $i < count($values); $i++) {
    echo $values[$i] . PHP_EOL;
}

foreach ($values as $v) {
    echo $v . PHP_EOL;
}

$i = 0;
while ($i < count($values)) {
    echo $values[$i] . PHP_EOL;
    $i++;
}


$j = 0;
do {
    echo $values[$j] . PHP_EOL;
    $j++;
} while ($j < count($values));

5-3. switch / match

注意点

  • matchはPHP8以上のバージョンで使用可能な分岐構文です。
  • switchは文(statement), matchは式(expression)
  • switch文は弱い比較(==)でmatchは厳密に値を比較(===)します。
python
state = "reading"

# switch(if/elifで表現しました)
if state in ("unread", "queued"):
    label_by_if = "未着手"
elif state == "reading":
    label_by_if = "読書中"
elif state == "finished":
    label_by_if = "読了"
else:
    label_by_if = "不明"
print(label_by_if)

# match
match state:
    case "unread" | "queued":
        label_by_match = "未着手"
    case "reading":
        label_by_match = "読書中"
    case "finished":
        label_by_match = "読了"
    case _:
        label_by_match = "不明"
print(label_by_match)
php
$status = 'reading';

// switch
switch ($status) {
    case 'unread':
    case 'queued':   // 複数ケースをまとめる
        $labelBySwitch = '未着手';
        break;
    case 'reading':
        $labelBySwitch = '読書中';
        break;
    case 'finished':
        $labelBySwitch = '読了';
        break;
    default:
        $labelBySwitch = '不明';
}
echo $labelBySwitch . PHP_EOL;

// match
$labelByMatch = match ($status) {
    'unread', 'queued' => '未着手', // 複数ケースをカンマでまとめられる
    'reading' => '読書中',
    'finished' => '読了',
    default => '不明',
};
echo $labelByMatch . PHP_EOL;

6. 関数

補足: php8以上であれば、greet(name: 'alice')のように名前付き引数で渡すことができるようです。

python
def greet(name: str, prefix: str = "Hello") -> str:
    return f"{prefix}, {name}"


def sum_all(*args: int) -> int:
    return sum(args)


def print_options(**kwargs: str) -> None:
    for key, value in kwargs.items():
        print(f"{key}={value}")
php
function greet(string $name, string $prefix = 'Hello'): string
{
    return "{$prefix}, {$name}";
}

// 可変長引数(Pythonの*argsに近い)
function sumAll(int ...$numbers): int
{
    return array_sum($numbers);
}

function printOptions(string ...$options): void
{
    foreach ($options as $key => $value) {
        echo "{$key}={$value}" . PHP_EOL;
    }
}

echo greet('alice') . PHP_EOL;  // Hello, alice
echo sumAll(1, 2, 3, 4) . PHP_EOL; // 10
printOptions(
    env: 'dev',
    region: 'ap-northeast-1',
);
// env=dev
// region=ap-northeast-1

7. クラスとオブジェクト

サンプル例では継承・クラス変数・classmethod・staticmethod・継承禁止等を比較するために書いたサンプルコードです。

補足:

  • Pythonの_method__methodは慣習によるアクセス制御であり、
    PHPのprotected / privateのように言語仕様として強制されるものではありません。
python
class Person:
    """人を表す基底クラス"""

    species = "human"

    def __init__(self, name: str, age: int):
        """
        Args:
            name: 名前
            age: 年齢
        """
        self.name = name
        self.age = age

    def introduce(self) -> None:
        """自己紹介"""
        print(f"{self.name}です。{self.age}歳です。")

    def _log(self) -> None:
        """内部用メソッド"""
        print("ログ出力")

    def __secret(self) -> None:
        """クラス内部専用メソッド"""
        print("秘密")

    @staticmethod
    def greeting():
        """共通の挨拶"""
        print("こんにちは")

class Student(Person):
    """学生クラス"""

    school_type = "university"

    def __init_subclass__(cls, **kwargs):
        raise TypeError("Studentクラスは継承できません")

    def __init__(self, name: str, age: int, school: str):
        super().__init__(name, age)
        self.school = school

    def study(self) -> None:
        """勉強する"""
        print(f"{self.name}{self.school}で勉強しています。")

    def introduce(self) -> None:
        """自己紹介(オーバーライド)"""
        print(f"{self.name}です。{self.school}の学生です。")

    @classmethod
    def create_guest_student(cls):
        """ゲスト学生を生成する"""
        return cls("ゲスト学生", 18, "未設定")

student = Student("太郎", 20, "東京大学")
student.introduce() # 太郎です。東京大学の学生です。
student.study() # 太郎は東京大学で勉強しています。
guest = Student.create_guest_student()
guest.introduce() # ゲスト学生です。未設定の学生です。
Person.greeting() # こんにちは
print(Person.species) # human
print(Student.school_type) # university
php
class Person
{
    public static string $species = "human";

    public string $name;
    public int $age;

    public function __construct(string $name, int $age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    public function introduce(): void
    {
        echo "{$this->name}です。{$this->age}歳です。\n";
    }

    protected function log(): void
    {
        echo "ログ出力\n";
    }

    private function secret(): void
    {
        echo "秘密\n";
    }

    public static function greeting(): void
    {
        echo "こんにちは\n";
    }
}

final class Student extends Person
{
    public static string $schoolType = "university";

    public string $school;

    public function __construct(string $name, int $age, string $school)
    {
        parent::__construct($name, $age);
        $this->school = $school;
    }

    public function study(): void
    {
        echo "{$this->name}{$this->school}で勉強しています。\n";
    }

    public function introduce(): void
    {
        echo "{$this->name}です。{$this->school}の学生です。\n";
    }

    public static function createGuestStudent(): Student
    {
        return new Student("ゲスト学生", 18, "未設定");
    }
}

$student = new Student("太郎", 20, "東京大学");
$student->introduce(); // 太郎です。東京大学の学生です。
$student->study();  // 太郎は東京大学で勉強しています。
$guest = Student::createGuestStudent();
$guest->introduce();  // ゲスト学生です。未設定の学生です。
Person::greeting();  // こんにちは
echo Person::$species . "\n";  // human
echo Student::$schoolType . "\n";  // university

8. 名前空間

Pythonでは import を使ってモジュールを読み込みます。
一方、PHPでは自作クラスなどはComposerのオートロード機能によって
自動的に読み込まれることが一般的です。

そのためPHPのuseはPythonのimportのようにモジュールを読み込むものではなく、クラスのフルネームを短く書くためのエイリアスとして使われます。

PHPではPSR-4というオートロード規約に従い、「ファイル名 = クラス名」にするのが一般的で、一方、実行用のファイル(例: index.php, main.php)などは小文字でファイル名を命名するのが一般的のようです。

python
# app/services/user.pyに定義したとする
class UserService:
    def hello(self) -> None:
        print("hello")
  
# app/main.pyでUserServiceを呼び出した場合。
# また、比較ように標準モジュールのosを使用する場合
import os

from services.user import UserService

default_region = os.getenv("DEFAULT_REGION", "ap-northeast-1")

user_service = UserService()
user_service.hello()  # hello
php
# app/Services/UserService.phpに定義したとする
namespace App\Services;

class UserService
{
    public function hello(): void
    {
        echo 'hello' . PHP_EOL;
    }
}

# app/main.phpでUserServiceを呼び出した場合。
# また、比較ように標準モジュールのgetenvを使用する場合
use App\Services\UserService;

$defaultRegion = getenv("DEFAULT_REGION") ?: "ap-northeast-1";

$service = new UserService();
$service->hello();  // hello

# または、useを使用せずにフルパスで書くこともできる
$service = new \App\Services\UserService();
$service->hello();  // hello

9. 例外処理

補足:
Pythonにはtryのelse節がありますが、PHPにはありません。
PHPでは例外が発生しなかった場合の処理は try/catch の後に書きます。

python
try:
    raise RuntimeError("テストエラー")
except Exception as e:
    print("例外時に呼び出し")
    raise # RuntimeErrorをそのまま再送出
else:
    print("例外が発生しなかった場合だけ実行")
finally:
    print("例外の有無に関わらず最後に実行")
try {
    throw new RuntimeException('テストエラー');
} catch (Exception $e) {
    echo '例外時に呼び出し' . PHP_EOL;
    throw $e;  // RuntimeExceptionをそのまま再送出
} finally {
    echo '例外の有無に関わらず最後に実行' . PHP_EOL;
}

echo '例外が発生しなかった場合だけ実行';

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?