PHP
#10
TIOBE#15
PYPL#7
GitHub#14
RedMonk#4
IEEESpectrum#13
JetBrains#12
プログラミング言語
PHP(PHP: Hypertext Preprocessor)
概要
PHPは、Web開発に特化したサーバーサイドスクリプト言語です。HTMLに埋め込んで使用でき、動的なWebページやWebアプリケーションの開発に広く使用されています。WordPress、Drupal、LaravelなどのCMSやフレームワークでも採用され、Web開発の基盤技術として重要な地位を占めています。
詳細
PHPは1995年にRasmus Lerdorfによって開発され、当初は「Personal Home Page」の略でした。現在は「PHP: Hypertext Preprocessor」という再帰的な略語として知られています。
オープンソースで無料で利用でき、学習コストが比較的低いことから、多くの開発者に採用されています。PHP 7以降では大幅な性能向上が図られ、PHP 8では型システムの強化、JITコンパイラの導入など、モダンな言語機能が追加されています。
書き方の例
Hello World
<?php
echo "Hello, World!";
?>
<!-- HTMLと組み合わせ -->
<!DOCTYPE html>
<html>
<head>
<title>PHP サンプル</title>
</head>
<body>
<h1><?php echo "Hello, World!"; ?></h1>
<p>現在時刻: <?php echo date('Y-m-d H:i:s'); ?></p>
</body>
</html>
変数とデータ型
<?php
// 変数の定義($マークで始まる)
$name = "太郎";
$age = 25;
$height = 175.5;
$is_student = true;
// 配列
$fruits = ["りんご", "バナナ", "オレンジ"];
$person = [
"name" => "花子",
"age" => 23,
"city" => "東京"
];
// 変数の表示
echo "名前: $name\n";
echo "年齢: {$age}歳\n";
echo "身長: " . $height . "cm\n";
// 配列の表示
echo "好きな果物: " . $fruits[0] . "\n";
echo "人物情報: " . $person["name"] . "さん(" . $person["age"] . "歳)\n";
// 型の確認
var_dump($name); // string
var_dump($age); // int
var_dump($height); // float
var_dump($is_student); // bool
// 文字列連結
$greeting = "こんにちは、" . $name . "さん!";
echo $greeting . "\n";
?>
関数とクラス
<?php
// 関数の定義
function greet($name, $time = "こんにちは") {
return $time . "、" . $name . "さん!";
}
// 型指定を使った関数(PHP 7+)
function add(int $a, int $b): int {
return $a + $b;
}
// 可変長引数
function sum(...$numbers) {
return array_sum($numbers);
}
// クラスの定義
class Person {
private string $name;
private int $age;
private array $skills;
public function __construct(string $name, int $age) {
$this->name = $name;
$this->age = $age;
$this->skills = [];
}
public function getName(): string {
return $this->name;
}
public function getAge(): int {
return $this->age;
}
public function addSkill(string $skill): void {
$this->skills[] = $skill;
}
public function getSkills(): array {
return $this->skills;
}
public function introduce(): string {
$skillList = empty($this->skills)
? "特になし"
: implode(", ", $this->skills);
return "私は{$this->name}です。{$this->age}歳です。スキル: {$skillList}";
}
}
// 使用例
echo greet("太郎") . "\n";
echo greet("花子", "おはよう") . "\n";
echo "計算結果: " . add(5, 3) . "\n";
echo "合計: " . sum(1, 2, 3, 4, 5) . "\n";
$person = new Person("山田太郎", 30);
$person->addSkill("PHP");
$person->addSkill("JavaScript");
echo $person->introduce() . "\n";
?>
データベース接続(PDO)
<?php
try {
// データベース接続
$pdo = new PDO(
'mysql:host=localhost;dbname=testdb;charset=utf8',
'username',
'password',
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]
);
// テーブル作成
$pdo->exec("
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
");
// データ挿入(プリペアドステートメント)
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
$stmt->execute(["山田太郎", "[email protected]"]);
$stmt->execute(["佐藤花子", "[email protected]"]);
// データ取得
$stmt = $pdo->query("SELECT * FROM users ORDER BY created_at DESC");
$users = $stmt->fetchAll();
echo "登録されているユーザー:\n";
foreach ($users as $user) {
echo "ID: {$user['id']}, 名前: {$user['name']}, Email: {$user['email']}\n";
}
// 特定ユーザーの検索
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute(["[email protected]"]);
$user = $stmt->fetch();
if ($user) {
echo "検索結果: {$user['name']} ({$user['email']})\n";
}
// ユーザー数の取得
$stmt = $pdo->query("SELECT COUNT(*) as count FROM users");
$count = $stmt->fetch()['count'];
echo "総ユーザー数: {$count}\n";
} catch (PDOException $e) {
echo "データベースエラー: " . $e->getMessage() . "\n";
}
?>
Webフォーム処理
<?php
session_start();
// CSRF トークン生成
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
// エラーメッセージ配列
$errors = [];
// フォームが送信された場合の処理
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// CSRF トークンの確認
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'] ?? '')) {
die('CSRF token mismatch');
}
// バリデーション
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
if (empty($name)) {
$errors['name'] = '名前は必須です';
} elseif (strlen($name) > 50) {
$errors['name'] = '名前は50文字以内で入力してください';
}
if (empty($email)) {
$errors['email'] = 'メールアドレスは必須です';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors['email'] = '有効なメールアドレスを入力してください';
}
if (empty($message)) {
$errors['message'] = 'メッセージは必須です';
} elseif (strlen($message) > 1000) {
$errors['message'] = 'メッセージは1000文字以内で入力してください';
}
// エラーがない場合の処理
if (empty($errors)) {
// データベース保存やメール送信などの処理
// ...
$_SESSION['success'] = 'お問い合わせを受け付けました';
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
}
}
// サクセスメッセージの取得と削除
$success = $_SESSION['success'] ?? null;
unset($_SESSION['success']);
?>
<!DOCTYPE html>
<html>
<head>
<title>お問い合わせフォーム</title>
<style>
.error { color: red; }
.success { color: green; }
.form-group { margin-bottom: 1rem; }
</style>
</head>
<body>
<h1>お問い合わせフォーム</h1>
<?php if ($success): ?>
<p class="success"><?php echo htmlspecialchars($success); ?></p>
<?php endif; ?>
<form method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<div class="form-group">
<label for="name">名前:</label><br>
<input type="text" id="name" name="name" value="<?php echo htmlspecialchars($name ?? ''); ?>">
<?php if (isset($errors['name'])): ?>
<div class="error"><?php echo htmlspecialchars($errors['name']); ?></div>
<?php endif; ?>
</div>
<div class="form-group">
<label for="email">メールアドレス:</label><br>
<input type="email" id="email" name="email" value="<?php echo htmlspecialchars($email ?? ''); ?>">
<?php if (isset($errors['email'])): ?>
<div class="error"><?php echo htmlspecialchars($errors['email']); ?></div>
<?php endif; ?>
</div>
<div class="form-group">
<label for="message">メッセージ:</label><br>
<textarea id="message" name="message" rows="5" cols="50"><?php echo htmlspecialchars($message ?? ''); ?></textarea>
<?php if (isset($errors['message'])): ?>
<div class="error"><?php echo htmlspecialchars($errors['message']); ?></div>
<?php endif; ?>
</div>
<button type="submit">送信</button>
</form>
</body>
</html>
JSON API の作成
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
header('Access-Control-Allow-Headers: Content-Type');
// エラーハンドリング関数
function sendError($message, $code = 400) {
http_response_code($code);
echo json_encode(['error' => $message]);
exit;
}
// 成功レスポンス関数
function sendResponse($data, $code = 200) {
http_response_code($code);
echo json_encode($data);
exit;
}
// リクエストメソッドの取得
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// 仮のデータ配列(通常はデータベースから取得)
$users = [
['id' => 1, 'name' => '山田太郎', 'email' => '[email protected]'],
['id' => 2, 'name' => '佐藤花子', 'email' => '[email protected]'],
['id' => 3, 'name' => '田中次郎', 'email' => '[email protected]'],
];
// ルーティング
switch ($method) {
case 'GET':
if (preg_match('/\/api\/users\/(\d+)$/', $path, $matches)) {
// 特定ユーザーの取得
$userId = (int)$matches[1];
$user = array_filter($users, function($u) use ($userId) {
return $u['id'] === $userId;
});
if (empty($user)) {
sendError('User not found', 404);
}
sendResponse(array_values($user)[0]);
} elseif ($path === '/api/users') {
// 全ユーザーの取得
$page = $_GET['page'] ?? 1;
$limit = $_GET['limit'] ?? 10;
$search = $_GET['search'] ?? '';
// 検索フィルタ
if ($search) {
$users = array_filter($users, function($user) use ($search) {
return stripos($user['name'], $search) !== false ||
stripos($user['email'], $search) !== false;
});
}
// ページネーション
$total = count($users);
$offset = ($page - 1) * $limit;
$users = array_slice($users, $offset, $limit);
sendResponse([
'data' => array_values($users),
'pagination' => [
'page' => (int)$page,
'limit' => (int)$limit,
'total' => $total,
'pages' => ceil($total / $limit)
]
]);
} else {
sendError('Endpoint not found', 404);
}
break;
case 'POST':
if ($path === '/api/users') {
// ユーザー作成
$input = json_decode(file_get_contents('php://input'), true);
if (!$input || !isset($input['name']) || !isset($input['email'])) {
sendError('Name and email are required');
}
// バリデーション
if (!filter_var($input['email'], FILTER_VALIDATE_EMAIL)) {
sendError('Invalid email format');
}
// 新しいユーザーの作成(通常はデータベースに保存)
$newUser = [
'id' => count($users) + 1,
'name' => $input['name'],
'email' => $input['email']
];
sendResponse($newUser, 201);
} else {
sendError('Endpoint not found', 404);
}
break;
default:
sendError('Method not allowed', 405);
}
?>
ファイルアップロード処理
<?php
// アップロード設定
$uploadDir = 'uploads/';
$maxFileSize = 5 * 1024 * 1024; // 5MB
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
// アップロードディレクトリの作成
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['upload'])) {
$file = $_FILES['upload'];
$errors = [];
// エラーチェック
if ($file['error'] !== UPLOAD_ERR_OK) {
$errors[] = 'ファイルのアップロードに失敗しました';
}
// ファイルサイズチェック
if ($file['size'] > $maxFileSize) {
$errors[] = 'ファイルサイズが大きすぎます(最大5MB)';
}
// ファイル形式チェック
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $file['tmp_name']);
finfo_close($finfo);
if (!in_array($mimeType, $allowedTypes)) {
$errors[] = '対応していないファイル形式です(JPEG、PNG、GIFのみ)';
}
// エラーがない場合はファイルを保存
if (empty($errors)) {
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $extension;
$destination = $uploadDir . $filename;
if (move_uploaded_file($file['tmp_name'], $destination)) {
echo "ファイルがアップロードされました: " . htmlspecialchars($filename);
// 画像の場合はサムネイル作成
if (strpos($mimeType, 'image/') === 0) {
createThumbnail($destination, $uploadDir . 'thumb_' . $filename);
}
} else {
$errors[] = 'ファイルの保存に失敗しました';
}
}
// エラー表示
if (!empty($errors)) {
foreach ($errors as $error) {
echo "<p style='color: red;'>" . htmlspecialchars($error) . "</p>";
}
}
}
// サムネイル作成関数
function createThumbnail($source, $destination, $maxWidth = 200, $maxHeight = 200) {
$imageInfo = getimagesize($source);
if (!$imageInfo) return false;
$originalWidth = $imageInfo[0];
$originalHeight = $imageInfo[1];
$mimeType = $imageInfo['mime'];
// 元画像の読み込み
switch ($mimeType) {
case 'image/jpeg':
$originalImage = imagecreatefromjpeg($source);
break;
case 'image/png':
$originalImage = imagecreatefrompng($source);
break;
case 'image/gif':
$originalImage = imagecreatefromgif($source);
break;
default:
return false;
}
// サムネイルサイズの計算
$ratio = min($maxWidth / $originalWidth, $maxHeight / $originalHeight);
$newWidth = intval($originalWidth * $ratio);
$newHeight = intval($originalHeight * $ratio);
// サムネイル画像の作成
$thumbnail = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled(
$thumbnail, $originalImage,
0, 0, 0, 0,
$newWidth, $newHeight,
$originalWidth, $originalHeight
);
// 保存
$result = imagejpeg($thumbnail, $destination, 80);
// メモリ解放
imagedestroy($originalImage);
imagedestroy($thumbnail);
return $result;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>ファイルアップロード</title>
</head>
<body>
<h1>ファイルアップロード</h1>
<form method="post" enctype="multipart/form-data">
<label for="upload">画像ファイル(JPEG、PNG、GIF、最大5MB):</label><br>
<input type="file" id="upload" name="upload" accept="image/*" required><br><br>
<button type="submit">アップロード</button>
</form>
<?php
// アップロード済みファイルの一覧表示
if (is_dir($uploadDir)) {
$files = glob($uploadDir . '*');
if (!empty($files)) {
echo "<h2>アップロード済みファイル</h2>";
foreach ($files as $file) {
if (is_file($file) && strpos(basename($file), 'thumb_') !== 0) {
$filename = basename($file);
$thumbFile = $uploadDir . 'thumb_' . $filename;
echo "<div style='margin: 10px; display: inline-block;'>";
if (file_exists($thumbFile)) {
echo "<img src='$thumbFile' alt='$filename' style='max-width: 200px; max-height: 200px;'><br>";
}
echo "<a href='$file' target='_blank'>" . htmlspecialchars($filename) . "</a>";
echo "</div>";
}
}
}
}
?>
</body>
</html>
メリット・デメリット
メリット
- 学習コストが低い: 比較的簡単に習得できる構文
- Web開発特化: HTMLとの親和性が高く、Web開発に最適化
- 豊富な資料: 長年の蓄積による学習リソースとコミュニティ
- ホスティング対応: 多くのレンタルサーバーで標準サポート
- CMSエコシステム: WordPress、Drupalなどの巨大な生態系
- フレームワーク: Laravel、Symfony、CodeIgniterなどの選択肢
デメリット
- 言語設計の一貫性: 歴史的経緯による関数名や仕様の不統一
- パフォーマンス: 他の言語と比較して実行速度が劣る場合がある
- 型安全性: 動的型付けによる実行時エラーのリスク
- セキュリティ: 適切な対策なしでは脆弱性を作り込みやすい
- 企業利用: 大規模システムでの採用が限定的
主要リンク
ランキング情報
- 総合ランキング: 10位
- TIOBE Index: 15位
- PYPL PopularitY: 7位
- GitHub使用率: 14位
- RedMonk言語ランキング: 4位
- IEEE Spectrum: 13位
- JetBrains開発者調査: 12位
PHPは、Web開発において長年の実績を持つサーバーサイド言語として、CMS開発やWebアプリケーション構築で重要な役割を果たしています。