PHP/入門/テキスト表示とコメント
Hello World
[編集]Hello World ハローワールド とは、画面に「Hello World!」と表示するプログラミングの本の最初に書いてあるプログラムです。
PHPのHello Worldプログラムは次のようになります。
- hello1.php
Hello World!
上記のコードをテキストエディタで書いて hello1.php
の名前で保存します。
これを、ウェブサーバー(CGI/MPM/FastCGIなどでPHPのスクリプトが実行可能にセットアップされているとします)にアップロードし、アップロードされたスクリプトをウェブブラウザで開くと
- ウェブブラウザーでの表示
Hello World!
と表示されます。
あるいは、コマンドラインから
- コマンドラインでの操作と表示
% cat hello1.php Hello World! % php hello1.php Hello World! % _
のように実行することができます。
- 「全然PHPのプログラムじゃない!」
と思った方もおられると思いますが、PHPはHTML(などのテキスト)に様々な処理を加えることで機能する「埋込み型言語」なので、地のテキストをそのまま表示するのはPHPの大事な機能です。
2例目
- hello2.php
<?php echo "Hello World!", PHP_EOL; ?>
- 大概の人が思い描く「PHPで書かれたHellow Worldプログラム」はこれだと思います。
- PHPのプログラムは、地のテキストの中に
<?php
(開始タグ) から?>
(終了タグ)の間(PHPタグ)に書きます[1]。 - この例では、
echo "Hello World!"
、がプログラム本体で echo コマンドに文字列リテラル "Hello World!" を渡しています。- echo コマンドは、受け取ったパラメーターを表示するコマンドです。
- PHP_EOLは、改行文字を表す定数で、オペレーションシステムによって異なる改行文字の違いを吸収します。
3例目
- hello3.php
<?= "Hello World!", PHP_EOL; ?>
<?= 値リスト ?>
は<?php echo 値リスト ?>
の短縮形式です。
4例目
- hello4.php
<?php $hour = localtime(null, true)['tm_hour']; ?> <?php if ($hour < 6 or $hour > 17) : ?> こんばんは。 <?php elseif ($hour < 10) : ?> おはようございます。 <?php else : ?> こんにちは。 <?php endif ?>
- 実行結果(0時から6時までと17時から24時まで)
こんばんは。
- 実行結果(6時から10時まで)
おはようございます。
- 実行結果(10時から17時まで)
こんにちは。
- 動的要素がないとPHPを使う意味はないので、時刻から、「おはようございます。」「こんにちは。」「こんばんは。」を切り替えるスクリプトを書きました。
- PHPタグは、1つのプログラムの中で複数回使うことができ、if 文や foreach 文 は複数のブロックに別れて書かれることがあります。
HTMLの生成
[編集]ウェブサーバー(たとえばapacheなど)あるいはコマンドラインから php にスクリプトを与え実行すると、HTMLに埋込まれた <?php
から ?>
のPHPの疑似タグの間のコードがPHPインタープリターに解釈され、地のHTMLに展開されます。
- hello.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"><html> <title>こんにちは</title> </head> <body> <?php echo "Hello World!" ?><br> <?= "こんにちは" ?><br> </body> </html>
- 実行結果
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"><html> <title>こんにちは</title> </head> <body> Hello World!<br> こんにちは<br> </body> </html>
- echo コマンドは、print コマンドと似ていますが、2つ以上のパラメーターを取れるところが違います。
<?= "こんにちは" ?>
は<?php echo "こんにちは" ?>
の短縮構文です。
HTMLにechoで文字列を埋込む
[編集]PHPでは、動的に文字列をHTMLをに埋込むことができます。 埋込まれたPHPのコードがどこに展開されるか見てみましょう。
- hello2.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"><html> <title>こんにちは こんにちは</title> </head> <body> ここは、phpタグの外です。<br><?php echo "ここからphpタグ内側", "<br>"; echo "Hello World!", "<br>"; echo "こんにちは", "<br>"; ?>phpタグを脱出。 </body> </html>
- 実行結果
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"><html> <title>こんにちは こんにちは</title> </head> <body> ここは、phpタグの外です。<br>ここからphpタグ内側<br>Hello World!<br>こんにちは<br>phpタグを脱出。 </body> </html>
- レンダリング結果
ここは、phpタグの外です。
ここからphpタグ内側
Hello World!
こんにちは
phpタグを脱出。
echoとprintの差異
[編集]PHPには、echoとprintと2つの標準出力に表示する機能がありますが、この2つの立ち位置は大きく違います。
echoとprintの差異 echo print 構文上の位置付け 文 演算子 値 返さない 返す matchのアクションに 使えない 使える パラメーター 複数可 1つ 短縮構文 <?php echo "abc"; ?>
⇓<?= "abc"; ?>
N/A
- また、printf() というC由来の「関数」もありますが
<?= sprintf("%03d", 42); ?>
のように、echo(の短縮構文)とsprintf() を組合わせると出力位置の把握が容易になります。
2つの短縮タグ
[編集]PHPタグには、2つの短縮形式があります。
- echo 文の短縮形式
<?php echo "abc"; ?> ⇓ <?= "abc" ?>
- php開始タグの短縮形式
<?php echo "abc"; ?> ⇓ <? echo "abc"; ?>
<?= 文字列式 ?>
[編集]「echo 文の短縮形式」は可読性が高く副作用もないので、積極的に使うべきです。
<? 文 ?>
[編集]これに対し「php開始タグの短縮形式」は
- XML宣言
<?xml version="1.1" encoding="UTF-8"?>
- と構文が衝突します。
- このため
php.ini
でshort_open_tag = Off
として「php開始タグの短縮形式」の使用を禁止することができます。 php.ini
の在処は% php -r 'echo phpinfo();' | grep 'Loaded Configuration File' Loaded Configuration File => /usr/local/etc/php.ini % _
- で確認できます。
シンプルなループ
[編集]PHPは、ただ単純にHTMLに文字列を埋め込めるだけでなく、ループで繰返し構造をHTMLに展開できます。
- loop.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>シンプルなループ</title> </head> <body> <ul> <?php foreach(range(1, 10) as $i) { ?> <li><?= $i * $i ?></li> <?php } ?> </ul> </body> </html>
- 実行結果
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>シンプルなループ</title> </head> <body> <ul> <li>1</li> <li>4</li> <li>9</li> <li>16</li> <li>25</li> <li>36</li> <li>49</li> <li>64</li> <li>81</li> <li>100</li> </ul> </body> </html>
- レンダリング結果
- 1
- 4
- 9
- 16
- 25
- 36
- 49
- 64
- 81
- 100
- ループ開始
<?php foreach(range(1, 10) as $i) { ?>
foreach()
は繰返し構文で、range(1, 10)
は 1 から 10 の数列を返します。そしてこれが、変数 $i に順に入り繰返します。- ループ文の開始の
{
が閉じられていないことに注意してください。 - ループの中
<li><?= $i * $i ?></li>
<?php ... ?>
の外の繰返しは、PHPのコードではなくHTMLのコードが丸ごと繰り返されます。- この場合は、I要素が量産されます。
- 量産されるI要素の内容にPHPのコードがあり変数を含む式が書かれています。
<?= 引数列 ?>
は、<?php echo 引数列 ?>
の短縮形です。- echo コマンドは、 ’,’(カンマ)で区切って複数の式を続けて表示することができます。
- これにたいし、print コマンドは、単一の式しか受付けらません。
- ループ終了
<?php } ?>
- 9行目の
{
は、ここで閉じられています。 - foreachの代替記法
<?php foreach(range(1, 10) as $i) : ?> <li><?= $i * $i ?></li> <?php endforeach ; ?>
- foreach の終わりを endforeach と書く代替構文があり、入組んだ構造のときにループの範囲を見失うリスクを下げることができます(: を忘れがち)。
TABLE要素を使った表組みなどの複合的な構造も、このようにHTMLとPHPのコードが出たり入ったりしながら、編み込むようにコード化します。 WordPressのテーマなどで、より複雑なPHPの(DOMとはまた違った)ドキュメント構造のデザインワークを見ることができます。 このように、PHPはテンプレート記述言語としての特徴を強く持っており、類似のものには ePerl や eRuby のようなスクリプト言語のテンプレート記述拡張がありますが、最初からテンプレート記述言語として設計されているスクリプト言語は、PHP以外に普及例は見当たりません。
コメント
[編集]PHPのコメントには3種類あります。
- 例
<?php declare(strict_types=1); // // から行末まではコメントです。 echo "Hello", /* このように範囲でもコメントが書けます。 */ " World", PHP_EOL; # シェルのように # から行末までもコメントです。 ?>
- 実行結果
Hello World
コメントは、プログラムのデータやロジックに影響を与えず、自由な文書をプログラムに含めることができます。 コメントには、なにを書いてもいいのですが、プログラムのロジックをそのまま記すのは、冗長であるうえにコードの変更にコメントが追従せずズレが生じる原因になります。
次のような要素がコメントによく書かれます
- 著作権者
- コピーライト
- ライセンス
- 参照した論文の DOI
- 関数の引数と戻値の型
- 型宣言仕様が追加されて以降は不要?
- 変数や定数の型
- XXX
- 検証が必要
PHPDoc
[編集]PHPDocは、PHPプログラムのドキュメントを自動的に生成するためのドキュメンテーションシステムです。PHPDocを使用することで、クラス、メソッド、関数、および変数の説明を含む網羅的なドキュメンテーションを作成することができます。このドキュメントを使用することで、他のプログラマーがコードを理解しやすくなり、プログラムの開発プロセスが簡単になるとともに、コードの保守性も向上します。CoCalcを使用してPHPDocを作成するには、PHPDocをインストールし、適切なコマンドを実行して、必要なPHPファイルに注釈を追加する必要があります。
構文
[編集]PHPDocは、PHPのドキュメント生成ツールで、コメントを用いて関数や変数の説明を記述するための構文です。 以下は、一般的なPHPDocの構文の例です。
/** * 関数の説明 * * @param タイプ $引数名 引数の説明 * @return タイプ 戻り値の説明 */ function 関数名($引数名) { // 関数の処理 }
上記の例では、以下のような要素が含まれています。
/**
と*/
で囲まれたコメントがPHPDocの開始と終了を表します。*
の後に、関数の説明文が続きます。@param
は、関数の引数の説明を示すタグです。第一引数には、引数の型、第二引数には、引数の名前、第三引数には、引数の説明を記述します。@return
は、関数の戻り値の説明を示すタグです。引数には、戻り値の型と説明を記述します。
例
[編集]- 1から100までの素数を表示
<?php /** * Displays all prime numbers between 1 and 100. * * @return array Array of prime numbers between 1 and 100 */ function getPrimes() { $primes = array(); for ($i = 2; $i <= 100; $i++) { // 2 is the smallest prime number $isPrime = true; for ($j = 2; $j < $i; $j++) { if ($i % $j == 0) { // if there is any number other than 1 and itself $isPrime = false; // then it is not a prime number break; } } if ($isPrime) { $primes[] = $i; // add the found prime number } } return $primes; } print_r(getPrimes());
使用されたアルゴリズムは比較的単純で、2から100までの各整数が素数かどうかを一つずつ調べる方法です。 このアルゴリズムは O(n2) の時間複雑度を持ちますが、入力範囲が固定された小規模な課題ではうまく機能します。 また、このコードには PHPdoc 形式のドキュメンテーションが含まれており、getPrimes
関数の動作について記述されています。
- 複素数クラス
/** * 複素数クラス */ class ComplexNumber { /** @var float 実数部 */ private $real; /** @var float 虚数部 */ private $imaginary; /** * コンストラクタ * @param float $real 実数部 * @param float $imaginary 虚数部 */ public function __construct($real, $imaginary) { $this->real = $real; $this->imaginary = $imaginary; } /** * 実数部を取得する * @return float 実数部 */ public function getReal() { return $this->real; } /** * 虚数部を取得する * @return float 虚数部 */ public function getImaginary() { return $this->imaginary; } /** * 複素数の加算を行う * @param ComplexNumber $number 加算する複素数 * @return ComplexNumber 計算結果の複素数 */ public function add($number) { $real = $this->real + $number->getReal(); $imaginary = $this->imaginary + $number->getImaginary(); return new ComplexNumber($real, $imaginary); } /** * 複素数の減算を行う * @param ComplexNumber $number 減算する複素数 * @return ComplexNumber 計算結果の複素数 */ public function subtract($number) { $real = $this->real - $number->getReal(); $imaginary = $this->imaginary - $number->getImaginary(); return new ComplexNumber($real, $imaginary); } /** * 複素数の乗算を行う * @param ComplexNumber $number 乗算する複素数 * @return ComplexNumber 計算結果の複素数 */ public function multiply($number) { $real = $this->real * $number->getReal() - $this->imaginary * $number->getImaginary(); $imaginary = $this->real * $number->getImaginary() + $this->imaginary * $number->getReal(); return new ComplexNumber($real, $imaginary); } /** * 複素数の除算を行う * @param ComplexNumber $number 除算する複素数 * @return ComplexNumber 計算結果の複素数 */ public function divide($number) { $denominator = pow($number->getReal(), 2) + pow($number->getImaginary(), 2); $real = ($this->real * $number->getReal() + $this->imaginary * $number->getImaginary()) / $denominator; $imaginary = ($this->imaginary * $number->getReal() - $this->real * $number->getImaginary()) / $denominator; return new ComplexNumber($real, $imaginary); } /** * 複素数の絶対値を取得する * @return float 絶対値 */ public function getAbsoluteValue() { return hypot($this->real, $this->imaginary); } }
上記のように、各メソッドに対してPHPdocを記述することで、ドキュメンテーションを行うことができます。