@blog.justoneplanet.info

日々勉強

PHP Functions(PHPの関数)

■文法

大文字と小文字は区別されない。functionキーワードの後に関数名が続く。

<?php
function func(){
    //code
}
?>

有効な関数名

^[a-zA-Z_][a-zA-Z0-9_]$

但し、システムで今後使用される可能性があるため、アンダーバー(アンダースコア)が2つ続いて始まる関数名は極力使用しない方が良い。

■戻り値(返り値)

PHPでは、関数は必ず戻り値を発生させる。returnを記述しなかった場合は、nullが戻り値となる。通常はreturnを実行すると、関数は残りの処理を行わない。

<?php
function hello($name){
    return "Hello, " . $name . "!";
}
$txt = hello('John');
echo $txt;//display : Hello, John!
?>

参照で戻り値を渡す為には以下のように記述する。

<?php
function &execute($sql){
    $result = mysql_query($sql);
    return $result;
}
$result = &execute("SELECT * FROM `table`");
?>

この場合、$resultは関数内部の$resultの参照になる。但し、大きな文字列や配列を戻り値とし、さらにそれを後で変更する場合以外では、参照渡しのコストの方が高くつく。また、この記法を用いる場合、戻り値は必ず発生し、かつ変数でなければならない。

■Passing Arguments(引数)

関数の挙動をコントロールするなどの目的で、任意の数の引数を関数に渡せる。

<?php
function hello($name){
    echo "Hello, {$name}.";
}
hello('John');//Hello, John.
?>

デフォルト値を持った引数を設定

引数を渡さなかった場合、デフォルト値が適用される。

<?php
function hello($name = 'John'){
    echo "Hello, {$name}.";
}
hello();//Hello, John.
hello('Nick');//Hello, Nick.
?>

デフォルト値を持たないパラメータを全て指定した後に、デフォルト値を持った引数はいくつも指定が可能である。以下の場合、引数$msgは指定しなければならない。また、$name1のみデフォルト値を指定し、$name2だけ任意の値を指定する、といった事は行えない。

<?php
function hello($msg, $name1 = 'John', $name2 = 'Nick'){
    echo "$msg, {$name1} and {$name2}.";
}
hello('Hello');//Hello, John and Nick.
?>

Passing Arguments by Reference(引数の参照渡し)

参照渡しの引数を使うと、関数内から関数外の変数の操作が出来る。

メモリを意識して楽しいといえば楽しいのだが、コードの可読性が下がる気がする。理屈だけ覚えて、個人的な範囲で実用は避けようと思う。

<?php
function add(&$a){
    $a++;
    //通常であれば、変数を操作してもスコープが異なるので関数外には影響しない
}
$num = 1;
add($num);
echo $num;//2
//メモリの住所を渡しただけなので、その場所に対して関数内で処理がされる
?>

PHP4では出来ないが、PHP5では以下のように参照渡しの引数にもデフォルトの値を設定することができる。

<?php
function add(&$a= 0){
    $a++;
}
add();
?>

■Variable-length Argument Lists(可変引数)

<?php
function calc(){
    $array = func_get_args();
    $count = func_num_args();
    //$value = func_get_arg((int) $index_number);
    if($count === 0){
        return 0;
    }
    else{
        $answer = 0;
        foreach($array as $key => $value){
            $answer = $answer + (int) $value;
        }
        return $answer;
    }
}
print(calc(1,5,4,8));//18
?>

各関数について

array func_get_args(void)
関数の引数を配列として返す
int func_num_args(void)
関数の引数の数を返す
mixed func_get_arg((int) $num)
$num番目の引数の値を取得する

関数で明示した引数がある場合は、func_get_args、func_num_args、func_get_argの各関数にその引数も含まれる。

また可変引数は非常に強力であるが、引数をいくつ受け付けるのかがパッと分からないためにコードが読みづらくなる欠点がある。

■可変関数

コードが読みづらくなり滅多に使われることがないが、変数に呼び出し用の括弧をつけて関数とすることもできる。

<?php
function first(){
    print('This is first.');
}
$which = 'first';
$which();//This is first.
?>

PHP Errors and Error Management(PHPにおけるエラー)

■エラーの種類

Compile-time errors

コンパイル中にパーサーに感知されたエラー。

Fatal errors

スクリプトの実行をとめる停止するエラー。

Recoverable errors(>=PHP5.2.0)

ユーザー定義のエラーハンドラで処理が可能。

Warning

致命的ではないエラー。関数に渡す引数を間違えた場合などに起こり、スクリプトの実行は止まらない。

Notice

通常の実行時に起こりうる注意。初期化していない変数にアクセスしようとした場合などに発生し、スクリプトの実行は止まらない。

■エラーレベルを表す定数

固有のビット値を持っている。

E_ERROR
実行時エラー
E_WARNING
実行時の警告
E_PARSE
パースエラー
E_NOTICE
実行時の注意
E_STRICT
コードの互換性上の注意(PHP5.0.0以降)
E_RECOVERABLE_ERROR
E_ERRORと同レベル
E_ALL
E_STRICT以外の全て

■エラーの表示

php.iniのいくつかのディレクティブで定義できるが、デバッグなどで一時的にエラーを表示させたい時は、error_reporting関数をスクリプトの先頭などに記述する。

<?php
error_reporting(E_ALL ^ E_NOTICE);//PHPのデフォルトのエラー表示
ini_set('display_errors', 1);//エラーを表示しない設定にしている場合は左記も追記する
?>

■エラーハンドラ

通常、エラーは関数に$errNo(エラーレベル), $errStr(エラーメッセージ), $errFile(エラーが発生したファイル名), $errLine(行番号), $errContext(エラーが発生したスコープ内での全変数の配列)を渡す。ユーザー定義関数がfalseを返した場合は、通常のエラーハンドラが処理を引き継ぐ。

<?php
$oldEh = '';
function MyEh($errNo, $errStr, $errFile, $errLine, $errContext){
    global = $oldEh;
    logToFile("Error: $errStr in $errFile as line $errLine");
    if($oldEh){
        $oldEh($errNo, $errStr, $errFile, $errLine, $errContext);
    }
}
$oldEh = set_error_handler('MyEh');
?>

PHP Iterative Constructs(繰り返し制御)

■while

<?php
$counter = 0;
while($counter < 4){
    //code
    $counter++;
}
?>

よくあるファイル操作だと以下のような形式かな。

<?php
$txt = '';
$fh = fopen('samle.txt', 'r');
while($row = fgets($fh)){
    $txt .= $row;
}
fclose($fh);
?>

do…while

知ってはいるけど使わないってのはコレ。通常のwhile文との違いは、条件が常にfalseの場合でも、必ず1回実行される事にある。

<?php
$counter = 0;
do{
    //code
}while($counter < 4);
?>

■for

for(カウンターの初期化用の式、条件式、カウンターの増減の式)となる。

PHPを勉強したての頃は、JavaScriptの影響もあって多用しました。

<?php
$ary = array('a', 'b', 'c');
for($i = 0; $i < count($ary); $i++){
    //code
    echo PHP_EOL;
}
?>

■foreach

PHPで便利なループコントロールの1つ。JavaScriptのforEachではネイティブで実装されていないブラウザの事を配慮しなくてはならないが、PHPならそんな事はない。

<?php
$ary = array();
foreach($ary as $value){
    //code
}
?>

配列のキーを使用したいときには

<?php
$ary = array();
foreach($ary as $key => $value){
    //code
}
?>

■break

最も内側のループを抜ける。以下の例では、任意の$sの値に対して、$tは0,1,2の時だけ//codeが実行される。$tが3になった時、breakが実行され内側のループから抜ける。

<?php
$a = array();
$b = array();
for($s = 0; $s < count($a); $s++){
    for($t = 0; $t < count($b); $t++){
        if($t === 3){
            break;
        }
        //code
    }
}
?>

■continue

ループの処理をスキップする。以下の例だと$iが3の時に//codeは実行されないが、ループ自体の処理は続く。

$ary = array();
for($i = 0; $i < count($ary); $i++){
    if($i === 3){
        continue;
    }
    //code
}

PHP Conditional Structures(条件)

■if

一般的な例

<?php
$flag = true;
if($flag){
    //execute
}
else{
    //code
}
?>

PHPにはループや条件分岐の際のブロックを表現する方法にコロンが用意されている。その場合はendifを使用しブロックの最後を明示してあげる。個人的にはトリッキーに見えるので使わないが、WordPressのテンプレートなどでは使われている。

<?php if($flag): ?>
<p>This is a pen.</p>
<?php else: ?>
<p>This is a book.</p>
<?php endif; ?>

■三項演算子

トリッキーに見えたりもするが、スッキリ見えたりもする。すなわち、使用の可否のボーダーが曖昧で難しいというように思える。

<?php
$flag = true;
$str = ($flag)? 'yes' : 'no';
?>

■switch

個人的にはあまり使わない方だが便利っちゃ便利。

以下の例では、$xを1回だけ評価し、その値のcase文から実行する。break文を書かない場合、全てのコードが実行される。「break文を書かない」というのは文法(syntax)エラーではないがコードが非常に見にくくなるので、あえてbreakは書いた方がイイと思う。

<?php
$x = 0;
switch($x){
    case 0:
        //code
        break;
    case 1:
        //code
        break;
    case 2:
        //code
        break;
    default:
        //code
}
?>

PHP Operators(演算子)

■Arithmetic Operators(算術演算子)

特に変わったところはない。余りは繰り返しをコントロールする際に有用だったりする

<?php
//加算
$a = 5 + 2.3;
//減算
$a = 8 - 2;
//乗算
$a = 7 * 5;
//除算
$a = 8 / 2;
//剰余
$a = 21 % 8;
?>

■Incrementing or Decrementing Operators(インクリメント演算子、デクリメント演算子)

演算子の位置が後ろの場合は値を返してから、加減の処理が行われる。この演算子は
戒めとして使わないプログラマーもいるようだ

<?php
$x = 1;
echo $x++;//output 1
echo ++$x;//output 3
echo --$x;//output 2
echo $x--;//output 2
?>

■The String Concatenation Operator(文字列結合演算子)

必要に応じてオペランドが文字列に変換される

<?php
$str = 'Hello ' . 'World';
echo $str;// Hello World
$str .= ', John';
echo $str;// Hello World, John
?>

■Bitwise Operators(ビット演算子)

滅多に使用しないと思われがちだが、PHPの関数の引数では頻繁に使用されるので、必ず覚えておかなければならない。

&
Bitwise AND。両方とも「1」だった場合は結果におけるそのビットが「1」になる。それ以外は「0」となる。
|
Bitwise OR。両方とも「0」だった場合は結果におけるそのビットが「0」になる。それ以外は「1」となる。
^
Bitwise XOR。組み合わせが「0」と「1」だった場合にけっかにおけるそのビットが「1」になる。両方のビットが等しい場合は「0」となる。
<?php
print(5 & 6);//101 & 110 => 100(4)
print(4 | 6);//100 | 110 => 110(6)
print(5 ^ 6);//101 ^ 110 => 011(3)
?>
~
ビット否定演算子・・・2進表現にした後で、0を1、1を0に変換する
<?php
$x = 0;
echo ~$x;//output -1
?>

■Bitwise Left / Right Shift

$x自身は変化しないことに注意しなくてはならない。基本的には2進数に変換し、各ビットを演算子が示す方向にシフトする。

<?php
$x = 1;
echo $x << 1;//output 2
echo $x << 3;//output 8
$a = 16;
echo $a >> 1;//output 8
echo $a >> 2;//output 4
?>

■Assignment Operators(代入演算子)

変数に値を代入する働きをする

<?php
$str = 'Hello World';

$x = 1;
$x += 5;
print($x);// output 6
?>

■Referencing Variables(参照)

オブジェクトを除く全てのデータ型は「&」を使わない限り、コピーとして値が渡される

<?php
$dog = 'Jack';
$cat = &$dog;
print($cat);//Jack
$cat = 'Emily';
print($dog);//Emily
?>

■Comparison Operators(比較演算子)

PHPは動的型付・・・。但し、この変換のパターンを覚えるのは非常にやっかいであるので、「===」や「!==」を使うことをお勧めする

$a = '1';
$b = 1;
if($a == $b){
    //execute
}
if($a === $b){
    //not execute
}
if($a != $b){
    //not execute
}
if($a !== $b){
    //execute
}
A > B, A >= B
AはBより大きい、AはB以上
A < B, A <= B
AはBより小さい、AはB以下

■Logical Operators(論理演算子)

$a = true;
$b = false;
//AND Operator(論理積演算子)
if($a && $b){
    //not execute
}
//OR Operator(論理和演算子)
if($a || $b){
    //execute
}
//XOR Operator(排他的論理和演算子)
if($a XOR $b){
    //execute
}
//論理否定演算子
$a = !$a;

■Cast Operators(キャスト演算子)

オペランドを特定の型に変換

$a = '7';
$b = (int) $a;

class Animal {
    $name = 'Pochi';
    $type = 'dog';
}
$animal = new Animal();
$a = (array) $animal;
print_r($a);
/**
 * array
 * [name] => Pochi
 * [type] => dog
 */

$b = array('name' => 'Pochi', 'type' => 'dog');
$c = (object) $b;
print($c->name);//Pochi

オブジェクトを配列にキャストすると、プロパティと値を関連付けた配列になる。配列をオブジェクトにキャストすると、配列のキーがオブジェクトのプロパティ名に、値がプロパティの値になる

■3項演算子

この演算子も好き嫌いがわかれるかもしれない。この演算子を上手く使うと、コードがスッキリとし見やすくなることもある。但し、逆に見にくくなることもある。個人の好き嫌いと扱いの技量が影響する非常に奥の深い演算子だと個人的には思う

<?php
$a = true;
$b = false;
$name = ($a && $b)? 'John' : 'Jack';
print($name);//Jack
?>

■エラー抑制演算子

特定の関数などにおけるエラーの発生を抑制する

<?php
$dat = @simplexml_load_string($str);
?>

■実行演算子

バッククォーテーションを使うと、OSに直接コマンドを渡せる。コレは非常に強力な機能だがOSコマンドインジェクションなどのセキュリティホールにも繋がる。個人的には可能な限り使わないでおきたいところだ

<?php
$directory = `ls`;
print($directory);
?>

PHP Variable Scopes(変数のスコープ)

■ローカルスコープ

<?php
$counter = 10;
function getVal(){
    $counter = 0;
    //code
}
?>

関数外で$counterが10であっても、関数内の$counterには影響しない

■グローバルスコープ

<?php
$counter = 10;
function getVal(){
    global $counter = 0;
    //code
}
getVal();
?>

globalキーワードをつけると関数内でもグローバル変数になる。もしくは、スーパーグローバル変数の$_GLOBALSを使う

■スタティック変数

<?php
function getVal(){
    static $counter = 0;
    $counter++;
    //code
}
getVal();
?>

関数が実行し終わっても、残り続ける。上の例だと関数が呼び出されるごとに0、1、2、・・・となる。関数外とは別個に存在できる。

■関数の引数

<?php
function printVal($str){
    $str = 'Hello World, ' . $str;
    print($str);
}
?>

基本的には関数内のみ有効。

PHP Variables and Constants(変数と定数)

PHPにおいては変数宣言構文が存在しない。変数は値が代入された時点で作成される

■変数名

^[a-zA-Z_][a-zA-Z0-9_]*こんな感じ。つまり変数名の先頭に数字は使えない。そして、頭には「$」をつけること!

大文字と小文字は区別される。

■可変変数

これは強力だが、コードが読みづらく非常に危険な気もする。個人的には敢えて使わないでおこう。

<?php
$name = 'foo';
$$name = 'bar';
print($foo);//bar

$name = '123';
$$name = '456';
print(${'123'});//456

function myFunc(){
    //code
}
$f = 'myFunc';
$f();
?>

■変数が存在しているかを確認

言語機構のisset()を使う。

<?php
if(isset($val)){
    //code
}
?>

isset()は変数が存在し、nullでない時にtrueを返す。従って以下のようなコードで問題が起こる可能性がある。このような問題を防ぐ為には、アルゴリズムを見直すか、is_nullを使う。

$tmpAry = array(1 => null, 2 => 'sample');
foreach($tmpAry as $key => $value){
    if(isset($value)/* || is_null($value)*/){
        //code
    }
}

また、以下のようにキーを使用して変数のテストをする方法も考えられる。

$tmpAry = array(1 => null, 2 => 'sample');
foreach($tmpAry as $key => $value){
    if(array_key_exixts($key, $tmpAry)){
        //code
    }
}

各関数について

bool isset(mixed $var)
変数がセットされているかどうかを返す。実際には関数ではなく言語構造である。

■参照

変数のクローンは作成されず、メモリ上の住所(参照)が格納される

<?php
$dog = 'Jack';
$cat = &$dog;
print($cat);//Jack
$cat = 'Emily';
print($dog);//Emily
?>

■定数

  • 値はスカラー値(論理値、整数、浮動小数点数、文字列)
  • 一度値を設定したら、後から変更することは出来ない
  • 全てのスコープから参照できる
  • 定数名は^[a-zA-Z_][a-zA-Z0-9_]*こんな感じ。但し、慣例として大文字が用いられることが多い
  • 大文字と小文字は区別される
<?php
define('EMAIL', 'sample@sample.com');
echo EMAIL;//sample@sample.com
?>

PHP Data Types(データ型:複合)

■array(配列)

いくつかのデータにキーを振って、まとめて管理する。

<?php
$ary[0] = 'dog';
$ary[1] = 'cat';
$ary[2] = 'fish';
?>

■object(オブジェクト)

任意のデータと処理をまとめたもの。

<?php
class Sample {
    private $val;
    public static function setVal($val){
        //code
    }
}
$obj = new Sample();
?>

■その他のデータ型

null

変数に値が何も代入されていない事を示す

Resource

外部とのやり取り用の識別子

<?php
$txt = '';
$fh = fopen('sample.txt', 'r');
while($row = fgets($fh,0)){
   $txt .= $row;
}
fclose($fh);
$dbh = mysql_connect(DB_HOST, DB_USER, DB_PASS);
?>

PHP Data Types(データ型:スカラー)

■boolean(論理値)

※小文字が一般的!?

  • true
  • false

PHPでfalseとみなされるのは以下の通り

  • 整数値0
  • 浮動小数点値0.0
  • 空の文字列
  • 文字列’0′
  • 要素数0の配列
  • 空のオブジェクト
  • NULL

但し、複雑な型変換を覚えるのはいささか面倒なので、以下のような型変換が起こらないコードを書く癖を付けた方が良い。

if($bool === true){
    //code
}

■int(整数値)

-2^32~2^32-1を範囲とするがプラットフォームによって異なる。正確には、使用したCコンパイラのlong型と等しくなる。

表記法

10進法
一般的な十進数表記
8進法
0を頭につけなければならない
16進法
0xを頭につけなければならない

■float(浮動小数値)

1.7E-308~1.7E+308を範囲とするがプラットフォームによって異なる。精度は15桁。使用したCコンパイラのdouble型と等しくなる。

表記法

通常の記法
0.87,18.257
指数表記
2E7,1.2e2

注意点としては、近似値である事を常に考慮しなくてはならない。以下のコードを実行すると

<?php
print((0.1 + 0.7) * 10);
?>

8が表示されるように思えるかもしれないが、実際には7.999999が表示される。計算の精度を上げる必要がある場合は、BCMathなどの拡張モジュールを使用する。また数値は予想される値が入っている事を期待してはならない。

■Strings(文字列)

正しくはバイナリデータの集合

リテラル

$str = 'Hello World';
print("$str, John!");//Hello World, John!が表示される
print('$str, John!');//$str, John!が表示される

■型変換について

以下のように、型を強制的に変換することができる

<?php
$x = 3.14;
print((int) $x);//3
?>

PHP Comments, Whitespace and Language Constructs

■コメント

Single line commentは改行コードや終了タグまでがコメントとなる

//この一行はコメント
#この一行はコメント

/*コメントの始まり
コメントの内容
コメントの終わり*/

//使用例
/**
 * get the value
 * @param string $str
 * @return (array) $ary
 */
function getVal($str){
     //code
    return $ary;
}

■スペース

使えない場所

  • 開始タグや終了タグの間
  • whileやfor、foreachなどキーワードの間
  • 変数名や関数名の間

それ以外は使える。

■言語機構(言語構造)

echo 'Hello World';//「Hello World」と表示される

echoは関数のように見えるが、実際には関数ではなく、値も返さない。値を返して欲しい場合はprintを使う(printは常に1を値として返す言語構造の一種である)。

スクリプトを終了させたい時は

die('status');
exit('status');

上述の2つの言語機構の違いは殆どない。