...

empty と isset と is_null ini_set と display_errors error_reporting

by user

on
Category: Documents
5

views

Report

Comments

Transcript

empty と isset と is_null ini_set と display_errors error_reporting
はまりどころ?
特に断りがなければ PHP5 での記述ということで。
empty と isset と is_null
値
if($var)
if(empty($var))
if(isset($var))
if(is_null($var))
$var=1
TRUE
FALSE
TRUE
FALSE
$var="";
FALSE
TRUE
TRUE
FALSE
$var="0";
FALSE
TRUE
TRUE
FALSE
$var=0;
FALSE
TRUE
TRUE
FALSE
$var=NULL;
FALSE
TRUE
FALSE
TRUE
$var
FALSE
TRUE
FALSE
TRUE
$var=array()
FALSE
TRUE
TRUE
FALSE
$var=array(1)
TRUE
FALSE
TRUE
FALSE
値(中身)があるかないかで if($var) と if(empty($var)) は正反対、
変数(入れ物)があるかないかで if(isset($var)) と if(is_null($var)) は正反対になる。
PHP Manual:PHP 型の比較表
http://www.php.net/manual/ja/types.comparisons.php
ゆどうふの湯豆腐ろぐ:$_POST、$_GET のよくある間違い
http://d.hatena.ne.jp/yudoufu1/20060628
ini_set と display_errors
マスターの php.ini で display_errors = Off のとき、エラーが発生してもブラウザのほうにはエラー
表示されない。
開発中(テスト中)はエラーを表示させるために、コード内で
ini_set('display_errors', '1');
などとすることがあるが、これは致命的なエラーの場合はエラー表示しないようになっている。
まぁ、場合によってはそのコードを書いた php ファイル自体が fatal error や syntax error なんてこと
もあるわけだから、ini_set するより先に処理が停止していることもあるわけで。
ということで、変にはまりたくなければ php.ini や .htaccess で設定したほうが無難そう。
PHP Manual 実行時設定
http://www.php.net/manual/ja/errorfunc.configuration.php#ini.display-errors
error_reporting
1
PHP 5 では、E_ALL に E_STRICT は含まれないというところ。
error_reporting = -1
と指定した場合は E_STRICT も含まれるみたい。
PHP Manual:error_reporting
http://www.php.net/manual/ja/function.error-reporting.php
PHP タグと短縮形
html に php コードを埋め込む際に
<?php echo 'Hello World!!' ?>
としたりするが、php.ini の short_open_tag が on ならば
<? echo 'Hello World!!' ?>
とすることができ、さらに <? echo のショートカットである
<?= 'Hello World!!' ?>
が利用できる。
php.ini ディレクティブに関する説明
http://www.php.net/manual/ja/ini.core.php#ini.short-open-tag
include_path と include
include 'foo/bar/hoge.php';
とやると、include_path から検索される。
include './foo/bar/hoge.php';
の場合はリクエストで呼ばれたファイルから相対パスでの読み込みとなり注意が必要だが、
include_path は使われないため高速になる。
include '/home/user/foo/bar/hoge.php';
のような絶対パスならばはまることもないため、予めプログラムの基点となるディレクトリを
dirname(FILE) で
$library_path = dirname(__FILE__);
include $library_path . '/foo/bar/hoge.php';
2
のようにして使いまわすといいかも。
include_path と file_exists
file_exists は include_path を使わずファイルの有無を返す関数なので、下記のようにすると
file_exists は true なのに include できないという状況がありえる。
if(file_exists('foo/bar/hoge.php')){ // 基点となったファイルから相対パスで hoge.php を探す
include 'foo/bar/hoge.php';
//include_path から相対パスで hoge.php を探す
}
これを成功させるには include_path に (カレントディレクトリ)
.
が含まれていなければならず、普
通は php.ini の初期設定でそのようになっているが、.htaccess 等を使って include_path を再設定(上
書き)する際は注意が必要。
大文字小文字
変数名の大文字小文字は区別される。
$hoge = 10;
$Hoge = 20;
echo $hoge; // 10
edho $Hoge; // 20
配列の添え字も同様。
$foo = array();
$foo['bar'] = 10;
$foo['Bar'] = 20;
echo $foo['bar']; // 10
echo $foo['Bar']; // 20
関数名の大文字小文字は区別されない。
function hoge() {
return 10;
}
echo hoge(); // 10
echo Hoge(); // 10
クラスのときも関数と同様。
class foo {
static function bar() {
return 10;
}
}
echo
echo
echo
$obj
echo
foo::bar(); // 10
Foo::bar(); // 10
Foo::Bar(); // 10
= new fOO();
$obj->bAR(); // 10
値渡しと参照渡し
3
new について
PHP4 のとき
$Foo = &new Foo(); // 参照渡し
$Foo = new Foo(); // 値渡し
$Bar= $Foo;
// 値渡し
PHP5 のとき
$Foo = new Foo(); // 参照渡し
$Bar = $Foo;
// 参照渡し
$Bar = clone $Foo; // 値渡し
PHP5 では new のデフォルトが参照渡しになったため、逆に値渡し(コピー)したい場合は clone
を使う。
引数の参照渡し
普通は受け取る側で & で受け取ればよい。
<?php
class Hoge {
function changeValue(&$data) {
$data = 'Hoge';
}
}
$data = 'Huga';
$Hoge = new Hoge();
$Hoge->changeValue($data);
echo $data; // Hoge が出力される
user_call_func_array() を使った場合は、送る側と受け取る側のどちらも & になっていなければ参照
渡しとならない。
<?php
class Hoge {
function changeValue(&$data) {
$data = 'Hoge';
}
}
$data = 'Huga';
call_user_func_array(array('Hoge', 'changeValue'), array(&$data));
echo $data; // Hoge が出力される
戻り値の参照渡し
<?php
class Hoge {
public $data = 'Huga';
function &getValue() { // A
return $this->data;
}
}
$Hoge = new Hoge();
$data = &$Hoge->getValue(); // B
$data = 'Hoge';
echo $Hoge->getValue(); // Hoge が出力される
4
A と B に対し、& が付いたときのみ参照渡しとなる。
いずれが欠けても値渡しとなるので注意。
session.use_trans_sid
cookie が使える環境では
session.use_cookies = 1
としていれば cookie が利用できるが(ただしブラウザ側でも cookie に対応のこと)、携帯など
cookie に対応していない場合に
session.use_trans_sid = 1
とする方法がある。
これを設定すると HTML の A タグ等のリンク
<a href="/foo.php">foo</a>
に自動的に
<a href="/foo.php?PHPSESSID=XXXXX">foo</a>
session id が付加される。
ただし http から記述したリンクは外部パスとみなされ、session id が付加されないので注意。
<a href="http://foo.bar.com/foo.php">foo</a>
また、当然ながら session start(auto start)しないと機能しない。
PHP Manual:セッション ID の受渡し
http://jp2.php.net/manual/ja/session.idpassing.php
mod_php と CGI のリダイレクト
sample.php からのリダイレクトで
header('Location: ' . $url);
exit;
とかした場合、$url が
1.http://foo.bar.com/hoge.html
2./hoge.html
3.hoge.html
5
2 のときの挙動が mod_php と CGI の php とで違ってくる。
mod_php のときは 1 も 2 も URL http://foo.bar.com/hoge.html にリダイレクトされるが、CGI のとき
は 2 のときに URL は http://foo.bar.com/sample.php のまま、hoge.html の内容が表示される。
これは内部リダイレクトと呼ばれているみたいで、Location ヘッダ自体が出力されないらしい。
OKwave:相対 URL によるリダイレクト
http://okwave.jp/qa/q2428571.html
一部のブラウザや docoom では相対 URL が NG みたいだが、絶対 URL ならすべての環境で OK と
いうわけでもないらしい。
@IT:モバイル Web 開発に失敗しない鉄則
http://www.atmarkit.co.jp/fdotnet/aspnetmobile/aspnetmobile05/aspnetmobile05_02.html
CGI の挙動の件は下記が詳しい。
ぐらめぬ・ぜぷつぇんのはてダ:cgi.force_redirect って何?
http://d.hatena.ne.jp/msakamoto-sf/20080802/1217662203
split
split() は『大文字小文字を区別しない正規表現により文字列を分割し、配列に格納する』なのだが、
正規表現にはまった。
$strs = split("¥s", $str);
これで $str に格納された文字列中の空白文字により分割されると思ったが、実際には機能しない。
POSIX で空白文字は
$strs = split("[ ¥t¥n¥r¥f¥v]", $str);
というようになるようだ。
空白文字が連続していても 1 つの区切りとしたい場合は
$strs = split("[ ¥t¥n¥r¥f¥v]+", $str);
とすればいい。
正規表現を必要としない、例えば改行で分割されればよい、というのであれば explode を使ったほ
うが高速。
6
$strs = explode("¥n", $str);
正規表現 - Wikipedia
http://ja.wikipedia.org/wiki/%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE
preg と ereg
共に正規表現を扱う関数群。
preg のほうが速く動作するようなので、基本は preg で。
・ereg は POSIX 拡張
・preg は Perl 互換
POSIX 正規表現関数
http://jp2.php.net/manual/ja/ref.regex.php
PCRE 関数
http://jp2.php.net/manual/ja/ref.pcre.php
動作確認に便利なサイト発見。
PHP の種:PREG ONLINE
http://www.php-seed.net/preg/
mbstring
日本語を扱う場合に設定するものだが、いまいち各設定の関係がよくわからなかったので試して
みた。
mbstring.language
mbstring.internal_encoding
neutral
UTF-8
まず .language が neutral だと .internal_encoding の UTF-8 が効かない。
つづいて
mbstring.language
mbstring.internal_encoding
mbstring.encoding_translation
neutral
UTF-8
On
だと、HTTP 入力に対して自動的に .internal_encoding(内部エンコーディング)の設定に変換しよ
うとする。
たとえば .encoding_translation が正常に機能する場合、EUC-JP の HTML フォームからポストされ
てきたデータは
$_POST['hoge'];
7
に格納されている状態で既に EUC-JP から .internal_encoding(内部エンコーディング)の
UTF-8 に変換済みとなる。
が、やはり .language が neutral だと .internal_encoding が効かないため、結果的に .encoding_translation
も機能しないことになる。
同様にプログラム内部で mb_convert_encoding() を使用し、auto を使っている場合、
$str = mb_convert_encoding($str, 'UTF-8', 'auto');
この auto も .internal_encoding(内部エンコーディング)が効かない状態だとうまく機能しない模
様。
auto ではなく直接、'EUC-JP, UTF-8' のように指定する分には OK らしい。
とりあえず
mbstring.language
Japanese
じゃないといろいろはまる。
プログラムでセットする場合は
mb_language('Japanese');
配列に対する文字エンコーディングの一括変換
string mb_convert_encoding(str, to_encofing, from_encoding)
となっており、str に array を渡してしまうと空っぽの array が返ってくる。
$str = array(' 古池や ',' 蛙飛び込む ',' 水の音 ');
$str = mb_convert_encoding($str, 'UTF-8', 'auto');
print_r($str); // Array()
上記の mbstring 設定との絡みを考えてサンプルを作ってみる。
// mbstring.encoding_translation = Off を想定
mb_language('Japanese');
ini_set('mbstring.detect_order', 'auto');
ini_set('mbstring.http_input' , 'pass');
ini_set('mbstring.http_output' , 'pass');
ini_set('mbstring.internal_encoding', 'UTF-8');
ini_set('mbstring.script_encoding' , 'UTF-8');
ini_set('mbstring.substitute_character', 'none');
// ↓ euc-jp の form から空白文字区切りの文字列が post されてくるのを想定
$request = split("[ ¥t¥n¥r¥f¥v]+", $_POST['comment']);
$request = mb_convert_variables('UTF-8', 'EUC-JP', $request)
プロキシ経由かチェック
8
レンタルサーバで共有 SSL を利用可能とするコードを書く場合、クライアント∼共有 SSL 用プロ
キシは HTTPS でも、共有 SSL 用プロキシ∼ Web サイトのあるサーバは内部で HTTP となってい
る場合がほとんど。
クライアント − (https) − 共有 SSL 用プロキシ − (http) − Web サーバー
そのため Web サーバー側で処理される $_SERVER['HTTPS'] で HTTPS かどうか判定できない。
xrea、coreserver では squid が使われていて
if (isset($_SERVER['HTTP_VIA']) && isset($_SERVER['HTTP_X_FORWARDED_FOR']))
というような感じ。
sakura ではプロキシが何か調べてないが
if (!isset($_SERVER['HTTP_VIA']) && isset($_SERVER['HTTP_X_FORWARDED_FOR']))
となる模様。
実際には変数にセットされている値もチェックしたほうがいいのかな。
eForm で画像認証を使いたい
http://modxcms.com/forums/index.php?topic=32384.75;wap2
MySQL と client と文字化け
文字化けの仕組みは割愛して(汗)。
以前から気になっていたのは my.cnf にある [client] の設定。
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
default-character-set=utf8
となっている場合、[client]ってなんなのだろうか?ということ。
例えば MySQL が latin1 で、上記のように my.cnf の設定により utf8 になっているとする。
このとき PHP から MySQL に接続をかけると、[client] の設定に従い utf8 で接続することになるの
では ... と思ったが、事実は違って latin1 での接続となる。
この [client] は libmysqlclient を使って mysqld サーバに接続をかけるときの話らしい。
で、libmysqlclient を使って接続をかけることができるのは PHP では mysqli_real_connect() で、mysqli
は PHP5 から利用できる MySQL 改良版拡張モジュールだ。
要するに PHP4 の場合は使えない。
9
MySQL 改良版拡張モジュール
http://jp.php.net/manual/ja/book.mysqli.php
で、PHP5 だ っ た と し て、PEAR::DB で mysqli を 利 用 で き る が、コ ー ド を 読 む と 普 段 は
mysql_connect() で接続し、SSL で接続する際は mysqli_real_connect() を使うようになっていた。
「mysqli を指定しているのに mysql_connect() を使ってる状態」になるので注意が必要。
多分、PEAR::MDB2 なら OK だと思われる。
まとめると
PHP5 → mysqli → mysqli_real_connect() → libmysqlclient(my.cnf) → mysqld
という接続のとき my.cnf の [client] の設定が効いてくることになる。
MySQL 初心者日記:libmysqlclient について
http://nysql.g.hatena.ne.jp/py4s-tnk/20090329/1238341015
パフォーマンス改善
え∼ そうだったの? みたいなのもあって、かなり参考になった。
Selfkleptomaniac:PHP のパフォーマンス改善 (1)
http://selfkleptomaniac.org/archives/43
Selfkleptomaniac:PHP のパフォーマンス改善 (2)
http://selfkleptomaniac.org/archives/44
Selfkleptomaniac:PHP のパフォーマンス改善 (3)
http://selfkleptomaniac.org/archives/45
高速化のための書き方
なるほど∼
Otaxa:PHP、チョイ高速化テクニック
http://otaxa.com/blog/others/php-faster-technics/?utm_source=twitterfeed&utm_medium=twitter
マジックメソッド
クラスの中で使用する、アンダースコア 2 つではじまる名前の特殊関数。定められたタイミング
で起動する。
マジックメソッド
説明
新たにオブジェクトが 生成される度に起動
__construct()
10
__destruct()
特定のオブジェクトへの全てのリファレンスが
削除された直後やオブジェクトが明示的に破棄
された直後、あるいはスクリプトの終了時に起
動
__call()
アクセス不能メソッドをオブジェクトのコンテ
キストで実行したときに起動
__callStatic()
アクセス不能メソッドを静的コンテキストで実
行したときに起動
__get()
アクセス不能プロパティからデータを読み込む
際に起動
__set()
アクセス不能プロパティへデータを書き込む際
に起動
__isset()
isset() あるいは empty() をアクセス不能プロパ
ティに対して実行したときに起動
__unset()
unset() をアクセス不能プロパティに対して実行
したときに起動
__sleep()
serialize() によるシリアル化の前に起動
__wakeup()
unserialize() によるアンシリアル化の前に起動
__toString()
クラスが文字列に変換される際に起動
__invoke()
スクリプトがオブジェクトを関数としてコール
しようとした際に起動
__set_state()
PHP5.1.0 以降で var_export() によってエクス
ポートされたクラスのためにコール
__clone()
オブジェクトが clone キーワードでコピーされ
る際に起動
PHP Manual:マジックメソッド
http://jp2.php.net/manual/ja/language.oop5.magic.php
flush() と ob_flush() と ob_start() のネスト
php の出力バッファを任意のタイミングで吐き出すのが ob_flush() で、web サーバーの出力バッ
ファは flush() らしい。
よって順序としては
<?php
for ($i=0; $i < 1000; $i++) {
echo $i . "<br>¥n";
ob_flush();
flush();
}
11
で、逐次出力されていく。
ob_start() してる間の echo とかの出力がバッファに溜まって、途中で ob_flush()、flush() しなければ
プログラムが終了したときに出力されるが、既に ob_start() しているときに更に ob_start() みたいな
ネストすることもできる。
この場合ネストは先入れ後出しとなり、ob_end_flush() でネストの深いところから総出力するには
while(ob_get_level()) ob_end_flush();
flush();
となる。
12
Fly UP