ut.code(); 学習カリキュラム #9

環境構築

今回のカリキュラムは、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という言語を使ってサーバーサイドのプログラムを書いていきます。

PHPとCGI

注: 一般的な環境での動作原理を説明しています。環境によっては異なる場合があります。

PHPの動作原理
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の実行結果に対し、ブラウザでソースコードを表示させる

結果は予想通りかと思いますが、ここで、ブラウザにソースコードを表示させてみましょう。右クリックして「ページのソースを表示」をクリックしてください。

ソースコードの表示画面
ソースコードの表示画面

ここで見ることのできるソースコードは、ブラウザが実際に解釈する、サーバー側から送られてきた生のデータです。クライアント側からは、PHPファイル内に存在していた<?php print(‘Hello PHP’); ?>は見えていないということが分かります。

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.

基本的にはシングルクォートを使用し、ダブルクォートは必要に応じて使用するのが良いでしょう。

PHPの基本文法

変数の使用と定数の宣言

// 変数
$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種類あり、

  • public … 全ての場所からアクセス可能
  • private … クラスの定義内からのみアクセス可能
  • protected … クラスの定義内と、継承先のクラスの定義内からのみアクセス可能

が利用できます。上記の例の場合、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までの数値のうち、素数のみを選んで表示するプログラムを作成してください。