五月祭に参加します特設ウェブサイトへ

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の動作原理

通常、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 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 までの数値のうち、素数のみを選んで表示するプログラムを作成してください。

ut.code(); に参加する準備はできましたか?

未経験からでも始められます。まずはお気軽にお声掛けください!

ut.code(); に参加する