今回のカリキュラムは、Vultr の VPS 上で
curl -fsSL https://raw.githubusercontent.com/chelproc/utcode-lectures-setup/master/lamp-on-docker/init.sh | sh
が実行されていることを前提としています。すでに実施済みの方は再度実行する必要はありません。
これまで、HTML / CSS / JavaScript の3つの言語を使い、プログラムを書いてきました。これら3つの言語はサーバーからクライアントに転送された後、ブラウザ上で実行されます(クライアントサイドでの動作)。しかしながら、クライアントへの転送前、サーバー上でプログラムを実行したい場合があります(サーバーサイドでの動作)。これはなぜかと言うと、クライアントサイドで実行されるプログラムは、ブラウザの挙動によっていかようにも偽装できてしまうからです。例えば、口座の残高を書き換えたりするプログラムがクライアントサイドだけで動作してしまったら、自分の口座残高を書き換え放題ですよね?
クライアントサイドで動作させるためのプログラムは、ブラウザが理解できる必要があるため、HTML / CSS / JavaScript で書く必要がありましたが、サーバーサイドで動作するプログラムに関しては、HTTP プロトコルに準拠した出力ができる言語であれば、何を使用しても構いません。今回は、比較的手軽に使用できるPHPという言語を使ってサーバーサイドのプログラムを書いていきます。
注: 一般的な環境での動作原理を説明しています。環境によっては異なる場合があります。
通常、Web サーバーはリクエストを受け、ファイルの内容を直接クライアント側に送信します。しかし、リクエストされたファイルが PHP ファイルであるとき、Web サーバーは、ファイルの内容を読み出す代わりに、PHP にファイルを実行するよう指示します。この仕組みをCGIと呼び、PHP のみならず、殆どの言語で利用できます。
index.html の名前を変更して、index.php としましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>Hello World</title>
</head>
<body>
<?php print('Hello PHP!'); ?>
</body>
</html>
冒頭で使用しているコマンドでは、Web サーバーの起動と同時に、PHP も有効化しています。したがって、PHP を使用するために特別な設定は必要ありません。何も考えず保存して実行しましょう。
結果は予想通りかと思いますが、ここで、ブラウザにソースコードを表示させてみましょう。右クリックして「ページのソースを表示」をクリックしてください。
ここで見ることのできるソースコードは、ブラウザが実際に解釈する、サーバー側から送られてきた生のデータです。クライアント側からは、PHP ファイル内に存在していた <?php print('Hello PHP'); ?>
は見えていないということが分かります。
Web 開発では、様々な言語を扱うことのできるスキルが求められます。毎度毎度新しく覚え直すのは余りにも手間がかかりすぎるので、一度一つの言語をマスターしたら、その後は言語毎の文法の差異を見ていくと良いでしょう。
PHP の実行エンジンは、PHP ファイルの中の <?php 〜 ?>
で囲まれた部分を PHP のコードとして解釈して実行します(ただし、ファイルの終端の ?>
は省略できます)。JavaScript と似ているようですが、あくまでサーバーサイドで動作するスクリプトのため、Web ページに動きをつけるような用途には使用できません。ただ、PHP を用いて JavaScript のコードを動的に作成して実行させることは可能です。
PHP の最も珍しい特徴です。PHP では、変数名の最初には必ず$をつける必要があります。
$name = 'Tanaka';
$age = 19;
JavaScript においては、文字列を表すとき、ダブルクォートで囲んでもシングルクォートで囲んでも差異は構いません。しかしながら、PHP においては、両者は厳密に区別されます。シングル クォートはごく普通の文字列リテラルなのですが、ダブルクォートを使用した際は、$で始まる部分が変数として解釈されます。以下のコードを実行してみましょう。
$age = 20;
print('I am $age years old.'); // I am $age years old.
print("I am $age years old."); // I am 20 years old.
基本的にはシングルクォートを使用し、ダブルクォートは必要に応じて使用するのが良いでしょう。
// 変数
$wonderful_variable = 'Hello';
// 定数
const SUPER_CONSTANT_VALUE = 123;
define('EXCELLENT_CONSTANT_VALUE', 'abc');
print(SUPER_CONSTANT_VALUE); // 123
PHP の定数は、数値、文字列、論理値と、配列のみに対して使用できます。JavaScript の const のように、通常の変数と同じように使用することはできません。また、定数を使用する際は$記号をつける必要がありません。
変数名は小文字のスネークケース、定数名は大文字のスネークケースを使用しましょう。
$fruits = ['apple', 'banana', 'lemon'];
print($fruits[0]);
print(count($fruits));
$fruits[] = 'strawberry';
array_push($fruits, 'melon');
PHP の配列はリストです。PHP が生まれた当初はオブジェクト指向ではなかったため、「$fruits.append('melon');」といった書き方はできません。長さの取得にも関数を使用します。要素の追加には 7 行目のように関数を使用することもできますが、6 行目のような記法も許されています。
$grades = ['japanese' => 67, 'math' => 80];
print($grades['japanese']);
連想配列を使うと、「キー」+「値」形式のデータ構造を扱うことができます。JavaScript オブジェクトと似ていますがキー名にクォーテーションが必要で、アクセスにはブラケットを使用する必要があります。
PHP の if 文、while 文、for 文は至って標準的な形式です。
if (20 <= $age) {
print('ようこそ!オトナの世界へ!');
} else if (18 <= $age && $age < 20) {
print('もう少し...');
} else {
print('子供は寝る時間ですよ。');
}
while ($remaining > 0) {
print("まだですよ");
$remaining--;
}
for ($i = 0; $i < count($students); $i++) {
print($students[$i]);
}
JavaScript と同じく、列挙可能な値を列挙するための構文が存在します。foreach 文です。2 種類の書き方があります。
$numbers = [1, 3, 6, 8];
foreach ($numbers as $number) {
$sum += $number;
}
$grades = ['japanese' => 67, 'math' => 80];
foreach ($grades as $subject => $points) {
print("$subject: $points");
}
「foreach ($array as $value)」の形式では、配列(または連想配列)の値だけを取り出します。「foreach ($array as $key => $value)」を使用すると、連想配列ではキーと値を、配列では添字と値を使用することができます。
function add($a, $b) {
return $a + $b;
}
print(add(1, 2));
こちらも至って一般的です。
class Dog
{
private $age;
public $name;
public function __construct($age) {
$this->age = $age;
}
public function bark() {
if ($this->age > 5) {
print('バウバウ');
} else {
print('ワンワン');
}
}
}
$pochi = new Dog(8);
$pochi->bark();
PHP のクラスの最大の特徴は、フィールドやメソッドへのアクセスのために、ドット演算子の代わりに「->」(アロー演算子)を使用することです。これはおそらく、一般的なドット演算子が文字列の結合のための演算子としてすでに使用されていたためだと考えられます。
また、PHP では、フィールドやメソッドの定義の前にアクセス修飾子を付加することができます。PHP のアクセス修飾子は3種類あり、
が利用できます。上記の例の場合、name フィールドは private 指定されていますので、
$pochi = new Dog(8);
print($pochi->age);
はエラーとなります。なお、フィールドのアクセス修飾子は省略できませんが、メソッドのアクセス修飾子は省略可能で、その場合は自動的に「public」が指定されたものとみなされます。
その他、コンストラクタに「__construct()」を使用する等、細かい違いがあります。
JavaScript と同様に、PHP でも無名関数が使用でき、クロージャの機能を有しています。比較的新しい機能のため JavaScript ほど頻繁には使用されませんが、この際ですので覚えておきましょう。
$numbers = [1, 2, 3, 4, 5];
$doubled_numbers = array_map(function($item) {
return $item * 2;
}, $numbers);
print_r($doubled_numbers);
PHP の無名関数は、function ($引数1, $引数2, ...) { 処理; }
の形式です。少々冗長な感じもしますが、将来的には短縮された形式の無名関数が使用できるようになるらしいので、それまでは頑張って耐えましょう。なお、print_r 関数は、配列の中身を見やすい形式で出力してくれる便利関数です。
2 ~ 100 までの数値のうち、素数のみを選んで表示するプログラムを作成してください。