home(h) links(l) memo(m) translation(t) profile(r)
memo(m) cgi(u) PHP

PHP関係

目次

PHPのインストールと設定

rpmを作ってインストール

1. ソースをダウンロード
[root@server ~]# cd /usr/src/redhat/SOURCES
PHPダウンロードページの「Complete Source Code」よりソースをダウンロード。
2. 解凍・展開
[root@server SOURCES]# tar -zxvf php-5.2.14.tar.gz
3. specファイルのコピー
[root@server SOURCES]# cd ../SPECS
[root@server SPECS]# cp ../SOURCES/php-5.2.14/php5.spec.in ./php5.spec
4. specファイルの編集
下記環境・条件にて動作するするよう調整。
---- php5.spec
%define version 5.2.14 # バージョン番号が初期値の "@VERSION@" ではうまくいかなかった
%define so_version 5
%define release 1 # 適宜値を修正(再ビルドごとに数値を増やす)
%define source_root /usr/src/redhat/SOURCES/php-5.2.14 # ソースルートパス

Name: php
Summary: PHP: Hypertext Preprocessor
Group: Development/Languages
Version: %{version}
Release: %{release}
License: The PHP license (see "LICENSE" file included in distribution)
# ^"Copyright"は古い書式であることによりビルドエラー。"License"に修正。
Source: https://www.php.net/get/php-%{version}.tar.gz
Icon: %{name}-%{version}/php.gif # パス "%{name}-%{version}/" 追記。

URL: http://www.php.net/
Packager: PHP Group <group@php.net>

BuildRoot: %{_tmppath}/%{name}-%{version}-root
BuildArch: x86_64 # 実際のアーキテクチャに応じた値を記述

%description
PHP is an HTML-embedded scripting language. Much of its syntax is
borrowed from C, Java and Perl with a couple of unique PHP-specific
features thrown in. The goal of the language is to allow web
developers to write dynamically generated pages quickly.

%prep
%setup

%build
set -x
#./buildconf --force # モジュール類を生成?
# またはインストール済みモジュール(/usr/lib64/php/modules/*.so)をソースtarballの modules に加えておく。
#./configure --prefix=/usr --with-apxs \
#       --disable-debug \
#       --with-xml=shared \
#↓ 必要要件などに合わせ修正
./configure --build=x86_64-redhat-linux-gnu \
            --host=x86_64-redhat-linux-gnu \
            --target=x86_64-redhat-linux-gnu \
            --program-prefix= --prefix=/usr \
            --exec-prefix=/usr --bindir=/usr/bin \
            --sbindir=/usr/sbin --sysconfdir=/etc \
            --datadir=/usr/share --includedir=/usr/include \
            --libdir=/usr/lib64 --libexecdir=/usr/libexec \
            --localstatedir=/var --sharedstatedir=/usr/com \
            --mandir=/usr/share/man --infodir=/usr/share/info \
            --cache-file=../config.cache --with-libdir=lib64 \
            --with-config-file-path=/etc \
            --with-config-file-scan-dir=/etc/php.d \
            --disable-debug --with-pic --disable-rpath \
            --without-pear --with-bz2 --with-curl \
            --with-exec-dir=/usr/bin --with-freetype-dir=/usr \
            --with-gd \
            --with-png-dir=/usr --enable-gd-native-ttf \
            --without-gdbm --with-gettext --with-gmp \
            --with-iconv --with-jpeg-dir=/usr --with-openssl \
            --with-pspell \
            --with-pcre-regex=/usr --with-zlib \
            --with-layout=GNU --enable-exif --enable-ftp \
            --enable-magic-quotes --enable-sockets \
            --enable-sysvsem --enable-sysvshm --enable-sysvmsg \
            --enable-wddx --with-kerberos --enable-ucd-snmp-hack \
            --with-unixODBC=shared,/usr \
            --enable-shmop --enable-calendar \
            --with-mime-magic=/usr/share/file/magic.mime \
            --without-sqlite \
            --with-libxml-dir=/usr \
            --with-apxs2=/usr/sbin/apxs \ # Apache2系の場合はapxs ではなく apxs2 を指定
            --with-mysql \
            --disable-dba \
            --without-unixODBC \
            --enable-pdo \ # pdoを有効化、"=shared" (共有オプション)はつけない方がいいらしい[1]
            --disable-xmlreader --disable-xmlwriter \
            --enable-mbstring 
#make clean
make

# デフォルトではcli版とcgi版の両方を生成する手順になっているが、cli版だけを生成する手順に変更。
#mv sapi/cgi/php php.keepme
test -f config.cache && rm -f config.cache
#cp %{source_root}/sapi/cli/php sapi/cli
cp ${RPM_SOURCE_DIR}/%{name}-%{version}/php.gif ${RPM_SOURCE_DIR}

#make clean
#./configure --enable-cli
#make
#mv php.keepme sapi/cgi/php
# figure out configure options options based on what packages are installed
# to override, use the OVERRIDE_OPTIONS environment variable.  To add
# extra options, use the OPTIONS environment variable.

#test rpm -q MySQL-devel >&/dev/null && OPTIONS="$OPTIONS --with-mysql=shared"
#test rpm -q solid-devel >&/dev/null && OPTIONS="$OPTIONS --with-solid=shared,/home/solid"
#test rpm -q postgresql-devel >&/dev/null && OPTIONS="$OPTIONS --with-pgsql=shared"
#test rpm -q expat >&/dev/null && OPTIONS="$OPTIONS --with-xml=shared"

#if test "x$OVERRIDE_OPTIONS" = "x"; then
#    ./configure --prefix=/usr --with-apxs2=$APXS $OPTIONS
#else
#    ./configure $OVERRIDE_OPTIONS
#fi

%install
rm -rf $RPM_BUILD_ROOT
mkdir -p ${RPM_BUILD_ROOT}
mkdir -p $RPM_BUILD_ROOT%{_libdir}/httpd/modules
install -m 0755 libs/libphp5.so $RPM_BUILD_ROOT%{_libdir}/httpd/modules
mkdir -p $RPM_BUILD_ROOT%{_bindir}
install -m 0755 sapi/cli/php $RPM_BUILD_ROOT%{_bindir}
#install -m 0755 sapi/cgi/php $RPM_BUILD_ROOT%{_bindir}/php_cgi
mkdir -p $RPM_BUILD_ROOT%{_mandir}/man1
install -m 0755 sapi/cli/php.1 $RPM_BUILD_ROOT%{_mandir}/man1
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}
install -m 0755 php.ini-recommended $RPM_BUILD_ROOT%{_sysconfdir}/php.ini
mkdir -p $RPM_BUILD_ROOT%{_libdir}/php/modules
install -m 0755 modules/*.so $RPM_BUILD_ROOT%{_libdir}/php/modules

%files
%defattr(-,root,root)
%{_libdir}
#/etc/httpd/conf
%{_bindir}/php*
%{_mandir}/man1/php.1*
%{_sysconfdir}/php.ini
#%{_libdir}/php/extensions/*.so
#/usr/lib/debug
#/usr/src/debug

%doc TODO CODING_STANDARDS CREDITS LICENSE NEWS README*
----

参考文献・サイト

自己内包型PHP拡張モジュールの作り方

PHPパッケージソース内の README.SELF-CONTAINED-EXTENSIONS より。

$Id: README.SELF-CONTAINED-EXTENSIONS 100881 2002-10-23 21:35:17Z jon $
=============================================================================

「自己内包型PHP拡張モジュールの作り方」

PHPソースに入っている拡張モジュールはPHPソースとは独立に配布することができます。
そのような拡張モジュールを作るには、下記2つの事項が必要になります。

  - 設定ファイル (config.m4)
  - モジュールのソースコード

では、これらをどのようにして作り、どのようにして一緒にするのかについて以下に記します。

「システムの準備」

作ったモジュールがあらゆるシステムで動作するようにするには、
以下のツールを開発者は用意しておく必要があります。

    GNU autoconf
    GNU automake
    GNU libtool
    GNU m4

これらは全て下記サイトから入手することができます。

    ftp://ftp.gnu.org/pub/gnu/

「既存の拡張モジュールを変換する」

自己内包拡張モジュールを作るのがどれだけ簡単かだけを示すために、
埋め込まれた拡張モジュールを自己内包モジュールに変換する手順を以下に示します。
PHPをインストールして以下のコマンドを実行して下さい。
  
     $ mkdir /tmp/newext
     $ cd /tmp/newext

これで空のディレクトリができました。
ではmysql拡張モジュールのファイルをコピーします。

     $ cp -rp php-4.0.X/ext/mysql/* .

次の処理でモジュールの作成は終わりです。以下のコマンドを実行して下さい。

     $ phpize

これでディレクトリ内のファイルを持ち出して使えるようになりました。
拡張モジュールは完全にそれ単独で動作します。

ユーザが拡張モジュールをインストールする方法は要約すると以下の通りです。

     $ ./configure \
            [--with-php-config=/path/to/php-config] \
            [--with-mysql=MYSQL-DIR]
     $ make install

The MySQL module will either use the embedded MySQL client 
library or the MySQL installation in MYSQL-DIR.

「新しい拡張モジュールの定義」

以下の例において、拡張モジュールの名前は「foobar」であるとします。

これは「foo.c」と「bar.c」という2つのファイルで構成されています。
(任意数のヘッダファイルも含まれますが、これはここではさほど重要なことではありません)
  
また、ここに例示する拡張モジュールはいずれの外部ライブラリも参照しません
(これは重要なことです、なぜならユーザは他に何も指定しなくても良いからです)。

「LTLIBRARY_SOURCES」はソースファイル名を指します。
任意数のソースファイル名をつけることができます。

「M4設定ファイルを作る」
m4設定によって追加のチェックを行うことができます。
自己内包拡張モジュールのために、マクロを呼び出す必要はありません。

------------------------------------------------------------------------------
PHP_ARG_ENABLE(foobar,whether to enable foobar,
[  --enable-foobar            Enable foobar])

if test "$PHP_FOOBAR" != "no"; then
  PHP_NEW_EXTENSION(foobar, foo.c bar.c, $ext_shared)
fi
------------------------------------------------------------------------------

「PHP_ARG_ENABLE」は正しい変数を自動的に設定し、
「PHP_NEW_EXTENSION」によってsharedモードで拡張モジュールが使えるようにします。

「PHP_NEW_EXTENSION」の最初の引数は拡張モジュールの名前を記します。
2番目の引数はソースコードファイル名です。
3番目は $ext_shared に値が渡されます。$ext_shared は 
PHP_ARG_ENABLE/WITH によって PHP_NEW_EXTENSION に設定されるものです。
  
PHP_ARG_ENABLE または PHP_ARG_WITH を常に使うようにして下さい。
あなたの作ったPHPモジュールを配布する予定がないとしても、
モジュールを簡単にメインのPHPモジュールの体系に組み込むことができるからです。

「ソースファイルの作成」

ext_skel はPHPにおける全モジュールの共通コードを作る時や、
基本的な関数定義や関数に渡す引数の制御を行うCのコードを記述する場合、
非常に助けとなるでしょう。
詳しくは README.EXT_SKEL をご覧下さい。

As for the rest, you are currently alone here.
多くの既存モジュールがあり、開始点として単一のモジュールを使ってそれに独自のコードを付加することを考えます。

「自己内包拡張モジュールを作る」

config.m4 ファイルと ソースファイルを1つのディレクトリに置きます。
そして、phpizeを実行します。
phpizeはphp 4.0をmake installする際にインストールされます。

例えば、php を --prefix=/php というオプションで configure した場合、
以下のファイルを実行することになるでしょう。

     $ /php/bin/phpize

これは自動的に必要なビルドファイルをコピーし、config.m4からconfigureを作ります。
これで自己内包拡張モジュールができるのです。

「自己内包型拡張モジュールのインストール」

拡張モジュールは以下のコマンドを実行することによってインストールされます。

     $ ./configure \
            [--with-php-config=/path/to/php-config]
     $ make install

「ADDING SHARED MODULE SUPPORT TO A MODULE」

利便性のため、自己内包型拡張モジュールは共有モジュールとして
ロードできるようになっている必要があります。
では次に「foo」という名前の既存モジュールに共有モジュールサポートを
付加するのかについて説明します。

  1. config.m4 の中で、PHP_ARG_WITH/PHP_ARG_ENABLE を使って下さい。
そうすると --with-foo=shared[,..] または --enable-foo=shared[,..]
が自動的に使えるようになります。

  2. config.m4 の中で、PHP_NEW_EXTENSION(foo,.., $ext_shared) を使って
拡張モジュールの作成を有効化して下さい。

  3. 以下の各行をあなたが作ったCのソースファイルに追加して下さい。

        #ifdef COMPILE_DL_FOO
        ZEND_GET_MODULE(foo)
        #endif

    

インストール後の設定

インストール時に設定しなかったオプションの追加を行うには、 php.iniを編集する(rpmパッケージを用いてインストールした場合も同様) →依然mbstring関数が使えない。

yum install php-mbstringを実行してパッケージをインストールした後、httpd -k restartでApacheを再起動する。→"additional .ini files parsed"に/etc/php.d/mbstring.iniが追加された。

その後php.iniの[mbstring]の項を修正。

マルチバイト関数のオーバーロード
元々マルチバイトに非対応の各関数を、マルチバイト対応関数に読み替えて実行(オーバーロード)する設定を行うには、php.inimbstring.func_overloadに以下の値を積算して指定する。
関数の種類 元の関数 オーバーロード関数
メール関数 mail mb_send_mail 1
文字列関数 strlen mb_strlen 2
strpos mb_strpos
strrpos mb_strrpos
substr mb_substr
strtolower mb_strtolower
strtoupper mb_strtoupper
substr_count mb_substr_count
正規表現関数 ereg mb_ereg 4
eregi mb_eregi
ereg_replace mb_ereg_replace
eregi_replace mb_eregi_replace
split mb_split
mbstring.func_overload = 0だと全てオーバーロードしない、mbstring.func_overload = 7だと全てオーバーロードする、と言った具合になる。

php.iniのある場所は<?php phpinfo();?>と記したスクリプトをブラウザで参照すれば記載されている。

参考文献・サイト:

各種設定(php.ini)

PHPに関する各種設定情報は php.ini に記述されている。UNIX系OSでは通常 /etc、Windowsでは C:¥windowsC:¥winnt にある。変更を反映するにはWebデーモン(Apacheなど)の再起動が必要。

キー 内容
expose_php On, Off サーバにPHPがインストールされているという情報をHTMLヘッダに乗せるかどうかを設定する。Onなら情報を出し、Offなら情報を出さない[1]。出したからと言って直接セキュリティ上の脅威になる訳ではないが攻撃に有用な情報を取得される可能性があるので、情報を出す必要がないなら出力しない方が好ましい。初期状態の php.ini での設定は On のよう。Onにしている時のhtmlヘッダは以下の様になる。Firefoxでのhtmlヘッダ閲覧方法はこちら
HTTP/1.1 200 OK
Date:Fri,21 May 2010 00:27:38 GMT
Server:Apache/2.2.8 (Unix) PHP/5.2.8
Content-Type:application/xhtml+xml
...
expose_php = On
error_log = ファイル名 エラーログ出力先指定 エラーログ出力先ファイル名を指定する。指定しない場合、Apacheのログにエラー出力される(Webスクリプトの場合[3])。 error_log = "/var/log/php.log";
error_reporting 内容参照 エラーレベルを示す文字列または値で指定する。ビット演算子(|→OR、&→AND、^→XOR、~!→NOT)を用いて組み合わせた指定や特定エラーだけを出なくするような指定も可能[2]
値(2進数) 定数 内容
1 (0000 0000 0000 0001) E_ERROR 重大な実行時エラー。メモリ確保に関する問題のように復帰不能なエラーを示す。スクリプトの実行は中断される。
2 (0000 0000 0000 0010) E_WARNING 実行時の致命的ではないエラー(警告事項)を示す。スクリプトの実行は中断されない。
30719 (0111 0111 1111 1111) E_ALL E_STRICTを除く全てのエラーと警告を出力する。
error_reporting = E_COMPILE_ERROR|E_ERROR_E_CORE_ERROR

参考文献・サイト

コマンドリファレンス

表記の基本事項

原則として<?php?> の間に記したもののみがPHPスクリプトとみなされ、その外に書いたものはPHPスクリプトとはみなされない。

<?php ←ここからPHPスクリプト
(PHPスクリプト)
?> ←ここでPHPスクリプト終わり

例外は以下の通り。

コメントアウト
以下の部分はコメントとみなされ、解釈は行われない。
  • //」〜行末(または?>
  • #」〜行末(または?>
  • /*」〜「*/
複数行にわたってコメントアウトしたい場合は上記3つ目の方法を用いる。
【例】以下の記述は全てコメントアウト
//これはコメントです。
#これもコメントです。
/*これも
コメント
です。*/
ヒアドキュメント
ヒアドキュメントを用いると、PHPスクリプトエリア(<?php ... ?>)内で一時的にPHPとしての解釈するのを停止することができる。まとまったhtmlコードを出力する場合などに有効。
【書式】
print <<< 終了検知文字列
(非PHPコンテンツ)
終了検知文字列

【例】
print <<< DOC_END
<html>
  <head>
    <title>ようこそ</title>
  </head>
  <body>
    <p>ここが本文です</p>
  </body>
</html>
DOC_END;
  • 終了検知文字列はPHPの予約語でなければ何でも可。
  • 終了検知文字列の前に空白などを入れないこと。入れるとその文字も含めて終了検知対象となり終了検知文字列にヒットしなくなる。

なお、print を変数名に置き換えれば、出力する代わりに変数への値代入を行うこともできる。

【例】"$contents" に代入
$contents = <<< DOC_END
<html>
  <head>
    <title>ようこそ</title>
  </head>
  <body>
    <p>ここが本文です</p>
  </body>
</html>
DOC_END;

ヒアドキュメント内でも変数を参照することができる。 但し、配列変数を参照する時は、変数名を{ }で囲む必要がある[3]

【例】
$ cat test.php
#!/usr/bin/php
<?php
date_default_timezone_set('Asia/Tokyo');
$today = date('Y年n月j日')."です。";
echo <<< _STR_
今日は${today}です。
_STR_
;
?>
$ php test.php
今日は2015年1月19日です。

参考文献・サイト:

数値

進数 表記
10 普通に表記 17, -34
2 先頭に0bを表記 0b1010(=10進数の10)※PHP 5.4.0から利用可能
8 先頭に0を表記 0123(=10進数の83)
16 先頭に0xを表記 0x1A(=10進数の26)
基数変換
基数1 ←関数 関数→ 基数2
2 - - 8
decbin bindec 10
- - 16
8 - octdec 10
- - 16
10 hexdec dechex 16

なお、2〜36の間で任意に基数(進数)変換を行うにはbase_convert(数値,元の基数,変換先)を用いる。11〜36進数ではa〜zの英字が用いられる(a=10,b=11,...,z=35)。

参考文献・サイト:

(ある程度)一意な値を得る方法

コマンド 備考
【書式】 uniqid(接頭辞,more_entropy);
【引数】
接頭辞
(文字列)指定は任意。指定がない場合の既定値は""(空文字列)。戻り値の前にここで指定した文字列を付加する。複数ホストでマイクロ秒まで完全に同じ時刻にアクセスすると同じIDが生成される可能性があるが、接頭辞をホストごとに変えると異なるホストに同じIDが発行されることを防げる。そのような使い方ができる。
more_entropy
(論理値)指定は任意。指定がない場合の既定値はfalse。trueを指定すると追加のランダム値が追加され一意になる可能性が高まる。
【戻り値】(文字列)マイクロ秒単位の現在時刻にもとづいた、接頭辞つきの一意な ID。 文字数は、more_entropyがfalseの場合「接頭辞の文字数+13文字」、trueの場合「接頭辞の文字数+23文字」。
この関数が生成する値は、暗号として安全ではないため、暗号として使うなら、random_int() か random_bytes() あるいは openssl_random_pseudo_bytes() を使うべき。
【例】
$ php -r "var_dump(uniqid());"
string(13) "58a3ae5632cb6"
$ php -r "var_dump(uniqid('hoge'));"
string(17) "hoge58a3ae6cbd61c"
$ php -r "var_dump(uniqid('',true));"
string(23) "58a3ae9cdb0765.65361913"
$ php -r "var_dump(uniqid('hoge',true));"
string(27) "hoge58a3aecd179a67.37155812"
【書式】 random_int(最小値,最大値);
【引数】
最小値
(整数)指定は必須。戻り値の最小値を指定する。この値は PHP_INT_MIN 以上である必要がある。
最大値
(整数)指定は必須。戻り値の最大値を指定する。この値は PHP_INT_MAX 以下である必要がある。
【戻り値】(整数)最小値以上、最大値以下の範囲で、暗号化されたランダムな整数値。
この関数が使えるのはPHP 7.0以降。
【例】
$ php -r "var_dump(random_int(0,100));"
int(88)
但し、PHP 5.2〜5.6で使えるものが別途つくられているとのこと。
【書式1】 rand();
【書式2】 rand(最小値,最大値);
【引数2】※書式1のように両方省略するか、書式2のように両方指定するかのどちらか
最小値
(整数)指定は必須。戻り値の最小値を指定する。
最大値
(整数)指定は必須。戻り値の最大値を指定する。
【戻り値1】(整数)0以上getrandmax以下の疑似乱数。
【戻り値2】(整数)最小値以上、最大値以下の疑似乱数。
この関数が生成する値は、暗号として安全ではないため、暗号として使うなら、random_int() か random_bytes() あるいは openssl_random_pseudo_bytes() を使うべき。
【例】
$ php -r "var_dump(rand());"
int(226590108)
$ php -r "var_dump(rand(5,10));"
int(7)
【書式】 random_bytes(長さ);
【引数】
長さ
(整数)指定は必須。返すランダム文字列の長さをバイト数で指定する。
【戻り値】(文字列)指定されたバイト数の、暗号化された安全なランダムバイナリ値。
この関数が使えるのはPHP 7.0以降。
【例】
$ php -r "var_dump(bin2hex(random_bytes(16)));"
string(32) "1dfb64415098d17f8d15cbe56907cad4"
但し、PHP 5.2〜5.6で使えるものが別途つくられているとのこと。
【書式】 getmypid();
【引数】なし
【戻り値】(整数)現在のPHPプロセスのIDを返す。エラーの場合は false を返す。
プロセスIDはある瞬間においては一意かもしれないが、時間差を空けて同じプロセスIDが再利用される可能性があるので、この関数が返す値だけを一意なIDとして使うべきではない。上に記す他の関数が返す値をつなげるなどした方がよい。
【例】
$ php -r "var_dump(getmypid());"
int(28410)
$ php -r "var_dump(getmypid().'_'.uniqid(rand().'_',true));"
string(40) "29104_1734255497_58a3bac85eae22.08791633"

演算

演算子の種類 名前 記述例 内容
代数演算子 正負逆転 -$a 値の符合を逆にする
加算 $a + $b $a と $bの合計
減算 $a - $b $a と $bの差
乗算 $a * $b $a と $bの積
除算 $a / $b $a を $bで割ったの商*
剰余 $a % $b $a を $bで割った余り。fmod関数でも同様の処理が可能。
演算代入 $a += $b $a の値に $b を加えた値を $a に代入
$a = $a + $bと同じ
加算子/減算子 前置加算子 ++$a $a に 1 を加えて$aを返す
後置加算子 $a++ $aを返してから$a に 1 を加える
前置減算子 --$a $a から 1 を引いて$aを返す
後置減算子 $a-- $aを返した後$a から 1 を引く
文字列演算子 結合演算子 $a . $b $a と $b を結合した文字列
結合代入演算子 $a .= $b $a に $b を追記
*
除数、被除数ともに整数で割りきれる場合には整数で、それ以外は浮動小数点値が返される。整数での商を得るには floor 関数(引数を越えない最大の整数を返す)を用いて商の小数点以下を切り捨てる。

比較演算子については以下の通り。

演算子 判定 備考
$a == $b 等しい 不問
  • 1 == "01" → true
  • 0 == false → true
  • NULL == false → true
整数値を文字列と比較する際、文字列は数値に変換される。
$a === $b 等しい 等しい
  • 1 === "01" → false
  • 0 === false → false
  • NULL == false → false
  • 1 === 1 → true
$a != $b
$a <> $b
等しくない 不問
  • 1 != "01" → false
  • 1 <> "02" → true
==の否定。
$a !== $b 値が等しくない、または型が違う
  • 1 !== "01" → true
  • 1 !== "02" → true
===の否定。
$a < $b $a は $b より小さい 不問 1 < "02" → true
$a > $b $a は $b より大きい 不問 3 > "02" → true
$a <= $b $a は $b 以下 不問 1 <= "02" → true
$a >= $b $a は $b 以上 不問 3 >= "02" → true
配列要素の演算
書式 内容
array_sum(配列変数) 配列変数の各要素の和を返す
array_product(配列変数) 配列変数の各要素の積を返す
ビット演算子
演算子 内容
$a & $b ビット積。両変数とも1になっているビットのみ1とした値を返す。
$a | $b ビット和。どちらかまたは両方が1になっているビットを1とした値を返す。
$a ^ $b ビット排他的論理和。どちらか一方が1になっているビットを1とした値を返す。
~ $a ビット否定。ビットを反転させた値を返す。
$a << $b ビット左シフト。$a のビットを $b ビット左にシフトする(=2$b倍する)
$a >> $b ビット右シフト。$a のビットを $b ビット右にシフトする(=1/2$b倍する)
$ cat test.php
<?php
$val1 = 0xa;
$val2 = 0x9;
echo "論理積(両方のビットがONならON)\n";
echo $val1.sprintf('(%04b_2)',$val1).' & '.$val2.sprintf('(%04b_2)',$val2).' = '.sprintf('%2d',$val1 & $val2).sprintf('(%04b_2)',$val1 & $val2)."\n";
echo "論理和(少なくともどちらか一方のビットがONならON)\n";
echo $val1.sprintf('(%04b_2)',$val1).' | '.$val2.sprintf('(%04b_2)',$val2).' = '.sprintf('%2d',$val1 | $val2).sprintf('(%04b_2)',$val1 | $val2)."\n";
echo "排他的論理和(一方がONでもう一方がOFFならON、論理和−論理積)\n";
echo $val1.sprintf('(%04b_2)',$val1).' ^ '.$val2.sprintf('(%04b_2)',$val2).' = '.sprintf('%2d',$val1 ^ $val2).sprintf('(%04b_2)',$val1 ^ $val2)."\n";
echo "否定(ビット反転)\n";
echo '~ '.$val1.sprintf('(%04b_2)',$val1).' = '.sprintf('%2d',~ $val1).sprintf('(%b_2)',~ $val1)."\n";
echo "ビット左シフト\n";
echo $val1.sprintf('(%04b_2)',$val1).' << 2'.sprintf('(%04b_2)',2).' = '.sprintf('%2d',$val1 << 2).sprintf('(%b_2)',$val1 << 2)."\n";
echo "ビット右シフト\n";
echo $val1.sprintf('(%04b_2)',$val1).' >> 2'.sprintf('(%04b_2)',2).' = '.sprintf('%2d',$val1 >> 2).sprintf('(%04b_2)',$val1 >> 2)."\n";
?>
$ php test.php

論理積(両方のビットがONならON)
10(1010_2) & 9(1001_2) =  8(1000_2)
論理和(少なくともどちらか一方のビットがONならON)
10(1010_2) | 9(1001_2) = 11(1011_2)
排他的論理和(一方がONでもう一方がOFFならON、論理和−論理積)
10(1010_2) ^ 9(1001_2) =  3(0011_2)
否定(ビット反転)
~ 10(1010_2) = -11(1111111111111111111111111111111111111111111111111111111111110101_2)
ビット左シフト
10(1010_2) << 2(0010_2) = 40(101000_2)
ビット右シフト
10(1010_2) >> 2(0010_2) =  2(0010_2)

参考文献・サイト:

数学関数

最大最小

maxminは最大、最小の値を返す。引数には1個の配列または1個以上の変数を指定する。

  • 配列を指定した場合は配列要素内で最大・最小の値、変数群を指定した場合は変数群の中で最大・最小の値が返される。
  • 値が数値ではない要素または変数については 0 とみなして判定される。
  • 同じ大きさの値が複数あった場合は、最初にあらわれたものを返す。
  • 最大最小値が 0 となった場合の扱いは以下の通り。
    文字種 扱い
    数値を含む 数値
    文字列のみ 文字コードが一番大きい(maxの場合)/小さい(minの場合)文字列

四捨五入・切り上げ・切り捨て

関数 書式 処理内容
round round(数値,丸める桁数,中間値の扱い); 四捨五入により指定桁に丸めた値を返す
ceil ceil(数値); 数値を越える整数の中で最も小さい整数を返す(小数点以下切り上げ)
floor floor(数値); 数値を超えない最大の整数を返す(小数点以下切り捨て)
丸める桁数
round関数において、四捨五入した結果を小数点以下何桁までの数値で返すかを数値で指定する。 負数を指定した場合は、小数点の上を意味する(例:-1→10の位、-2→100の位)。指定がない場合の既定値は0(小数点以下を四捨五入して整数に丸める)。
中間値の扱い
round関数において、丁度中間の値であった場合の扱いを指定する。指定できる値は下表の4種。
内容
PHP_ROUND_HALF_UP 丁度中間の値は切り上げる
(指定がない場合の既定の動作)
echo round(1.5, 0, PHP_ROUND_HALF_UP);
2
PHP_ROUND_HALF_DOWN 丁度中間の値は切り捨てる echo round(1.5, 0, PHP_ROUND_HALF_DOWN);
1
PHP_ROUND_HALF_EVEN 偶数側に丸める echo round(1.5, 0, PHP_ROUND_HALF_EVEN);
2

echo round(2.5, 0, PHP_ROUND_HALF_EVEN);
2

PHP_ROUND_HALF_ODD 奇数側に丸める echo round(1.5, 0, PHP_ROUND_HALF_ODD);
1

echo round(2.5, 0, PHP_ROUND_HALF_ODD);
3

余り(剰余)

fmodは指定した数で割り算した時の余り(剰余)を返す。

【書式】
fmod(被除数,除数);
【戻り値】
剰余
      

被除数 = 除数 × 商 + 余り」の関係になる。

%演算子を使った場合と同じ? 以下の例を見る限り、同じに見える。

$ cat test.php
<?php
echo "10 % 3 (10÷3の余り)= ".(10 % 3)."\n";
echo "fmod(10,3) (10÷3の余り)= ".fmod(10,3)."\n";
?>
$ php test.php
10 % 3 (10÷3の余り)= 1
fmod(10,3) (10÷3の余り)= 1

指数

powは指数計算を行う。

【書式】
pow(基数,指数);
      

戻り値は基数指数乗した値(整数型の値)。指数が計算できない場合は false を返す。

対数

log10は底を10とする対数を返す。その他の底を使う時はlogを用いる

【書式】
log10(真数);
log(真数,);

【引数】
真数:浮動小数点数(float)
[logのみ]:浮動小数点数(float)
 指定がない場合の既定値はネピア数(e、自然対数の底)

【戻り値】
[log10]
10を底とする真数の対数:浮動小数点数(float)
[log]
指定した底と真数に対する対数:浮動小数点数(float)

      

乱数

randは乱数を生成して返す。引数を指定しない場合は0からgetrandmaxの間の擬似乱数(整数)を、指定した場合はその範囲内の擬似乱数(整数)を返す。いずれも範囲には端点を含む。

【書式】
rand();
rand(最小値(整数),最大値(整数));
      

なお、randよりも生成速度などに優れたmt_rand関数もある。使い方は同じ。引数を指定しない場合の最大値はmt_getrandmaxで取得できる。

【書式】
mt_rand();
mt_rand(最小値(整数),最大値(整数));
      

一意な文字列を生成

uniqidはマイクロ秒単位の現在時刻にもとづいた、指定した接頭辞つきの一意な文字列を返す。戻り値の文字数は more_entropy が false の場合は(接頭辞+13 文字)、true の場合は(接頭辞+23 文字)。

【書式】
uniqid(接頭辞,more_entropy);
      
接頭辞
生成される値の前に付加する文字列。複数ホストで同時に値を生成する場合、同一時刻なら同一の値を生成してしまう可能性があるが、接頭辞を付加することでそのような事態を防ぐことができる。指定がない場合の既定値は空の接頭辞(接頭辞なし)。
more_entropy
true を指定すると、線形合同法を使用したエントロピーが戻り値の最後に追加され、結果の一意性がより増す。指定がない場合の既定値は false。

絶対値

absは絶対値を返す。引数が浮動小数点(float)型の値であった場合は浮動小数点型、それ以外は整数型の値を返す。

【書式】
abs();
      

入出力制御

echo などによる出力の出力先は、通常の場合標準出力(端末、ブラウザなど)となるが、ob_start を使うと一時的に出力先を内部バッファに変更できる。バッファの内容は ob_get_contents で文字列変数などに取り込むことができる。ob_end_flush はバッファの内容を出力し、ob_end_clean はバッファの内容を消去する。

ob_get_length は出力バッファの内容の長さをバイト単位で返す。

出力先のバッファリング開始(ob_start)

ob_startは出力のバッファリングを開始する。バッファリングを開始すると、ヘッダを除くスクリプトからの出力内容が内部バッファに蓄積される。

【書式】
ob_start();
【戻り値】
成功→true
失敗→false

出力バッファの内容取得、バッファリング終了、バッファ消去

コマンド 戻り値 バッファリング バッファ内容 標準出力への送信
ob_get_contents() バッファの内容※1 継続 保持 ×
ob_flush() なし 継続 消去
ob_clean() なし 継続 破棄 ×
ob_get_flush() バッファの内容※1 終了 消去
ob_get_clean() バッファの内容※1 終了 破棄 ×
ob_end_flush() 成功→true、失敗→false 終了 消去
ob_end_clean() 成功→true、失敗→false 終了 破棄 ×
  • ※1:出力バッファリングが有効になっている状態での戻り値。出力バッファリングが有効になっていない時の戻り値は false。
  • ※2:「消去」は標準出力にバッファ内容を送ってからバッファ内容を消去し、「破棄」は標準出力にバッファ内容を送ることなくバッファ内容を消去する。
【書式】
ob_get_contents();
【戻り値】
出力のバッファリングが有効になっている時→出力バッファの内容
出力のバッファリングが有効になっていない時→false
【例】
<?php
ob_start();  #- 出力バッファリング開始
$log = 'hoge.log';  #- 出力先ファイル名定義
$handle = fopen($log,'w');  #- 出力先ファイルを開く
if ($handle) {
  echo "The log file was opened successfully.\n";
} else {
  echo "The log file couldn't be opened.\n";
}
fwrite($handle,ob_get_contents());  #- バッファ内容をファイルに書き込む
fclose($handle);  #- ファイルを閉じる
?>

文字列処理

参考文献・サイト:

文字列の出力

特殊文字

改行は\n(UNIX系 LF),\n\r(DOS系 LF+CR),\r(Mac系 CR)。

echo, print

echoprintは文字列をそのまま出力する。どちらも引数を括弧でかこまなくてよい。

【書式】
echo 出力内容,出力内容,...
print 出力内容

【戻り値】
echo→なし
print→常に1

括弧はあってもなくてもOK

【例】
$ cat test.php
<?php
echo ("Hello World from echo with parentheses.\n");
print ("Hello World from print with parentheses.\n");
echo "Hello World from echo without parentheses.\n";
print "Hello World from print without parentheses.\n";
?>
$ php test.php
Hello World from echo with parentheses.
Hello World from print with parentheses.
Hello World from echo without parentheses.
Hello World from print without parentheses.

ダブルクォート(")で囲むと、中に記述した変数名や特殊文字(改行¥nなど)は解釈した結果に置換して出力される。シングルクォート(アポストロフィ、')で囲むと、解釈は行われない。

【例】
$ cat test.php
<?php
$keyword = 'Hello World';
echo "$keyword from echo\n surrounded by double quote.\n";
print "$keyword from print\n surrounded by double quote.\n";
echo '$keyword from echo\n surrounded by single quote.\n'."\n";
print '$keyword from print\n surrounded by single quote.\n'."\n";
?>
$ php test.php
Hello World from echo
 surrounded by double quote.
Hello World from print
 surrounded by double quote.
$keyword from echo\n surrounded by single quote.\n
$keyword from print\n surrounded by single quote.\n

複数行に渡って引数を記すこともできます。

【例】
$ cat test.php
<?php
echo "echoの引数は複数行に渡って
書くことができます\n";
print "printの引数も複数行に渡って
書くこともできます\n";
?>
$ php test.php
echoの引数は複数行に渡って
書くことができます
printの引数も複数行に渡って
書くこともできます

echo 文中に数値の計算式を記すときは全体を括弧で囲んでおく。

<?php
$x = 100;
$y = 120;
echo $x . " - " . $y . " = " . ($x -$y) . "\n";
echo $x . " - " . $y . " = " . $x -$y . "\n";
?>

【処理結果】
100 - 120 = -20
-20
	
指定書式で出力

printfは整形文字列を出力し、その長さを返す。 sprintfは整形文字列を出力し、その整形済み文字列を返す。

【書式】
(s)printf(書式指定,文字列1,文字列2...)

【例】
$num = 5;
$location = 'tree';
$format = 'There are %d monkeys in the %s'; ←"%d"は整数10進数、"%s"は文字列
printf($format, $num, $location); ←There are 5 monkeys in the tree

$format2 = 'The %2$s contains %1$d monkeys'; ←"%"+数値で何番目の引数を割り当てるかを指定できる
                                            (指定が無ければ登場順)
printf($format2, $num, $location); ←The tree contains 5 monkeys
	

書式設定にはそのままの文字が表示される通常の文字列と、それぞれ特定の変換を行う変換指定子を0個以上組み合わせて指定する。変換指定子(群)の先頭はパーセント記号(%)で始まる。

指定子種別 指定子 内容
符合指定子 %+ 数値に対して±の符合をつける。これがないと負値のみ符合がつく。
echo sprintf('%+d','12345');
 +12345
echo sprintf('%+d','-12345');
 -12345
echo sprintf('%d','12345');
 12345
echo sprintf('%d','-12345');
 -12345
パディング指定子 %埋める文字 表示幅指定子で指定した幅より文字列が短かった場合、指定幅になるまで埋める文字で埋める。埋める文字は空白文字または0はそのまま記し、それ以外の文字は前にシングルクォート(")を記す。
echo sprintf('% 10s','12345');
      12345
echo sprintf('%010s','hoge');
 000000hoge
echo sprintf('%'#10s','hoge');
 ######hoge
アライメント指定子 %- これを指定すると左寄せで出力される。指定しない場合は右寄せ。
echo sprintf('[%-10s]','hoge123');
 [hoge123   ]
echo sprintf('[%10s]','hoge123');
 [   hoge123]
表示幅指定子 %自然数 最低何桁(何文字幅)で表示するかを指定する。
精度指定子 %.自然数 浮動小数点に対して数値を何桁まで表示するかを指定する。文字列の場合はこの文字数を超えた分が切り捨てられる。
echo sprintf('%.2f','123.4567');
 123.45
echo sprintf('%.5f','123.4567');
 123.45670
echo sprintf('%.5f','hogehoge');
 hogeh
型指定子 % パーセント記号そのもの
%b 整数値に対応する2進数
echo sprintf('%b','55');
 110111
※10進数55を2進数に直すと "110111"
%c 整数値に対応するASCIIコードを持つ文字列
echo sprintf('%c','55');
 7
※キャラクターコード55の文字は "7"
%d 整数値に対応する10進数
echo sprintf('%d','55');
 55
%e 指数形式
echo sprintf('%e','55');
 5.50000e+1
%u 符合無し10進数。負数の場合2の補数(ビット反転して+1)に当たる正の10進数
echo sprintf('%e','-55');
 4294967241
%f 倍精度浮動小数点数
【例】小数点以下3桁表示
echo sprintf('%.3f','55');
 55.000
【例】8文字固定長右揃え
echo sprintf('% 8s',sprintf('%.3f','55'));
   55.000
%F 単精度浮動小数点数(PHP 4.3.10、5.0.3以降)
%o 整数として扱い8進数にして返す
%s 文字列
【例】通常、幅10文字右詰め、幅10文字左詰め
$ php -r "echo sprintf('[%s]','hoge').\"\n\";"
[hoge]
$ php -r "echo sprintf('[%10s]','hoge').\"\n\";"
[      hoge]
$ php -r "echo sprintf('[%-10s]','hoge').\"\n\";"
[hoge      ]
%x 16進数(小文字)
%X 16進数(大文字)
指定個出力(str_repeat)

str_repeatは文字列を指定回数繰り返した文字列を返す。

【書式と戻り値】
str_repeat(文字列,回数);
→文字列を指定回数繰り返した文字列(文字列 string 型)
文字列
繰り返す文字列(文字列 string 型)
回数
繰り返す回数(整数 int 型)。指定値は0以上である必要がある。0を指定すると空文字を返す。
print_r

文字列を整形して出力する。配列変数の内容を表示する場合などに便利。

変数情報を出力(var_dump)

var_dumpは、変数に関する情報を出力する。戻り値はなし。

==== test.php ===
<?php
$a = array(1, 2, array("a", "b", "c"));
$b = 1.23;
$c = true;
$d = "abc";
var_dump($a);
var_dump($b);
var_dump($c);
var_dump($d);
?>

=================
shell> ./test.php
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  array(3) {
    [0]=>
    string(1) "a"
    [1]=>
    string(1) "b"
    [2]=>
    string(1) "c"
  }
}
float(1.23)
bool(true)
string(3) "abc"

var_dumpの出力を変数に代入するには、出力バッファリングを使う[17]

【例】
<?php
ob_start(); # 出力バッファリング開始
var_dump($var); # 変数varの内容をダンプ
$output = ob_get_contents(); # バッファ内容を変数に代入
ob_end_clean(); # バッファ内容を破棄してバッファリング終了
?>

入力文字の取得

標準入力からの文字入力を取得したい場合、fgetsを使うとよい。ファイル名には「STDIN」を指定する。ファイルオープン処理は不要。

文字列情報

文字列の長さを返す

strlenは指定した文字列の長さをバイト単位で返す。マルチバイト文字は2以上にカウントされる。マルチバイト関数のオーバーロード設定で文字列関数が有効になっている場合はマルチバイト文字対応のmb_strlenで読み替えられる。その場合は、マルチバイト文字についても1文字とカウントされる。

【書式】
strlen(文字列)
mb_strlen(文字列,エンコーディング)
	
文字列の出現回数を返す(substr_count)

substr_countは指定文字列の出現回数を返す。

【書式】
substr_count(検査対象文字列,副文字列,検査開始位置,検査文字数);
【戻り値】
整数
検査対象文字列
この文字列の中を検査する。
副文字列
副文字列が検査対象文字列中に何回登場するかを検査する。既にカウントされた部分と重なる副文字列はカウントされない
【例】
$ php -r 'echo substr_count("hogehogehoge","hogehoge")."\n";'
1
検査開始位置
検査対象文字列の何文字目から検査を開始するかを指定する。最初の文字が0番目。指定がない場合の既定値は0。
検査文字数
検査開始位置から何文字分を検査対象とするかを指定する。検査対象文字列の末端を越えるような値(検査開始位置+検査文字数>検査対象文字列の長さ)を指定した場合、エラーが発生する。
【例】
$ php -r 'echo substr_count("abcdefg-abcedfg","abc")."\n";'
2
$ php -r 'echo substr_count("abcdefg-abcedfg","abc",0,3)."\n";'
1
$ php -r 'echo substr_count("abcdefg-abcedfg","abc",1,3)."\n";'
0
$ php -r 'echo substr_count("abcdefg-abcedfg","abc",8,3)."\n";'
1
$ php -r 'echo substr_count("abcdefg-abcedfg","abc",9,3)."\n";'
0
$ php -r 'echo substr_count("abcdefg-abcedfg","abc",8,8)."\n";' # 長さが1文字オーバーしている

Warning: substr_count(): Length value 8 exceeds string length in Command line code on line 1

文字列のMD5ハッシュ値を計算する(md5)

md5は指定した文字列のMD5ハッシュ値を計算する。ファイルのMD5ハッシュ値を計算する場合はmd5_fileを用いる。

【書式】
md5(文字列,raw_output);
【戻り値】
計算成功:ダイジェスト計算結果
計算失敗:false      
【必須】(文字列)文字列
計算対象とする文字列。
(真偽値)raw_output
trueを指定すると長さ16のバイナリデータで計算値(ダイジェスト)を返す。falseを指定すると32文字の16進数でMD5ハッシュ値を返す。指定がない場合の既定値は false。

文字列の検索置換変換など

参考文献・サイト:

単純文字列検索(位置検出)

strposは文字列が別の文字列中で見つかれば「最初に出現する位置を示す整数」(先頭が0番)を返し、見つからなければfalseを返す。単純文字列検索に使える。なお、文字列が見つからないことを検知する際、"===" 演算子を使う(またはその否定形"!==")。"==" 演算子だと型が論理値型(boolean)ではないがfalseを意味する 0 なども検知されてしまう(最初の文字にヒットした場合は0が返る)。

【書式】
strpos(検索対象文字列,検索内容,開始位置)

【戻り値】
文字列が見つかった場合:見つかった位置(文字列の最初が0文字目)
見つからなかった場合:false
検索内容
検索したい内容を指定する。文字列で指定した場合はその文字列が、数値で指定した場合は整数に変換し、その番号?に対応する文字が検索される。
開始位置
検索対象文字列の先頭を0番目として検索開始位置を指定する。このオプションを指定した場合でも、戻り値は先頭から数えた位置となる。

strposは任意長の文字列を検索できるのに対し、指定文字列の先頭文字だけを取り出して検索したい場合はstrrposを用いる。マルチバイト関数オーバーロードが有効な場合はマルチバイト対応可能なmb_strposが自動的に適用される。

正規表現を用いた文字列検索(preg_match、preg_match_all)

preg_matchはPerl互換正規表現構文による文字列検索を行う。指定パターンを検出した時点で検索を終了して 1 を返す。検出しなければ 0、何らかのエラーがあれば False を返す。マッチ回数を取得したいならpreg_match_allを用いる(戻り値はヒット回数またはFalse)。正規表現については正規表現も参照のこと。マルチバイト文字にも対応した検索についてはmb_ereg参照のこと。

【書式と戻り値】
preg_match(検索パターン,検索対象文字列,結果格納配列,フラグ,検索開始位置)
検出した場合→1(整数 (int) 型)
検出しなかった場合→0(整数 (int) 型)
エラー発生→false(論理 (boolean) 型)

preg_match_all(検索パターン,検索対象文字列,結果格納配列,フラグ,検索開始位置)
検出した場合→検出した個数(整数 (int) 型)
検出しなかった場合→0(整数 (int) 型)
エラー発生→false(論理 (boolean) 型)
検索パターン
パターンの前後をスラッシュではさんで表記する(例:"/^[abc]/")。なお、ereg系関数の場合はスラッシュ不要。
結果格納配列

preg_matchの場合、結果格納配列を指定すると指定した名前の配列変数に検索結果が格納される。結果格納配列[0] にはパターン全体に一致した文字列が、結果格納配列[1] 以降にはキャプチャ用サブパターン(検索パターン中に(...)で指定したパターングループ)に一致した文字列が代入される。

preg_match_allの場合、結果格納配列を指定するとフラグの指定に応じた内容が指定した名前の配列変数に検索結果が格納される。格納内容はフラグの項目参照。

フラグ

preg_matchの場合、フラグに指定できる値は "PREG_OFFSET_CAPTURE" のみ。このフラグを指定すると、戻り値は一致回数(0か1)に加え、パターンが見つかった位置のオフセット値(先頭を0としてバイト単位で数えた値、UTF-8の場合平仮名、カタカナ、漢字などは3バイト、半角英数字記号は1バイトとしてカウント)も含む配列となる。また結果格納配列にもこのオフセット値が追加される。

preg_match_allの場合、フラグに指定できる値とそれぞれの場合に結果格納配列へ格納される値は以下の通り。指定しない場合の既定値は "PREG_PATTERN_ORDER"。値による指定も可能[18]

結果格納配列[0]への格納値 結果格納配列[1]への格納値
PREG_PATTERN_ORDER 1 パターン全体に一致した文字列の配列、[0][0]が最初に一致した値、[0][1]が2番目に一致した値。 最初のサブパターンに一致した文字列の配列、[1][0]が最初に一致した値、[1][1]が2番目に一致した値。
PREG_SET_ORDER 2 最初に検索パターンに一致した値の配列。[0][0]が全体、[0][1]以降がサブパターン。 2番目に検索パターンに一致した値の配列。[1][0]が全体、[1][1]以降がサブパターン。
PREG_OFFSET_CAPTURE 256 結果格納パターンは既定値の"PREG_PATTERN_ORDER"と同じ。 このフラグを指定すると、戻り値は一致回数(0か1)に加え、パターンが見つかった位置のオフセット値(先頭を0としてバイト単位で数えた値、UTF-8の場合平仮名、カタカナ、漢字などは3バイト、半角英数字記号は1バイトとしてカウント)も含む配列となる。また結果格納配列にもこのオフセット値が追加される。
検索開始位置
指定すると検索対象文字列の指定位置(先頭文字が0番目)から検索を開始する。

パターンの後に任意で以下の修飾子を指定することができる(例:/pattern/i、大文字小文字を区別しない)。参照:PHP: 正規表現パターンに使用可能な修飾子 - Manual

修飾子 内容
i 大文字小文字を区別せずマッチする
m 通常、文字列は単一行として扱われるため、行頭指定(^)や行末指定($)は文字列の最初や最後にしかマッチしないが、この修飾子を指定すると文字列の最初・最後に加えて各改行の直後・直前にもマッチするようになる。
s 通常、任意の1文字を意味するドット(.)は改行にはマッチしないが、この修飾子を指定すると改行にもマッチするようになる。
【例1】preg_match→パターンに一致する文字列が1つ見つかったら終わり
$a = 'カロテノイドとその産物が働いているところをPDBに登録されたいくつかの構造で見ることができる。多くのβ-カロテン分子が、光合成で光を捕らえるのに用いられる大きな光化学系で見られる。上図左に示した例はシアノバクテリアから得られた[[mom:022|光化学系I]](PDBエントリー [[PDB:1jb0]])である。端には橙色で示したいくつかのβ-カロテン分子が見える。レチナールはβ-カロテンの半分の大きさで、上図右に示した[[mom:027|ロドプシン]](rhodopsin、PDBエントリー [[PDB:1f88]])のような光感覚蛋白質で見られる。ピンク色で示したレチナールは蛋白質の内側奥深くに埋まっており、そこでリジン(lysine)アミノ酸が付加されている。';
preg_match('/\[\[mom:(.+?)\|(.+?)\]\]/',$a,$match);
print_r($match);

【実行結果】
Array
(
    [0] => [[mom:022|光化学系I]]
    [1] => 022
    [2] => 光化学系I
)

【例2】preg_match + PREG_OFFSET_CAPTUREフラグ
preg_match('/\[\[mom:(.+?)\|(.+?)\]\]/',$a,$match,PREG_OFFSET_CAPTURE);
print_r($match);

【実行結果】
Array
(
    [0] => Array
        (
            [0] => [[mom:022|光化学系I]]
            [1] => 330
        )

    [1] => Array
        (
            [0] => 022
            [1] => 336
        )

    [2] => Array
        (
            [0] => 光化学系I
            [1] => 340
        )
)

【例3】preg_match_all→見つかってもその後の文字列から検索続行、最後まで
preg_match_all('/\[\[mom:(.+?)\|(.+?)\]\]/',$a,$match,PREG_PATTERN_ORDER);
print_r($match); このフラグは既定値と同じなのでなくても動作は同じ↑

【実行結果】
Array
(
    [0] => Array
        (
            [0] => [[mom:022|光化学系I]]
            [1] => [[mom:027|ロドプシン]]
        )

    [1] => Array
        (
            [0] => 022
            [1] => 027
        )

    [2] => Array
        (
            [0] => 光化学系I
            [1] => ロドプシン
        )

)

【例4】preg_match_all、フラグPREG_SET_ORDER
preg_match_all('/\[\[mom:(.+?)\|(.+?)\]\]/',$a,$match,PREG_SET_ORDER);
print_r($match);

【実行結果】
Array
(
    [0] => Array
        (
            [0] => [[mom:022|光化学系I]]
            [1] => 022
            [2] => 光化学系I
        )

    [1] => Array
        (
            [0] => [[mom:027|ロドプシン]]
            [1] => 027
            [2] => ロドプシン
        )

)
【例5】preg_match_all、フラグ PREG_OFFSET_CAPTURE  
preg_match_all('/\[\[mom:(.+?)\|(.+?)\]\]/',$a,$match,PREG_OFFSET_CAPTURE);
print_r($match); ↑既定のフラグ PREG_PATTERN_ORDER の内容に加え、見つかった場所をオクテット(バイト)値で示す値が追加される。

【実行結果】
Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => [[mom:022|光化学系I]]
                    [1] => 330
                )

            [1] => Array
                (
                    [0] => [[mom:027|ロドプシン]]
                    [1] => 563
                )

        )

    [1] => Array
        (
            [0] => Array
                (
                    [0] => 022
                    [1] => 336
                )

            [1] => Array
                (
                    [0] => 027
                    [1] => 569
                )

        )

    [2] => Array
        (
            [0] => Array
                (
                    [0] => 光化学系I
                    [1] => 340
                )

            [1] => Array
                (
                    [0] => ロドプシン
                    [1] => 573
                )

        )

)
	
正規表現を用いた文字列検索のマルチバイト文字対応(mb_ereg)

マルチバイト文字に対応した正規表現検索を行うにはmb_eregを用いる(preg_matchと似ているが、こちらはマルチバイト文字に対応していない)。マッチした部分文字列が不要ならmb_ereg_matchを使ってもよい。

【書式】
mb_ereg(検索パターン,検索対象文字列,結果格納変数)
mb_ereg_match(検索パターン,検索対象文字列)
	
検索パターン
検索パターンを正規表現で指定する。preg系関数とは異なり、パターンはスラッシュ(/)で囲まない。また検索対象文字列の先頭にのみマッチするため、任意の場所を検索したいならパターンの前に .* (任意の文字0回以上)を付加しておく。
結果格納変数
マッチした部分の文字列。

mb_eregは検索パターンにヒットした場合、結果格納変数を指定していなければ1を、指定していればヒットした部分のバイト数を返す。それ以外の場合はfalseを返す。

mb_ereg_matchは検索パターンにヒットすればtrue、ヒットしなければfalseを返す。

cat test.php
<?php
$str = 'ふらいぱん';
echo $str." →「ぱん」で検索 ... ";
if (mb_ereg_match('ぱん',$str)) {
  echo "Hit!\n";
} else {
  echo "Not Hit!\n";
}
echo $str." →「.*ぱん」で検索 ... ";
if (mb_ereg_match('.*ぱん',$str)) {
  echo "Hit!\n";
} else {
  echo "Not Hit!\n";
}
?>
php test.php
ふらいぱん →「ぱん」で検索 ... Not Hit!
ふらいぱん →「.*ぱん」で検索 ... Hit!

preg_match_allのマルチバイト文字対応版に当たる、複数回のヒットに対応した関数は用意されていないが、mb_ereg_search_init(検索条件初期設定を行う)とmb_ereg_search_regs(実際の検索を行う)を使って相応の関数を定義できる。但し以下の点に注意。

  • preg_match_allの引数に指定する検索パターンは / ... / のようにスラッシュではさむが、mb_ereg系関数ではパターンをスラッシュで囲んではいけない。
  • preg_match_allでは第3引数にヒットパターン受領変数を指定するが下記関数では戻り値を受け取る必要がある。
function mb_ereg_match_all($pattern,$subject)
{
  #- マルチバイト文字列検索設定(失敗したらfalseを返して終了)
  if (!mb_ereg_search_init($subject,$pattern)) {
    return false;
  } else {
    #- 結果格納配列変数初期値セット(空配列)
    $matches = array();
    #- 見つからなくなるまで検索を繰り返す
    while ($match = mb_ereg_search_regs()) {
      $matches[] = $match;
    }
    return $matches;
  }
}

使用例

$ cat test.php
<?php
$str = '我々と最も近縁な[哺乳類 ほにゅうるい]のミオグロビンは我々のものとかなり似ているが、[爬虫類 はちゅうるい]や魚類になると分化からより長い時間が経っており違いはより大きくなっている。';
preg_match_all('/[^\[]?[\[]([^\[]+?) +?([^\[]+?)[\]][^\]]?/',$str,$match);
$match2 = mb_ereg_match_all('[^\[]?[\[]([^\[]+?) +?([^\[]+?)[\]][^\]]?',$str);
echo "Search Items (preg_match_all):\n";
echo var_dump($match);
echo "Search Items (mb_ereg_match_all):\n";
echo var_dump($match2);
?>
$ php test.php
Search Items (preg_match_all):
array(3) {
  [0]=>
  array(2) {
    [0]=>
    string(32) "�[哺乳類 ほにゅうるい]�"
    [1]=>
    string(32) "�[爬虫類 はちゅうるい]�"
  }
  [1]=>
  array(2) {
    [0]=>
    string(9) "哺乳類"
    [1]=>
    string(9) "爬虫類"
  }
  [2]=>
  array(2) {
    [0]=>
    string(18) "ほにゅうるい"
    [1]=>
    string(18) "はちゅうるい"
  }
}
Search Items (mb_ereg_match_all):
array(2) {
  [0]=>
  array(3) {
    [0]=>
    string(36) "な[哺乳類 ほにゅうるい]の"
    [1]=>
    string(9) "哺乳類"
    [2]=>
    string(18) "ほにゅうるい"
  }
  [1]=>
  array(3) {
    [0]=>
    string(36) "、[爬虫類 はちゅうるい]や"
    [1]=>
    string(9) "爬虫類"
    [2]=>
    string(18) "はちゅうるい"
  }
}

参考文献・サイト

配列からパターンにマッチした要素を取り出す(preg_grep)

preg_grepは、配列の要素のうち、指定した正規表現パターンにマッチするものを要素とする配列を返す。

【書式】
preg_grep(正規表現パターン,配列,フラグ)
【戻り値】
[配列]指定した正規表現パターンにマッチするものを要素とする配列。配列キーは配列のまま。
	
正規表現パターン
[文字列]正規表現パターンを示す文字列。
配列
[配列]検索対象配列。
フラグ
[整数]PREG_GREP_INVERT(または 1?)を設定すると指定したパターンに「マッチしない」要素を返す。指定がない場合の既定値は 0。
【例】
$ cat test.php
<?php
$array = array('tiger','leopard','snow leopard','lion','mountain lion','mavericks','yosemite');
echo "【元配列】";
print_r($array);
echo "【leopardを含む】";
print_r(preg_grep('/leopard/',$array));
?>
$ php test.php
【元配列】Array
(
    [0] => tiger
    [1] => leopard
    [2] => snow leopard
    [3] => lion
    [4] => mountain lion
    [5] => mavericks
    [6] => yosemite
)
【leopardを含む】Array
(
    [1] => leopard
    [2] => snow leopard
)
	
単純文字列置換(str_replace)

str_replaceは、検索対象の中で見つかった検索内容を全て置換内容と置き換えて返す。正規表現を使わない単純な文字列置換。

【書式】
str_replace(検索内容,置換内容,検索対象,置換数格納先)
【戻り値】
置換後の文字列または配列。
	
検索内容(必須)
検索文字列または検索文字列を各要素に持つ配列。
置換内容(必須)
置換文字列または置換文字列を各要素に持つ配列。 検索内容が配列で置換内容が文字列である場合、検索内容に指定した配列の各要素値が全て置換内容に指定した文字列に置換される。 検索内容、置換内容ともに配列の場合、同じ順序に位置する配列要素が対応付けされて検索置換される(配列キーは関係なし)。置換内容配列の配列要素数の方が少なく対応する置換内容要素がない場合は空文字に置換される。
検索対象(必須)
検索する対象とする文字列。配列の場合、配列の各要素について検索と置換が行われる。
置換数格納先(任意)
指定した場合、マッチし置換された箇所の個数が指定した変数に格納される。

文字列の検索置換変換などに戻る

文字の変換、部分文字列置換(strtr)

strtrは、文字の変換や部分文字列置換を行う。

【書式】文字単位での置換
strtr(置換対象文字列,置換対象文字群,置換後文字群);
【戻り値】
変換後の文字列
	

置換対象文字列の中で、置換対象文字群のn文字目が見つかると置換後文字群のn文字目の文字と置換された値が返る。置換対象文字群置換後文字群の文字列長が同じでなかった場合、長い方の前部、短い方と同じ長さ分だけ用いられ、それより後の部分は無視される。

【書式】文字列単位での置換
strtr(置換対象文字列,置換対応群);
【戻り値】
変換後の文字列
但し、置換対応群の中に空文字のキーがあるとfalseを返す。
	

置換対応群には、検索文字列をキー、置換後文字列を値した要素群を指定する。複数のキーに一致する場合、より長いキーの方が優先される。

【例】
$ cat test.php
<?php
$str = "abccbadef";
echo $str."\n";
echo strtr($str,"abc","123")."\n";
echo strtr($str,"abc","12345")."\n";
echo strtr($str,"abcde","123")."\n";
echo strtr($str,array("abc"=>"123","ab"=>"xxx"));
?>
$ php test.php
abccbadef
123321def # a→1、b→2、c→3 の置換
123321def # 置換後文字の4,5は無視
123321def # 置換前文字のd,eは無視
123cbadef # abc→123 の置換、ab→xxxの置換はabcより短く優先度下なので適用されない
	
正規表現を用いた文字列置換(preg_replace)

preg_replaceは、Perl互換正規表現構文による文字列置換を行う。正規表現については正規表現も参照のこと。

【書式】
preg_replace(検索パターン,置換パターン,検索置換対象,置換上限回数,置換数格納先);
【戻り値】
検索置換対象が文字列→文字列
検索置換対象が配列→配列

文字列または配列の各要素の扱い
検索パターンにマッチした→置換後の値
検索パターンにマッチしない→検索置換対象そのまま

エラーがあった場合→NULL
	
検索パターン
検索パターンを指示する文字列、または各要素に検索パターン指示文字列を格納した配列。各パターンはPerl互換正規表現('/(検索パターン)/(修飾子)')で記述する。
置換パターン
置換パターンを指示する文字列、または各要素に置換パターン指示文字列を格納した配列。検索パターンが配列で置換パターンが文字列の場合、全ての検索パターンが同一の置換パターンに置換される。検索パターン、置換パターンいずれも配列の場合、各検索パターンは対応する順序に位置する置換パターン要素に置換される(配列キーは関係なし)。検索パターン配列要素の数>置換パターン配列要素の数、であった場合、対応する要素がない検索パターンは空文字に置換される。
検索パターンの一部を引用する「後方参照」はドル記号($)の後に数値を記して示す。数値は0から99までの整数(0は検索パターン全体、1は一番目のサブパターン、...を示す)。後方参照の直後に数字そのものを記したい場合、${1}1 のように後方参照の番号を中括弧で囲むことで数値そのものなのか後方参照番号の一部なのかを明確に区別できる。バックスラッシュ+数値でも後方参照を表記できるが、このような区別ができないので、ドル記号による後方参照を使用するのが望ましい。
検索置換対象
検索置換を行う対象とする文字列、または配列。配列を指定した場合、検索置換は配列の各要素に対して行われ、結果も配列で返る。
置換上限回数(任意)
置換を行う最大回数。既定値は-1(制限なし)
置換数格納先(任意)
この引数を指定すると指定した変数に置換回数が渡される。

戻り値は、置換後の文字列または配列。マッチしなかった場合は元の$subjectがそのまま返される。エラーが発生した場合はNULLが返される。

検索パターンの修飾子は以下の通り。

修飾子意味
gマッチしたものを全件拾う
i大文字と小文字を区別しない
m文字列を複数行として扱う(この指定があると行末指定は実際の行末)
o変数展開を1回行う
s文字列を単一行として扱う(この指定があると行末指定時に改行文字を無視)
x拡張正規表現を使う
【例1】
<script>
$string = '$pname はでんぶんを加水分解する酵素の1つです。';
$pattern = '/¥$pname/';
$replacement ='アミラーゼ';
echo preg_replace($pattern,$replacement,$string);
<結果>
アミラーゼ はでんぶんを加水分解する酵素の1つです。

【例2】
<script>
$string = '右図上部に示したのはノイラミニダーゼ([[PDB:1nn2]])で、4つの同じサブユニットが四角く並んでいる。'
$pattern = '/¥¥[¥[(PDB):([0-9a-z]{4})¥]¥]/';
$replacement = '$1エントリー:<a href="http://pdbjs8.pdbj.org/xPSSS/xPSSSSearch?search_type=pdbid_search&query=$2">$2</a>'
echo preg_replace($pattern,$replacement,$string);
<結果>
右図上部に示したのはノイラミニダーゼ(PDBエントリー:<a href="http://pdbjs8.pdbj.org/xPSSS/xPSSSSearch?search_type=pdbid_search&query=1nn2">1nn2</a>)で、4つの同じサブユニットが四角く並んでいる。
	
正規表現を用いた文字列置換のマルチバイト文字対応

マルチバイト文字に対応した正規表現検索を行うにはmb_ereg_replaceを用いる。大文字小文字の区別をしない場合はmb_eregi_replacemb_ereg_replaceで i オプションをつけたのと同じ)。使用するエンコードは内部エンコーディングまたはmb_regex_encodingで指定したもの。

【書式】
mb_ereg_replace(検索パターン,置換パターン,置換対象文字列,オプション);
	

オプション

i
大文字小文字の区別をしない
x
空白無視
m
マルチラインモード(改行も「.」(任意の1文字)に含まれるようになる)
p
POSIXモード(改行も通常文字とみなす)
e
置換後文字列がPHPの式として評価される

置換に成功した場合は置換後の文字列を、エラー発生時はfalseを返す。

【例】
<?php
echo "<html>\n<body>\n";
$a = "あいうえお.jpg あいうえお.png あかさたな.jpg";

echo "<p>\$a は「" . $a . "」です。</p>\n";
echo "<p>「あ」で始まり、「.jpg」で終わる場合、「あ」を「か」に置換します。</p>\n";
echo "<p>結果は「" . mb_ereg_replace('あ([^ ]+?\.jpg)','か\1',$a) . "」です。</p>\n";
echo "</body>\n</html>\n";
?>

※パターンについて
[^ ]: 空白( )以外
+?\.jpg: 1文字以上最短マッチ(最初の .jpg でヒット範囲は停止)

【出力結果】
$a は「あいうえお.jpg あいうえお.png あかさたな.jpg」です。
「あ」で始まり、「.jpg」で終わる場合、「あ」を「か」に置換します。
結果は「かいうえお.jpg あいうえお.png かかさたな.jpg」です。
	
前後から指定文字を除去

trimは指定文字列の先頭末尾にある指定文字を削除した文字列を返す。またltrimは先頭だけを対象に、rtrimは末尾だけを対象にして指定文字を削除し、削除済みの文字列を返す。削除対象とする文字の指定がない場合の既定値は空白文字(NULL、タブ、改行などを含む、詳細は下記参照)。

【書式】
trim(文字列,削除対象文字);
ltrim(文字列,削除対象文字);
rtrim(文字列,削除対象文字);
【戻り値】
指定文字削除済み文字列
削除対象文字
文字を列挙するか、または範囲で指定(範囲指定は..で行う)。例:「 \t.」(スペース、タブ、ピリオド)、「\x00..\x1F」(ASCII 0〜31 の制御文字群)。指定がない場合の既定値は以下の空白文字列。
  • NULバイト(\0、ASCII 0 (0x00))
  • タブ(\t、ASCII 9 (0x09))
  • 復帰(\n、ASCII 10 (0x0A))
  • 垂直タブ(\x0B、ASCII 11 (0x0B))
  • 改行(\r、ASCII 13 (0x0D))
  • スペース(ASCII 32 (0x20))
文字列比較(strcmp)
文字列の一部を取得(substr)

substrは、文字列の一部を返す。位置指定はバイト単位で行うため、マルチバイト文字についてはバイト数を考慮してカウントし指定する必要がある。マルチバイト関数のオーバーロード設定で文字列関数のオーバーロードを有効にしている場合は、mb_substrと読み替えられる。その場合は文字種にかかわらず1文字としてカウントされる。

【書式】
substr(処理対象文字列, 開始位置, 長さ)
mb_substr(処理対象文字列, 開始位置, 長さ)

【例1】
$rest = substr("abcdef", 0, 3);     → "abc" を返す(正数は先頭からのカウント、先頭文字が0番目)
$rest = substr("abcdef", 3);     → "def" を返す(第2引数がない場合は最後まで)
$rest = substr("abcdef", -1);    → "f" を返す(負数は末尾からのカウント、最後の文字が-1番目)
$rest = substr("abcdef", -2);    → "ef" を返す
$rest = substr("abcdef", -3, 1); → "d" を返す
$rest = substr("abcdef", 0, -1);  → "abcde" を返す
$rest = substr("abcdef", 2, -1);  → "cde" を返す
$rest = substr("abcdef", 4, -4);  → "" を返す
$rest = substr("abcdef", -3, -1); → "de" を返す

【例2】UPDATE datatable SET name="jiro",species="shiba",sex="male" WHERE name="taro" を生成
$datalist = array('name'=>'jiro,'species'=>'shiba','sex'=>'male');
$qstr = 'UPDATE datatable SET ';
foreach($datalist as $key=>$value) { 
  $qstr = $qstr . $key . '="' . $value . '",';
}
$qstr = substr($qstr,0,-1) . ' WHERE name="' . 'taro' . '"';
↑最後の1文字(カンマ)を除去してから WHERE...を追加している

【例3】@より前の部分を取り出す
<?php
$address = "user@mail.hoge.com";
$local = substr($address,0,strpos($address,'@'));
↑0番目(先頭文字)からn文字取り出す
 n='@'の場所、先頭を0として数えているのでn文字取り出すと丁度@の直前文字までになる
 strposコマンドも参照のこと
echo $local;
?>
user
	
開始位置
値が0か正である場合、処理対象文字列の最初からから開始位置番目(最初が0番目)から始まる文字列が返される。 値が負である場合、処理対象文字列の末尾から数えて開始位置番目(末尾が-1番目)から始まる文字列が返される。 処理対象文字列の長さが開始位置文字以下の場合は FALSE が返される。
長さ
値が正である場合、開始位置から長さ文字分が返される。 値が負である場合、処理対象文字列末尾から長さ番目(末尾が-1番目)分が切り取られた文字列が返される。もし切り取り範囲が開始位置を越えていた場合は空文字が返される。
文字列の分割

以下の通りいくつか文字列を分割する関数がある。詳細は各節を参照のこと。

関数 分割基準 戻り値
explode(区切り文字列,対象文字列,最大要素数) 指定文字列 配列
preg_split(パターン,対象文字列,最大要素数,フラグ) 正規表現
str_split(対象文字列,分割部最大長) 文字数
wordwrap(対象文字列,文字数,分割文字列,cut) 文字数 文字列
explode(区切り文字列,対象文字列,最大要素数)

explodeは文字列を指定した文字列で分割し、各部分文字列を要素とする配列を返す。

$ php -r "print_r(explode(',','Shiga,Kyoto,Osaka,Hyogo,Nara,Wakayama'));"
Array
(
    [0] => Shiga
    [1] => Kyoto
    [2] => Osaka
    [3] => Hyogo
    [4] => Nara
    [5] => Wakayama
)

explodeは文字列を指定した文字列で分割し、各部分文字列を要素とする配列を返す。最大要素数に正の値を指定した場合、返される配列の要素数はこの指定値以内となり、部分文字列の個数がこの値を越えた場合は最後の要素に対象文字列の残り全てが格納される。負の値が指定された場合は、最後の"-要素数"個の要素を除く全てが返される。0を指定すると1を指定したものとみなされる(=全てが1個の要素に格納される)。このパラメータを省略した場合は、全ての要素が返される。

区切り文字列が空("")の場合、戻り値はfalse。 区切り文字列対象文字列に含まれず、要素数が負である場合は対象文字列全体を含む要素を1つ持った配列を返す。

preg_split(パターン,対象文字列,最大要素数,フラグ)

preg_splitパターンで指定した正規表現にマッチした文字列で対象文字列を分割し、各部分文字列を要素に持つ配列を返す。

最大要素数として自然数を指定すると、分割要素数は最大でも指定した個数となり、残った文字列は最後の要素に含められる。最大要素数に0または-1を指定すると「制限なし」を指定したものとして扱われる(既定値は-1)。

フラグには次のフラグを組み合わせたものを指定する。ビット論理和演算子「|」で指定を組み合わせることもできる。

PREG_SPLIT_NO_EMPTY
空文字でないものだけが返される。
$ php -r "var_dump(preg_split('/,/','alpha,,gamma,delta'));"
array(4) {
  [0]=>
  string(5) "alpha"
  [1]=>
  string(0) ""      ←PREG_SPLIT_NO_EMPTYオプションを付けるとこれは除外される
  [2]=>
  string(5) "gamma"
  [3]=>
  string(5) "delta"
}
$ php -r "var_dump(preg_split('/,/','alpha,,gamma,delta',-1,PREG_SPLIT_NO_EMPTY));"
array(3) {
  [0]=>
  string(5) "alpha"
  [1]=>
  string(5) "gamma"
  [2]=>
  string(5) "delta"
}
PREG_SPLIT_DELIM_CAPTURE
分割文字列パターン中のサブパターンで取得された値も返される。
$ php -r "print_r(preg_split('/(\(.+?\)),/', 'midosuji(red),tanimachi(perple),yotsubashi(blue),chuo(green),sennichimae(pink),sakaisuji(brown),nagahori-tsurumiryokuchi(lime green),imazatosuji(orange),', -1,PREG_SPLIT_NO_EMPTY));"
# "\(.+?\)" で ?(最短マッチ指定)を付けないと最長パターン「(red),...(orange)」にマッチ
# 対象文字列最後にあるコンマの後の空文字はPREG_SPLIT_NO_EMPTYオプションで除外
Array
(
    [0] => midosuji
    [1] => tanimachi
    [2] => yotsubashi
    [3] => chuo
    [4] => sennichimae
    [5] => sakaisuji
    [6] => nagahori-tsurumiryokuchi
    [7] => imazatosuji
)
$ php -r "print_r(preg_split('/(\(.+?\)),/', 'midosuji(red),tanimachi(perple),yotsubashi(blue),chuo(green),sennichimae(pink),sakaisuji(brown),nagahori-tsurumiryokuchi(lime green),imazatosuji(orange),', -1,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE));"
# サブパターン「\(.+?\)」(括弧で囲まれた文字列)もキャプチャー
Array
(
    [0] => midosuji
    [1] => (red)
    [2] => tanimachi
    [3] => (perple)
    [4] => yotsubashi
    [5] => (blue)
    [6] => chuo
    [7] => (green)
    [8] => sennichimae
    [9] => (pink)
    [10] => sakaisuji
    [11] => (brown)
    [12] => nagahori-tsurumiryokuchi
    [13] => (lime green)
    [14] => imazatosuji
    [15] => (orange)
)
PREG_SPLIT_OFFSET_CAPTURE
返される各要素は配列となり、要素0にはマッチした部分文字列、要素1には対象文字列中で部分文字列の開始位置(先頭が0)が格納される。
$ php -r "print_r(preg_split('/ /','hypertext language programming'));"
Array
(
    [0] => hypertext
    [1] => language
    [2] => programming
)
$ php -r "print_r(preg_split('/ /','hypertext language programming',-1,PREG_SPLIT_OFFSET_CAPTURE));"
Array
(
    [0] => Array
        (
            [0] => hypertext
            [1] => 0
        )

    [1] => Array
        (
            [0] => language
            [1] => 10
        )

    [2] => Array
        (
            [0] => programming
            [1] => 19
        )

)
		
str_split(対象文字列,分割部最大長)
str_splitは指定文字数ごとに文字列を分割してそれぞれを配列要素に格納する。最後の要素は指定文字数に満たない場合がある。分割部最大長の既定値は1。
【例】3文字ずつに分ける
<?php
$array = str_split("abcdefghij",3);
?>

Array
(
  [0] => abc
  [1] => def
  [2] => ghi
  [3] => j
)
wordwrap(対象文字列,文字数,分割文字列,cut)
wordwrapは指定文字数ごとに分割文字列を挿入する。cut に true をセットすると、指定幅より長い単語でも強制的に分割される。文字数の既定値は75、分割文字列の既定値は改行(LF、\n)。
【例】40文字ごとに改行を入れる。
$ php -r 'echo wordwrap("This is a pen. That is a pencire erasers. Those are three pairs of scissors.",40)."\n";'
This is a pen. That is a pencil. These
are erasers. Those are three pairs of
scissors.
【例】長い単語を強制改行
$ php -r 'echo wordwrap("abcdefghijklmnopqrstuvwxyz",10,"\n")."\n";'
abcdefghijklmnopqrstuvwxyz
$ php -r 'echo wordwrap("abcdefghijklmnopqrstuvwxyz",10,"\n",true)."\n";'
abcdefghij
klmnopqrst
uvwxyz
文字列の大文字小文字変換
関数 内容
strtolower(文字列) 文字列を全て小文字にする
strtoupper(文字列) 文字列を全て大文字にする
lcfirst(文字列) 先頭文字がアルファベットなら小文字に変換する(他は変更しない)
ucfirst(文字列) 先頭文字がアルファベットなら大文字に変換する(他は変更しない)
ucwords(文字列) 文字がアルファベットの場合、各単語の先頭文字を大文字にする。 ここで言う単語は空白文字(スペース、LF、CR、LF+CR、水平tab、垂直tab)の直後にあるあらゆる文字列を指す。

「アルファベット」の範囲はロケール情報に依存する(既定ではウムラウトがついた文字などは含まれない)。

【例1】
$str = "This is a pen.\n";
echo $str;
$str = strtoupper($str);
echo $str;
$str = strtolower($str);
echo $str;
$str = ucfirst($str);
echo $str;
$str = ucwords($str);
echo $str;

【結果】
This is a pen.
THIS IS A PEN.
this is a pen.
This is a pen.
This Is A Pen.
	
html関係の文字列変換

htmlspecialcharsは、そのままhtmlソースコード上に記述すればhtmlのコードとして認識され意図しない出力となってしまう文字群にエスケープ処理を施し、文字そのもの(実体参照)が表示されるように変換する。逆に元に戻すのがhtmlspecialchars_decode

【書式】
htmlspecialchars(文字列,フラグ,文字セット,double_encode)
【戻り値】
変換後の文字列
但し、文字列中に

オプション

文字列
変換対象文字列
フラグ
下記フラグが指定可能。フラグ名(複数指定する場合は論理和演算子"|"でつなぐ)またはビット値の和で指定する。既定値は ENT_COMPAT | ENT_HTML401(不等号、アンパサンド、ダブルクォートを変換、コードを HTML 4.01 として処理)。
フラグ名 ビット値 説明
ENT_COMPAT 2 ダブルクオートは変換しますがシングルクオートは変換しません。
ENT_QUOTES 3 シングルクオートとダブルクオートを共に変換します。
ENT_NOQUOTES 0 シングルクオートとダブルクオートは共に変換されません。
ENT_IGNORE 4 無効な符号単位シーケンスを含む文字列を渡したときに、 空の文字列を返すのではなく無効な部分を切り捨てるようになります。 これは過去との互換性のために残されているものです。 セキュリティの問題が発生する可能性があるので、使わないようにしましょう。
ENT_SUBSTITUTE 8 無効な符号単位シーケンスを含む文字列を渡したときに、 空の文字列を返すのではなく Unicode の置換文字に置き換えます。 UTF-8 の場合は U+FFFD、それ以外の場合は &#FFFD; となります。
ENT_DISALLOWED 128 指定した文書型において無効な符号単位シーケンスを含む文字列を渡したときに、 Unicode の置換文字に置き換えます。 UTF-8 の場合は U+FFFD、それ以外の場合は &#FFFD; となります。
ENT_HTML401 0 コードを HTML 4.01 として処理します。
ENT_XML1 16 コードを XML 1 として処理します。
ENT_XHTML 32 コードを XHTML として処理します。
ENT_HTML5 (16|32) コードを HTML 5 として処理します。
文字セット(PHP 4.1.0以降)
変換に使用される文字セットを指定する。既定値は ISO-8859-1。
double_encode(PHP 5.2.3以降)
falseに設定すると既存の html エンティティをエンコードしない。既定値はtrue(既存のエンティティも含めてすべて変換)。

文字列に含まれる &(アンパサンド)、'(シングルクォート)、"(ダブルクォート)、<、>(不等号)をエスケープする。

対象文字列 エスケープ処理後文字列 第2引数
なし ENT_NOQUOTES ENT_QUOTES
& &amp;
' &#039; × ×
" &quot; ×
< &lt;
> &gt;

配列の各要素に対してhtmlエスケープを行いたい場合はforeachを併用する。

【出展】PHP Manual: htmlspecialchars
<?php
function htmlspecialchars_deep($mixed, $quote_style = ENT_QUOTES, $charset = 'UTF-8')
{
  if (is_array($mixed)) {
    foreach($mixed as $key => $value) {
      $mixed[$key] = htmlspecialchars_deep($value, $quote_style, $charset);
    }
  } elseif (is_string($mixed)) {
    $mixed = htmlspecialchars(htmlspecialchars_decode($mixed, $quote_style), $quote_style, $charset);
  }
  return $mixed;
}
?>

$mixed: 配列または文字列(必須)
$quote_style: 引用符の扱い(任意、無指定時の既定値は引用符も全てエスケープ)
$charset: 文字コード(任意、無指定時の既定値はUTF-8)
	

元の文字列に戻す、htmlspecialcharsとは逆の操作を行うコマンドがhtmlspecialchars_decode。引数指定はhtmlspecialcharsと同じ。

URLエンコード

urlencodeは、文字列をURLで許可されている形式に変換(エンコーディング)する。具体的には-_. を除くすべての非英数文字が % 記号 (%)に続く2桁の16進数で、空白は + 記号(+)に置換される。rawurlencodeも同様だが、除外対象にチルダ (~) が加わり(PHP 5.3.0以降)、空白は他の非英数文字と同様に % + 2桁の16進数(%20)に置き換えられる点が異なる。 PHP 5.3.0以降におけるrawurlencodeの動作はRFC 3986で規定されたエンコーディング方法、PHP 5.3.0より前のバージョンではRFC 1738の規定に基づきチルダ (~) もエンコードされていた。 urlencoderawurlencodeの違いを以下にまとめた。

文字 urlencode rawurlencode 備考
+ %20 空白
~ %7E ~ チルダ
【例】PHP 5.3.0以降の場合
$ cat test.php
<?php
$array = array(' -_.~','!"#$%&\'()*+,/',
             ':;<=>?@',
             '[\]^`{|}',
             '¥');
foreach ($array as $val) {
  echo $val."\n";
  echo "  urlencode   : ".urlencode($val)."\n";
  echo "  rawurlencode: ".rawurlencode($val)."\n";
}
?>
$ php test.php
 -_.~
  urlencode   : +-_.%7E
  rawurlencode: %20-_.~
!"#$%&'()*+,/
  urlencode   : %21%22%23%24%25%26%27%28%29%2A%2B%2C%2F
  rawurlencode: %21%22%23%24%25%26%27%28%29%2A%2B%2C%2F
:;<=>?@
  urlencode   : %3A%3B%3C%3D%3E%3F%40
  rawurlencode: %3A%3B%3C%3D%3E%3F%40
[\]^`{|}
  urlencode   : %5B%5C%5D%5E%60%7B%7C%7D
  rawurlencode: %5B%5C%5D%5E%60%7B%7C%7D
¥
  urlencode   : %C2%A5
  rawurlencode: %C2%A5

逆の変換を行うのが、urldecoderawurldecode

MySQLクエリ文エスケープ

↑上位目次(文字列の検索置換変換など)に戻る

MySQLに送るクエリ文(mysql_querymysqli_queryで指定するクエリ文)を、安全な形式に変換するにはmysql_real_escape_string(旧式MySQLコマンド)、mysqli_real_escape_string(改良型MySQLiコマンド)を用いる。このコマンドは、具体的には以下の各文字列の直前にバックスラッシュを付加してエスケープ処理を行う。

元の値 処理後の値 処理内容 値の内容
\x00 '\x00' シングルクォートで囲む NULコード(ASCII 0x00、ヌル)
\n '\n' LFコード(ASCII 0x0A、Line Feed(改行、UNIX改行コード)
\r '\r' CRコード(ASCII 0x0D、Carriage Return(復帰、Mac改行コード)
\x1a '\x1a' SUBコード(ASCII 0x1A、Substitute(置換))
\ \\ 先頭にバックスラッシュを付加
' \'
" \"

※オンラインマニュアル本文では上記全てに対して、「先頭にバックスラッシュ付加」の処理を行うと記載されているが、下部のユーザコメントによると上記の通り一部はクォート処理になるとのこと。

【MySQL】
mysql_real_escape_string(文字列,接続ハンドル)

【MySQLi オブジェクト指向型】
mysqli::real_escape_string(文字列)

【MySQLi 手続き型】
mysqli_real_escape_string(接続ハンドル,文字列)

【戻り値】
エスケープ済みの文字列
	
文字列
エスケープ処理対象文字列。
接続ハンドル
MySQL 接続を特定する接続ハンドル。省略すると、直近に開かれたMySQL接続が対象となる。直近に開かれた接続が無かった場合、引数を指定せずに mysql_connect() がコールした時と同様にリンクを確立する。リンクが見付からない、または、確立できない場合、 E_WARNING レベルのエラーが生成される。

サーバレベル、またはmysqli_set_charsetコマンドで文字セット(文字コード)をあらかじめ指定しておく必要あり。

参考文献・サイト:

↑上位目次(文字列の検索置換変換など)に戻る

暗号化、ハッシュ

cryptは指定した文字列のハッシュを返す。

配列関係の文字列処理

配列の各要素を指定文字列でつなぐ(implode)

implodeは、配列の各要素を指定文字列でつないだ文字列を返す。その逆をするのがexplode

【書式】
implode(つなぎ文字列,配列)

【例】
$array = array('a','b','c');
$comma_separated = implode(",",$array);
echo $comma_separated;
a,b,c
	

マルチバイト関数

マルチバイト関数を利用するには、mbstring関数を有効にする必要がある。インストール後の設定参照。

文字エンコーディングの変換

mb_convert_encodingは指定の文字列の文字エンコーディングを変換した値を返す。

【書式】
mb_convert_encoding(文字列,変換後文字エンコーディング名,変換前文字エンコーディング)

【例】Shift JISに変換
$str = mb_convert_encoding($str, "SJIS");
	
変換後文字エンコーディング
ASCII、JIS、UTF-8、EUC-JP、SJIS
変換前文字エンコーディング
指定しなければ内部エンコーディングが使用される。
MIMEヘッダの文字列をエンコードする

mb_encode_mimeheader

mb_encode_mimeheader(文字列,文字列のエンコーディング,MIMEエンコーディング方式);
	
言語設定値の取得、設定

mb_languageは、現在の言語設定情報の取得や変更を行う。この設定に基づきメール送信のエンコーディングが決定される。

【書式1】現在の言語設定情報の取得
mb_language
→戻り値は言語名(言語設定が事前に行われている場合)または false
【書式2】現在の言語設定情報を変更
mb_language(エンコーディング指定文字列)
→戻り値はtrue(指定が有効な値であった場合)またはfalse
	

エンコーディング指定文字列に使用できる文字列は以下のいずれか。各値を設定した場合のメール送信のエンコーディングも合わせて記す

エンコーディング指定文字列 メール送信エンコーディング
Japanese ISO-2022-JP/Base64
ja
English ISO-8859-1/quoted printable
en
English UTF-8/Base64
内部エンコーディング設定値の取得、設定

mb_internal_encodingは内部文字エンコーディング情報の取得や変更を行う。

【書式1】現在の内部文字エンコーディング情報の取得
mb_internal_encoding
→戻り値は現在の内部エンコーディング名
【書式2】現在の内部文字エンコーディング情報の変更
mb_language(エンコーディング指定文字列)
→戻り値はtrue(設定に成功した場合)またはfalse(設定に失敗した場合)
	

エンコーディング指定文字列に指定できる文字は次に挙げるものなど。大文字小文字は区別しない?

  • UTF-8
  • ASCII
  • JIS
  • ISO-2022-JP
  • EUC-JP
  • eucJP-win
  • SJIS
  • SJIS-win

参考文献・サイト:

キャラクターコード関係

chrは指定コード(10進数で表記したキャラクターコード)に対する文字を、ordは、指定文字列の最初の文字に対するキャラクターコードを返す。

【書式】
chr(キャラクターコード)
ord(文字列)
      

マルチバイト文字をord関数で処理した場合、1文字目の先頭1バイトだけのコードが返る。

【例】
echo dechex(ord('あ')); UTF-8の場合「あ」の文字コードは「e38182」
e3

$ php -r "echo 'aaa'.chr(8).'bbb';" キャラクターコード08はBS(BackSpace、後退)、1文字戻る
aabbb
$ php -r "echo 'aaa'.chr(10).'bbb';" キャラクターコード10(16進数で0A)はLF(LineFeed、改行)
aaa
bbb
$ php -r "echo 'aaa'.chr(11).'bbb';" キャラクターコード11(16進数で0B)はVT(Vertical Tabulation、垂直タブ)
aaa
   bbb
$ php -r "echo 'aaa'.chr(12).'bbb';" キャラクターコード12(16進数で0C)はFF(Form Feed、改ページ)だがVTと見た目は同じ?
aaa
   bbb
$ php -r "echo 'aaa'.chr(13).'bbb';" キャラクターコード13(16進数で0D)はCR(Carriage Return、復帰)
bbb
$ php -r "echo 'aaaaa'.chr(13).'bbb'.chr(10);" 復帰しても上書きする文字列の方が短ければ元の文字列が残る
bbbaa
      

マルチバイト文字のコード全体を得るにはmb_convert_encoding関数で1バイトずつのASCII文字に変換し、それぞれの文字コードを得てつなげる以下のようなユーザ定義関数を用意する。

function uniord($u) {
    $k = mb_convert_encoding($u, 'UCS-2LE', 'UTF-8');
    $k1 = ord(substr($k, 0, 1));
    $k2 = ord(substr($k, 1, 1));
    return $k2 * 256 + $k1;
}
【出展】PHP Manual: ord の "v0rbiz at yahoo dot com" 氏によるコメント

上記関数を使った例。

echo dechex(uniord('あ'));
3042
「あ」のUnicode(UTF-16)は16進数で「3042」(2進数で 0011|0000|0100|0010)。
(※UTF-8は、判別符合を付加し 1110|0011| 10|0000|01 1000|0010 (16進数で e38182))
ASCII文字のキャラクターコードでは、30→"0"、42→"B" なので、
「あ」をUCS-2LE(LEは下位ビットが先に来る)に変換すると"B0"。
$k1="0x42"(10進数で66), $k2="0x30"(10進数で48)となり、
戻り値は48×256+66=12354(dechexで16進数に変換すると3042)。

      

日付時刻

現在時刻を得る(time)

timeは、現在時刻をUNIXタイム(1970年1月1日 00:00:00 GMTからの積算秒数)で返す。

【書式】
time()
      

時刻を整形して出力(date)

dateは、

【書式】
date(書式指定,UNIXタイム値)

書式指定には定義済み定数または書式文字列を指定する。UNIXタイム値(1970年1月1日 00:00:00 GMTからの積算秒数)を指定しない場合の既定値は現在時刻(=time()の戻り値)。

定義済み定数
相当する書式 備考
DATE_RSS D, d M Y H:i:s Mon, 15 Aug 2005 15:52:01 +0000 RSS書式
主な書式文字列
種類 書式文字 内容 戻り値の例
Y 西暦を4桁表示 1999, 2009
y 西暦の下2桁を表示 99, 09
L 閏年かどうか 閏年→1、非閏年→0
n 月の数字表記。先頭の0は表記しない。 112
m 月を常に2桁の数字で表記。 0112
t 指定月の日数。 2831
F 月名をフルスペルで表記。 JanuaryDecember
M 月名を3文字形式で表記。 JanDec
W 月曜日に始まる年単位の週番号(ISO-8601形式) 年の42週目→42
j 日の数字表記。先頭の0は表記しない。 131
d 日を常に2桁の数字で表記。 0131
S 英語の序数を示す接尾辞2文字。jと併用可能。 st, nd, rd, thのいずれか
z 年通算日。1/1が0。 0365
曜日 N 曜日の数値表記(ISO-8601 形式) 1(月曜日)〜7(日曜日)
w 曜日の数値表記 0(日曜日)〜6(土曜日)
l 曜日のフルスペル表記 SundaySaturday
D 曜日の3文字表記 SunSat
午前午後 a 午前午後を小文字2文字表記 am, pm
A 午前午後を大文字2文字表記 AM, PM
g 時を12時間単位で表記、1桁時は10の位の0を付けない。 112
G 時を24時間単位で表記、1桁時は10の位の0を付けない。 023
h 時を12時間単位で2桁表記、1桁時は10の位の0を付ける。 0112
H 時を24時間単位で2桁表記、1桁時は10の位の0を付ける。 0023
i 分を常に2桁の数値で表記。 0059
s 秒を常に2桁の数値で表記。 0059
タイムゾーン O グリニッジ標準時(GMT)との時差 例:+0900
P グリニッジ標準時(GMT)との時差、時と分の間にコロンあり(PHP 5.1.3以降) 例:+09:00
T タイムゾーン名略称 例:JST
e タイムゾーン名(PHP 5.1.0 で追加) 例:Asia/Tokyo
総合 c ISO 8601 形式の日付(PHP5以降、'Y-m-d\TH:i:sP' 相当) 例:2004-09-28T13:53:21+09:00
r RFC 2822 形式の日付('D, d M Y H:i:s O' 相当) 例:Mon, 28 Sep 2009 13:53:21 +0900
U Unixタイム(1970年1月1日0時0分0秒からの積算秒数) 例:1254171201
【例】
# UNIXタイム0=1970年1月1日 0:00:00(UTC)
$ php -r 'echo date("Y/m/d H:i:s O(T)",0)."\n";'
1970/01/01 09:00:00 +0900(JST)
# 現在時刻
$ php -r 'echo date("Y/m/d H:i:s O(T)")."\n";'
2013/08/27 15:31:19 +0900(JST)

指定日時に対応するUNIXタイムスタンプを得る(mktime)

mktimeは、指定日時に対応するUNIXタイムスタンプ(1970年1月1日 00:00:00からの積算秒数)を返す。引数は後ろから順に省略可能で、省略された値はローカルの日付時刻値に従った現在の値にセットされる。引数が不正であった場合は false が返る(PHP 5.1以降の場合、それより前は -1)。PHP 5.1以降で全ての引数を省略すると E_STRICT notice を返すようになったので、現在時刻のUNIXタイムスタンプを得るにはtimeを使うこと。

【書式】
mktime(,,,,,)
→整数(UNIXタイムスタンプ)または false(PHP 5.1以降、それより前は-1)
      
整数値。0-23は指定日の当日、負数は指定日の0時から遡った時間、24以上は翌日以降の該当時間を表す。指定がない場合の既定値は現在の時(date('H')の戻り値)だが、PHP 5.1以降では全ての引数を省略することはできない。
整数値。0-59は指定時内の分、負数は指定時の0分から遡った時間、60以上は次の時以降の該当分を表す。指定がない場合の既定値は現在の分(date('i')の戻り値)。
整数値。0-59は指定分内の秒、負数は指定分の0秒から遡った時間、60以上は次の分以降の該当秒を表す。指定がない場合の既定値は現在の秒(date('s')の戻り値)。
整数値。前年末から数えた月数。1-12は指定年内の月と一致。0 は前年12月、負数は前年12月から遡った月、13以上は翌年以降の該当月を表す。指定がない場合の既定値は現在の月(date('n')の戻り値)。
整数値。前月末から数えた月数。指定月内に存在する日と同じ値については月内の日、0 は前月末日、、負数は前月末日から遡った日、指定月の末日より大きな値は翌月以降の該当日を表す。指定がない場合の既定値は現在の日(date('j')の戻り値)。
整数値。2,3桁または4桁で西暦を指定。2,3桁の場合、0-69は2000-2069年、70-100は1970-2000年を表す。4桁の場合、1901-2038が指定可能。指定がない場合の既定値は現在の年(date('Y')の戻り値)。
【例】現在から72時間前
$ cat test.php
#!/usr/bin/php
<?php
date_default_timezone_set('Asia/Tokyo'); # PHP 5.1以降、既定時間帯の設定は必須(php.iniに設定していない場合)
echo date('Y/m/d H:i:s',mktime(date('H')-72));
echo " (UNIX epoch: ".mktime(date('H')-72).")\n";
?>
$ php ./test.php
2011/05/10 13:04:39 (UNIX epoch: 1305000279)

【例】前月の年月
$ php -r "date_default_timezone_set('Asia/Tokyo');echo 'Today is '.date('Y/m/d').\"\n\";"
Today is 2011/08/01
$ php -r "date_default_timezone_set('Asia/Tokyo');echo 'The last month is '.date('Y/m',mktime(0,0,0,date('m')-1)).\"\n\";"
The last month is 2011/07
      

既定のタイムゾーン設定(date_default_timezone_set)

date_default_timezone_setは、日付/時刻関数で 使用されるタイムゾーンの既定値を設定する。PHP初期設定ファイルのdate.timezoneに設定しても同じ(記述例:date.timezone = 'Asia/Tokyo')。PHP 5.1.0 以降、タイムゾーンを 正しく設定せずに日付/時刻関数をコールすると E_NOTICE が発生し、システムの設定や TZ 環境変数を 使用すると E_WARNING エラーが発生するようになっている。

【書式】
date_default_timezone_set(タイムゾーン識別子);
【戻り値】
正しいタイムゾーン識別子→true
正しくないタイムゾーン識別子→false

【例】
date_default_timezone_set('Asia/Tokyo');

# 既定タイムゾーンの設定がないと、警告が出る
$ cat test.php
#!/usr/bin/php
<?php
$today = date('Y年n月j日');
echo <<< _STR_
今日は${today}です。

_STR_
;
?>
$ php test.php
Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead in /Library/Webserver/Documents/kw1/jv/test/test.php on line 3
今日は2015年1月19日です。
# 既定タイムゾーンの設定を追加すると、警告が出なくなった
$ cat test2.php
#!/usr/bin/php
<?php
date_default_timezone_set('Asia/Tokyo');
$today = date('Y年n月j日');
echo <<< _STR_
今日は${today}です。

_STR_
;
?>
$ php test2.php
今日は2015年1月19日です。

文字列をUNIXタイムスタンプに変換(strtotime)

strtotimeは英語の書式で書かれた日付をUnixタイムスタンプ(1970 年 1 月 1 日 00:00:00 UTC からの経過秒数)に変換する。

【書式】
strtotime(文字列,起点となる時刻);
【引数】
文字列:[文字列]日付や時刻を含む文字列
起点となる時刻:[整数]戻り値を計算する際、起点となる時刻のUNIXタイムスタンプ。
指定がなかった場合の既定値は現在時刻(timeの戻り値)

【戻り値】
成功→[整数]タイムスタンプ
失敗→false

【例】
$ cat test.php
<?php
$strlist = array("now","10 September 2000","+1 day","+1 week","+1 week 2 days 4 hours 2 seconds",
  "next Thursday","last Monday","2018/02/01","03/02/01","2018-02-01");
foreach ($strlist as $str) {
  echo date('Y-m-d H:i:s O(T)',strtotime($str)).' ('.strtotime($str).')'.' <- '.$str."\n";
}
?>
$ php test.php
2018-02-21 15:01:40 +0900(JST) (1519192900) <- now
2000-09-10 00:00:00 +0900(JST) (968511600) <- 10 September 2000
2018-02-22 15:01:40 +0900(JST) (1519279300) <- +1 day
2018-02-28 15:01:40 +0900(JST) (1519797700) <- +1 week
2018-03-02 19:01:42 +0900(JST) (1519984902) <- +1 week 2 days 4 hours 2 seconds
2018-02-22 00:00:00 +0900(JST) (1519225200) <- next Thursday
2018-02-19 00:00:00 +0900(JST) (1518966000) <- last Monday
2018-02-01 00:00:00 +0900(JST) (1517410800) <- 2018/02/01
2001-03-02 00:00:00 +0900(JST) (983458800) <- 03/02/01
2018-02-01 00:00:00 +0900(JST) (1517410800) <- 2018-02-01

日付の表記には注意が必要。スラッシュ区切りはアメリカ風の m/d/y 、ダッシュ (-) あるいはドット (.) で区切られている場合はヨーロッパ風の d-m-y であるとみなす。年を二桁で表して区切り文字がダッシュ (-) である場合は、 y-m-d であるとみなす。

このような曖昧さを避けるためにも、ISO 8601 形式 (YYYY-MM-DD) を使うか、可能であれば DateTime::createFromFormat() を使うことが推奨される。

型判定、変換

型判定・値の比較

書式列のリンク先はPHP Manualの各ページ。

書式 Trueパターン
ctype_digit(文字列) 文字列が全て数字だった場合。
※「数値」は文字列ではないのでFalseが返る。数値もtrueを返して欲しい場合はis_numericを用いる。
is_numeric(変数) 変数が数値または全て数字で構成される文字列であった場合('1a'など英字を含む16進数表記も'0x1a'と記して16進数である宣言を行えばtrueになる)。
is_int(変数) 変数が整数であった場合。
is_float(変数) 変数が浮動小数点型(float)であった場合。
is_bool(変数) 変数が真偽値型(boolean)であった場合。
is_null(変数) 変数がNULLであった場合。
is_string(変数) 変数が文字列であった場合。
is_array(変数) 変数が配列であった場合。
is_object(変数) 変数がオブジェクトであった場合。
is_resource(変数) 変数がリソース型であった場合。リソース型はオープンされたファイル、データベース接続、イメージキャンバスエリアのような特殊なハンドルを保持する変数型。
判定 備考
$src = array(1,0,0,0,1,0,0,0,1,0,0,0);
$dest = array(1,0,0,0,1,0,0,0,1,0,0,0);
$src == $dest;
true 配列同士の比較も可能
array() == NULL; true 空配列とNULL
array() === NULL; false 空配列は型判定まで含むとNULLとは一致しない

型変換

前に"()" と記すことで型を宣言(型キャスト)できる。

$a = 100; // $a は整数
$b = (string) $a; // $b は文字列
      

利用できる型キャストは以下の通り。

型キャスト記述
(int), (integer) 整数
(bool), (boolean) 論理値
(float), (double), (real) float(浮動小数点)値
(string) 文字列
(array) 配列
(object) オブジェクト
(unset) NULL(PHP5)

intvalは、指定された文字列を整数に変換する。

【書式】
intval(変数名,基数);
      

戻り値は以下の通り。

引数、状況 戻り値
変換成功 (指定基数の整数値)
変換失敗 0
空の配列
空のオブジェクト
空ではない配列 1
空ではないオブジェクト
文字列 先頭(左側)に1つ以上の数字があればその数字群が示す数値、そうでなければ0
論理値 false は 0、true は 1

英字を含む引数に指定した場合、「数値または.」+「e/E」+「数値または.」の形式なら数値とみなされる。基数に10より大きい値を指定した場合で、該当値に当たる文字があれば数値とみなされる(例:16進数のA~F)。それ以外の英字は0となる。

【例】
intval(42); → 42
intval(4.2); → 4
intval('42'); → 42
intval('+42'); → 42
intval(042); → 42
intval('042'); → 42
intval('42',8); → 34、8進数の"42"が10進数の整数値に変換される
intval('0x1f'); → 0、英字を含むと原則として0になる
intval('0x1f',16); → 31、基数を指定するとa〜fも数字文字列とみなされる
intval('1f',16); → 31、基数16を指定すれば"0x"を前に付けなくても16進数とみなされる
intval('01f',16); → 31、頭に空桁があっても同じ

なお、intvalは出力形式を指定できないので、出力形式を指定したい場合はsprintfを用いる。

バイナリ値を16進数値に変換するにはbin2hexを用いる。

逆16進数値をバイナリ値に変換するにはhex2binを用いる。

繰り返し処理

変数の操作と条件指定で繰り返し処理を行う(for)

forは指定回数繰り返し処理を行うのに使える。

【書式】
for (式1;式2;式3) {
  
}
      

式1は繰り返し処理全体の開始時、無条件に実行される。 式2は各回繰り返し処理開始時に評価され、結果がTrueならが実行される。Falseなら繰り返し処理は終了する。 式3は各回繰り返し処理後、無条件に実行される。

【例】
for ($i = 1; $i <= 10; $i++) {
  echo $i . " ";
}
【結果】
1 2 3 4 5 6 7 8 9 10
      

まず最初に「$i = 1」($i に 1 を代入する)が実行されて繰り返し処理が開始される。 「$i <= 10」($i は 10 以下)の評価結果はTrueなので「$i . " "」($i と空白を出力)が実行される。その後「$i++」($i に 1 を足す)が実行されて次のループに進む。10回ループが実行され $i が 11 になった時、$i <= 10がFalseになるので繰り返し処理は終了する。

配列要素全体に対して処理する(foreach)

foreachは配列の全要素に対して処理を行う。

【書式】
foreach (配列変数 as 一時変数名)
foreach (配列変数 as 一時変数キー名=>一時変数名)

【例】
$a = array(1,2,3);
foreach ($a as $item) {
  echo $item * 2 . ",";
}
2,4,6
foreach ($a as $key=>$item) {
  $b[$key] = $item * 2;
}
print_r($b);
Array
(
  [0] => 2
  [1] => 4
  [2] => 6
)
      

条件を満たす間繰り返す(while,do while)

whileは最初に条件判定を行い条件を満たしている間処理を繰り返す。do-whileは最低1回は処理を行ってから条件判定を行う。

【書式】
while (条件) {
  処理
}
do {
  処理
} while (条件);

【例】
$i = 1;
while ($i <= 10) { ←$iが10以下である間は繰り返す
  echo $i++ . " "; ←$iを表示してから1を加える(→演算参照)
}
1 2 3 4 5 6 7 8 9 10 $i=10の処理→次は$i=11なので処理されず終了

do {
  echo $i++ . " ";
} while ($i <= 10); ←$iが10以下である間は繰り返す
11 まず処理実行→その後判定→$i=12>10なので条件に合わず終了
      

ループを出る(break)

breakは for, foreach, while, do-while, switch 構造の実行を終了する。引数を省略すると直近のループ構造のみを出る(つまり既定値は1)。

【書式】
break ループ構造を抜ける段数
ループ構造を抜ける段数
(自然数)ループ構造を抜ける段数を自然数で指定する。値の指定がない場合の既定値は1。PHP 5.4.0以降、0は指定できなくなった(それまでは1と同じ意味に解釈されていた)。また、同バージョンより変数は指定できなくなった。

参考文献・サイト:

定義済み変数

PHP の定義済み変数のうち「スーパーグローバル」は、スクリプト全体を通して全てのスコープで使用可能。関数やメソッドの内部からアクセスする際にも global $variable; などの宣言は不要。スーパーグローバルには以下のものがある。

現在の設定値はコマンドラインで直接コードを実行(→参照:直接コマンドライン上にコードを記述する)して確認できる(但し、スクリプト上でないと確認できない項目もある)

shell> php -r 'print_r($_SERVER);'
Array
(
    [HOSTNAME] => www.hoge.com
    [TERM] => xterm-color
    [SHELL] => /bin/bash
...
)
    

下記の例は、

ローカル絶対パス
/var/www/html/index.php
リモート絶対パス
http://www.hoge.com/foo/index.php
GET文字列も含めたリモート絶対パス
http://www.hoge.com/foo/index.php?p=123&q=abc

$_SERVER

$_SERVERの各キーと対応する値の内容、例を以下に示す。

変数 内容
$_SERVER['SERVER_PROTOCOL'] HTTP/1.1 プロトコル名、バージョン
$_SERVER['SERVER_SOFTWARE'] Apache/2.2.3 (Red Hat) ウェブサーバのソフトウェア名、バージョン
$_SERVER['REQUEST_METHOD'] GET リクエストメソッド名(GET,HEAD,POST,PUTなど)
$_SERVER['SERVER_NAME'] www.hoge.com サーバのホスト名
$_SERVER['HOSTNAME'] www.hoge.com サーバのホスト名
$_SERVER['SERVER_ADDR'] 1.2.3.4 サーバのIPアドレス
$_SERVER['PHP_SELF'] /foo/test.php リモート絶対パス+ファイル名
$_SERVER['SCRIPT_NAME'] /foo/test.php PHP_SELFとは常に同じ? REQUEST_URIとは以下の場合に値が異なる。
  • GETメソッドによるURL引数がファイル名の後についている場合(例:$_SERVER['REQUEST_URI'] → /foo/index.php?p=123、$_SERVER['SCRIPT_NAME'] → /foo/index.php)
  • ファイル名を指定せずDirectoryIndexに設定したファイルが表示されている場合(例:$_SERVER['REQUEST_URI'] → /foo/、$_SERVER['SCRIPT_NAME'] → /foo/index.php)
$_SERVER['REQUEST_URI'] /foo/test.php?p=123&q=abc アクセスURIの絶対パス+ファイル名+クエリ文字列。URI末尾にある#以降の文字列(id属性値で表示するページ内の位置を指定する)は含まれない。
$_SERVER['QUERY_STRING'] p=123&q=abc クエリ文字列(ファイル名の後に記す?より後の文字列)
$_SERVER['DOCUMENT_ROOT'] /var/www/html ドキュメントルートのローカル絶対パス
$_SERVER['SCRIPT_FILENAME'] /var/www/html/foo/test.php ローカル絶対パス+ファイル名
__FILE__ /var/www/html/foo/test.php $_SERVER['SCRIPT_FILENAME']と同じ
$_SERVER['HTTP_USER_AGENT'] Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; ja-JP-mac; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 リクエストにUser-Agent:ヘッダがあればその内容
$_SERVER['HTTP_ACCEPT_LANGUAGE'] ja
ja,en-us;q=0.8,en;q=0.7,zh-cn;q=0.5,zh-tw;q=0.3,ru;q=0.2
リクエストにAccept-Language:ヘッダがあればその内容。クライアントブラウザに複数の言語が設定されている場合、適当に比重を示す値が合わせてセットされウェブサーバに送られるよう。
$_SERVER['REMOTE_PORT'] 56789 アクセス元側の通信ポート番号
$_SERVER['SERVER_PORT'] 80 ウェブサーバ側の通信ポート番号
$_SERVER['HTTP_REFERER'] http://example.com/ リンクをたどってページにやってきた場合、リンク元のURL情報があればその値を返す
$_SERVER['HTTPS'] on 使用プロトコルがHTTPSであった場合、空ではない値(on)が返される。

スクリプトファイル名だけを取り出すにはbasename関数を用いる。

スクリプトをコマンドラインから実行する場合に関わる定義済み変数($argv$argc)についてはコマンドラインからの実行 - 引数の指定と参照を参照のこと。

$_GET、$_POST

それぞれ、GETメソッド、POSTメソッドで送られたキーと値のセットが配列として格納される。

$_FILES

フォームで送信されたファイルに関する情報が格納される。詳細はファイルのアップロードに関する情報参照を参照のこと。

変数関係

変数の割り当て解除(unset)

unsetは変数の割り当てを解除する。

【書式】
unset(変数名,変数名...)

【例】
$ cat test.php
<?php
$array = array(1=>'Hydrogen',2=>'Helium',3=>'Lithium',4=>'Beryllium',5=>'Boron',6=>'Carbon');
var_dump($array);
unset($array[1]);
var_dump($array);
?>
$ php test.php
array(6) {
  [1]=>
  string(8) "Hydrogen"
  [2]=>
  string(6) "Helium"
  [3]=>
  string(7) "Lithium"
  [4]=>
  string(9) "Beryllium"
  [5]=>
  string(5) "Boron"
  [6]=>
  string(6) "Carbon"
}
array(5) {
  [2]=>
  string(6) "Helium"
  [3]=>
  string(7) "Lithium"
  [4]=>
  string(9) "Beryllium"
  [5]=>
  string(5) "Boron"
  [6]=>
  string(6) "Carbon"
}

変数の設定状況判定(isset)

issetは変数の設定状況を判定する。「セットされ、NULLではない」ならtrue、そうでないならfalseを返す。複数の変数を指定した場合、前から順に判定してfalseとなる変数があった時点でfalseを返し、最後まで全てtrueならtrueを返す。

【書式】
isset(変数名,変数名...)
      

変数が空であるかを調べる(empty)

emptyは変数が空であるかを調べる。変数が存在しないか、またはfalseと判定される値がセットされている場合に空とみなされる(変数が存在しなくてもエラーにはならない)。「 !isset($var) || $var == false」の判定をやっているのと同じ。

【書式】
empty(変数);

【戻り値】
空と判定(変数が存在しない場合も含む)→true
空ではない(変数が存在し、かつその値が空と判定されるような値ではない)→false

空と判定される値は以下のとおり。

  • ""(空文字列)
  • 0(整数の0)
  • 0.0(浮動小数点の0)
  • "0"(文字列の0)
  • NULL
  • FALSE
  • array()(空配列)
  • $var(宣言されてはいるが値が設定されていない変数)

参考文献・サイト:

配列変数

配列の定義

$配列変数名[キー値] の形でキー毎に個別に代入するか、またはarrayを使って一度に指定する。

【例1】arrayを使って複数の要素を一度に定義
$a = array('abc','def','123');
foreach ($a as $tmp) {
print "$tmp¥n";
}
【結果1】
abc
def
123

【例2】配列内の個別要素を定義するには、変数名[キー値]を用いる。値は非負整数または文字列。
$b[0] = "ghi";
$b[3] = "def";
$b[] = "xyz"; キー値を省略すると既存最大キー値(3)+1が自動的に採用される
print "$b[0]¥n";
print "$b[3]¥n";
print "$b[4]¥n¥n";
print_r $b;
【結果2】
ghi
def
xyz

Array
  (
  [0] => ghi
  [3] => def
  [4] => xyz
)

【例3】連想配列(キー値が数値ではない配列)の設定
$c = array('apple' => 'red', 'banana' => 'yellow', 'chocolate' => 'brown');
print_r $c;
Array
(
  [apple] => red
  [banana] => yellow
  [chocolate] => brown
  )
      

配列要素の追加と削除

関数 処理位置 追加/削除 戻り値 備考
array_unshift(配列,追加値,追加値...) 先頭 追加 処理後の要素数 配列の数字添字は0から振り直し、文字キーはそのまま。
array_shift(配列) 先頭 削除 配列が空ではない→取り出した値
配列が空または配列ではない→NULL
配列の数字添字は0から振り直し、文字キーはそのまま。
第1引数が空の配列または配列ではない場合、NULLを返す。
array_push(配列,追加値,追加値...) 末尾 追加 処理後の要素数 $配列変数名[]=を繰り返すのと同じ。
array_pop(配列) 末尾 削除 配列が空ではない→取り出した値
配列が空または配列ではない→NULL
第1引数が空の配列または配列ではない場合、NULLを返す。

特定の要素を削除するのはunset。配列添字ふり直しはarray_values(配列から全ての値を取り出し、数値添字をつけた配列を返す)。

【書式】
unset(変数名, 変数名...);
array_values(配列);
      
$a = array (2 => 'two',
            3 => 'three');
print_r($a);
Array
(
  [2] => two
  [3] => three
)

array_push(4 => 'four', 5 => 'five'); ←最後に要素追加
print_r($a);
Array
(
  [2] => two
  [3] => three
  [4] => four
  [5] => five
)

$a[] = 'six'; ※要素を1個だけ追加するなら、この方が軽い
print_r($a);
Array
(
  [2] => two
  [3] => three
  [4] => four
  [5] => five
  [6] => six
)

array_pop($a) ←最後に要素を1個削除
print_r($a);
Array
(
  [2] => two
  [3] => three
  [4] => four
  [5] => five
)

array_unshift($a,'zero','one') ←先頭に要素追加し、添字番号ふり直し(文字列キーの要素はそのまま)
print_r($a);
Array
(
  [0] => zero
  [1] => one
  [2] => two
  [3] => three
  [4] => four
  [5] => five
)

array_shift($a) ←先頭から1個要素削除し、添字番号ふり直し(文字列キーの要素はそのまま)
print_r($a);
Array
(
  [0] => one
  [1] => two
  [2] => three
  [3] => four
  [4] => five
)

unset($a[3]) ←指定の要素を削除(添字はそのまま)
print_r($a);
Array
(
  [0] => one
  [1] => two
  [2] => three
  [4] => five
)
※unsetは配列用の関数ではなく、変数一般を削除する関数

$a = array_values($a) ←添字番号割り振り直し
print_r($a);
Array
(
  [0] => one
  [1] => two
  [2] => three
  [3] => five
)
      

配列要素の取得

配列の内部ポインタを扱う関数群を以下に記す。

関数 ポインタ移動先 戻り値
reset(配列) 先頭
配列が空→false(論理値)
配列が空ではない→最初の要素の値
end(配列) 末尾
配列が空→false(論理値)
配列が空ではない→最後の要素の値
next(配列) ひとつ次
次の要素がない→false(論理値)
次の要素あり→次の要素の値
prev(配列) ひとつ前
前の要素がない→false(論理値)
前の要素あり→前の要素の値
current(配列) 移動せず
ポインタ箇所が最終要素の次、または配列が空→false(論理値)
それ以外→現在のポインタがある箇所の要素の値
key(配列) 移動せず
ポインタ箇所が最終要素の次、または配列が空→false(論理値)
それ以外→現在のポインタがある箇所の要素のキー

値だけではなく、キーと値のセットを取り出すのに使える、eachという関数(配列から現在のポインタ位置のキー・値ペアを返して、ポインタを進める)があったがこの関数はPHP7.2.0で非推奨となりPHP8.0.0で削除されたので利用は非推奨。

【書式】
each(配列);

【戻り値】
ポインタ位置が配列の最後より後→false
not→以下の配列
Array {
(
 [0]=>キー
 [1]=>値
 [key]=>キー
 [value]=>値
)
}

配列内の要素数を数える

配列内の要素数を数えるにはcount関数を用いる。

【書式】
count(配列,カウントモード)

【戻り値】
数えられるオブジェクト→要素数(整数)
数えられないオブジェクト→1(整数)
NULL→0(整数)
未セット→0(整数)※isset関数を併用すると、NULLなのか未セットなのかは区別可能

カウントモードに0またはCOUNT_NORMALを指定した場合は最上階層要素だけ数える。1またはCOUNT_RECURSIVEを指定した場合は、全階層の要素数を数える。

【例】
<?php
$a = array('a','b','c');
$b = array(array('a','b','c'), array('1','2','3'));
echo '$a: ' . count($a); . "¥n";
echo '$b: ' . count($a); . "¥n";
echo '$b(all): ' . count($a,COUNT_RECURSIVE); . "¥n";
?>

【出力】
$a: 3
$b: 2
$b(all): 8

なお、第1引数にテキストファイル名を指定した場合、テキストファイルの行数を返す。

【書式】
count(テキストファイル名)

配列中で値があるか調べる

in_arrayは配列要素中に指定した値があるかどうか調べる。あればtrue、それ以外はfalseを返す。

【書式】
in_array(探索値,配列,strict)
【戻り値】真偽値(bool)
探索値が配列要素中にあった:true
探索値が配列要素中になかった:false
探索値
データ型:混合型(object|resource|array|string|int|float|bool|null、PHP 8.0.0以降で利用可能)
探す値。文字列の場合、大文字小文字は区別して比較される。
配列
データ型:配列(array)
探索先となる配列
strict
データ型:真偽値(bool)
既定値:false
trueを指定すると型も一致しているかを確認する。

array_key_existsは配列中に指定したキーがあるかどうか調べる。あればtrue、なければfalseを返す。

【書式】
array_key_exists(探索値,配列)
【戻り値】真偽値(bool)
キーが見つかった:true
キーが見つからない:false
探索値
データ型:文字列型(string)または整数型(int)
探すキー値。配列添字として使えるすべての値を指定可能。
配列
データ型:配列(array)
探索先となる配列

issetはnull値を持つ配列キーは返さないが、このarray_key_existsはtrueを返す。

array_key_existsは最初のレベルのキーだけを探索する。多次元配列の第2階層以降にあるキーは探索対象外。

array_searchin_arrayと似ているが、戻り値が「最初に見つかった値のキー」である点が異なる。見つからない場合 false を返すのは同じ。

【書式】
array_search(探索値,配列,strict)
【戻り値】整数(int)、文字列(string)またはfalse
値が見つかった:要素のキー
値が見つからない:false

全てのマッチした値に対するキーを得るには、array_keys 関数で 検索値オプションを指定する。

配列のキーを得る

array_keysを用いる(配列キーを配列で得られる)。

【書式】
array_keys(配列,検索値,型判定);
      
検索値
検索値を値に持つ要素のキーのみが返される。指定がない場合の既定動作は全ての検索値が対象(配列の全要素のキーが返される)。
型判定
trueを指定すると型も含めて一致しているかどうかの判定(===)が行われる。falseを指定すると型判定までは行わない通常の比較(==)が行われる。指定がない場合の既定値は false。
【例】
$airports = array('KIX'=>'関西国際空港',
                  'ITM'=>'伊丹空港',
                  'UKB'=>'神戸空港',
                  'SHM'=>'南紀白浜空港',
                  'TKG'=>'コウノトリ但馬空港');
$cords = array_keys($airports);
print_r($cords);

<出力結果>
Array
(
  [0] => KIX
  [1] => ITM
  [2] => UKB
  [3] => SHM
  [4] => TKG
)
      

配列のキーをランダムに取り出す(array_rand)

array_randは配列から一つ以上の要素をランダムに取り出し、取り出した要素キーを返す。取り出す要素の数が1つである場合はそのキー値、複数ある場合は各キー値を要素とする配列を返す。配列の中にある要素数より多くの要素を取り出そうとすると E_WARNING レベルのエラーが発生し、NULL を返す。

【書式】
array_rand(配列,取り出す要素数);

【戻り値】
取り出す要素が1つ→文字列:そのキー値
取り出す要素が複数→配列:各キー値を要素とする配列
配列の中にある要素数より多くの要素を取り出そうとした時→NULL
配列
配列:入力の配列
取り出す要素数
整数:取り出す要素の数。指定がない場合の既定値は1。
【例】
$ cat test.php
<?php
$array = array(1=>'Hydrogen',2=>'Helium',3=>'Lithium',4=>'Beryllium',5=>'Boron',6=>'Carbon');
echo '1つ取り出し:';
var_dump($array[array_rand($array)]);
echo '2つ取り出し:';
foreach (array_rand($array,2) as $key) {
  var_dump($array[$key]);
}
?>
$ php test.php
1つ取り出し:string(9) "Beryllium"
2つ取り出し:string(8) "Hydrogen"
string(6) "Carbon"

キーと値を入れ替える(array_flip)

array_flipはキーを値を入れ替えた配列を返す。キーが整数型(integer)または文字列型(string)である必要があり、そうでないキーを持つキーと値の組については入れ替えずそのままになる? またある値が複数出現した場合、最後に出現した値がキーとして採用され、その他の値は失われる。戻り値はキーと値の反転に成功した場合はその配列、失敗した場合はNULL。

array_flip(配列);
      

配列要素の並べ替え

参考:PHP: 配列のソート - Manual

関数名 並べ替えの基準 キーと値の関係 並べ替え順
sort(配列,ソート型フラグ) 維持しない 昇順
rsort(配列,ソート型フラグ) 降順
usort(配列,比較関数) ユーザ定義
asort(配列,ソート型フラグ) 維持する 昇順
arsort(配列,ソート型フラグ) 降順
uasort(配列,比較関数) ユーザ定義
ksort(配列,ソート型フラグ) キー 維持する 昇順
krsort(配列,ソート型フラグ) 降順
uksort(配列,比較関数) ユーザ定義
shuffle(配列) 維持しない ランダム

戻り値はいずれも並べ替えに成功した場合はtrue、失敗した場合はfalse。

ソート型フラグ
SORT_REGULAR
標準の比較…ってどんな比較?
SORT_NUMERIC
数値として比較…ってどんな比較?
SORT_STRING
文字列として比較…ってどんな比較?
比較関数
引数を2つとり、ある数値を返す関数。usort, uasort, uksort関数の第2引数に指定し、配列の各要素の比較判定に用いられる。関数の返すべき値は下記参照。
function comp($a,$b)
{
  if ($aが前と判定される条件) {
    return -1;
  } else if ($bが前と判定される条件) {
    return 1;
  } else { # $a,$b 同点の場合
    return 0;
  }
}

なお、これらの並べ替え関数はマルチバイト文字には有効ではない(文字単位ではなくバイト単位で判断されるよう)。 対応策として、uniord(引数文字に対応する文字コードを返す関数ordのマルチバイト対応版)をユーザ定義関数として定義しておき、比較関数として以下のような関数を定義する(以下の例において長音記号は無視して判定している)。

function mbcmp($a,$b)
{
  #= エンコーディング設定
  $encode = 'UTF-8';
  #== 短い方の文字の長さを取得し、短い方が前と仮判定
  #- $a の方が短い場合
  if (strlen($a) < strlen($b)) {
    $len = strlen($a);
    $cmp = -1;
  #- $a の方が長い場合
  } else if (strlen($a) > strlen($b)) {
    $len = strlen($b);
    $cmp = 1;
  #- 同じ長さ→$aが前とする
  } else {
    $len = strlen($a);
    $cmp = 0;
  }

  #== 変数定義
  $i = 0; #- チェック位置(最初の文字が0)
  $dash = array('a'=>0, 'b'=>0); #- 長音記号数
  $flg = true; #- チェック継続フラグ(falseになると判定終了)
  #== チェック
  while ($flg !== false) {
    #- 前の長音記号チェック(長音記号なら$dash['a']に1加算)
    if (mb_substr($a,$i+$dash['a'],1,$encode) == "ー") {
      $dash['a']++;
    }
    #- 後の長音記号チェック(長音記号なら$dash['b']に1加算)
    if (mb_substr($b,$i+$dash['b'],1,$encode) == "ー") {
      $dash['b']++;
    }
    #- i-1文字目(長音記号はカウントせず)が同じ
    if (mb_substr($a,$i+$dash['a'],1,$encode) == mb_substr($b,$i+$dash['b'],1,$encode)) {
      #- チェック位置を次に
      $i++;
      #- 短い方の最後まで到達(短い方=長い方の前部)→短い方が前
      if ((($cmp <= 0) and ($i+$dash['a'] >= $len)) or (($cmp > 0) and ($i+$dash['b'] >= $len))) {
	$flg = false;
      }
    #- i-1文字目が違う
    } else {
      #- $a の($i-1)文字目の文字コード
      $code_a = uniord(mb_substr($a,$i+$dash['a'],1,$encode));
      #- $b の($i-1)文字目の文字コード
      $code_b = uniord(mb_substr($b,$i+$dash['b'],1,$encode));
      #- $a の文字コードの方が小さい場合→$aが前
      if ($code_a < $code_b) {
	$cmp = -1;
      #- $b の文字コードの方が小さい場合→$bが前
      } else if ($code_a > $code_b) {
	$cmp = 1;
      }
      $flg = false;
    }
  }
  return $cmp;
}
      

キーの割り振り直し(array_values)

array_valuesは配列から全ての値を取り出し、数値をキーとする配列を返す。

【書式】
array_values(配列);
      
【例】
<?php
$a = array (1 => 'one',
            '二' => 'two',
            3 => 'three',
            'четыре' => 'four');
$b = array_values(配列);
print_r($a);
print_r($b);
?>

「実行結果」
Array
(
    [1] => one
    [二] => two
    [3] => three
    [четыре] => four
)
Array
(
    [0] => one
    [1] => two
    [2] => three
    [3] => four
)
      

配列の重複要素を削除

array_uniqueは、配列の各要素の値をチェックし、重複した値を取り除いた配列を返す。同じキーを持つ配列要素が存在した場合、先に登場した方が残され、後に登場する方が捨てられる。型の扱いは既定では全て文字列に変換して比較される(後述のソートフラグオプション参照)。

【書式】
array_unique(配列,ソートフラグ);
【戻り値】
(配列)処理済の配列
      
ソートフラグ
指定できる値と内容は以下の通り。キャスト指定の括弧内にタブ、スペースなどを含んでもよい(無視される)。
比較式 内容
SORT_REGULAR $変数1 === $変数2 そのままのデータ型で型も含めて比較。但し文字と数値が表記上同じなら型が違っても同じとみなされるよう。
SORT_NUMERIC (float) $変数1 === (float) $変数2 数値として比較
SORT_STRING (string) $変数1 === (string) $変数2 文字列として比較(これが既定値)
SORT_LOCALE_STRING (string) $変数1 === (string) $変数2 現在のロケール(地域設定)に基づき文字列として比較
【例】
<?php
$input = array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($input);
print_r($result);
?>
↓結果
Array
(
    [a] => green
    [0] => red
    [b] => green # キー"a"に同じ値があるので除去対象
    [1] => blue
    [2] => red # キー"0"に同じ値があるので除去対象
)
Array
(
    [a] => green
    [0] => red
    [1] => blue
)

【例】
<?php
$input = array(4, "4", "3", 4, 3, "3","3.0");
var_dump($input);
var_dump(array_unique($result,SORT_STRING));
var_dump(array_unique($result,SORT_REGULAR));
var_dump(array_unique($result,SORT_NUMERIC));
?>
↓結果
array(6) {
  [0]=>
  int(4)
  [1]=>
  string(1) "4" # 型は違うが文字として比較すると[0]に一致→除外対象
  [2]=>
  string(1) "3"
  [3]=>
  int(4) # [0]に一致→除去対象
  [4]=>
  int(3) # 型は違うが文字として比較すると[2]に一致→除去対象
  [5]=>
  string(1) "3" # [2]に一致→除去対象
  [6]=>
  string(3) "3.0" # 数値としては[2]に一致、文字としては不一致→REGULAR,NUMERICは除去対象
}
# 元の型は保持されている
array(2) {
  [0]=>
  int(4)
  [2]=>
  string(1) "3"
}
      

複数階層の配列の場合、

<?php
$a = array('A'=>array('0036','0037','0036','0038'),
	   'B'=>array('0012','0013','0012','0014'));
print_r($a);
print_r(array_unique($a,SORT_STRING));
echo $a['A']."\n";
echo $a['B']."\n";
print_r(array_unique($a,SORT_REGULAR));
#- 下位階層の各値の重複を取り除くには各下位階層にarray_uniqueを適用
foreach ($a as $key=>$subarray) {
  $a[$key] = array_unique($subarray);
}
?>

#- 元の配列
Array
(
    [A] => Array
        (
            [0] => 0036
            [1] => 0037
            [2] => 0036
            [3] => 0038
        )

    [B] => Array
        (
            [0] => 0012
            [1] => 0013
            [2] => 0012
            [3] => 0014
        )
)
#- 文字列として比較して処理した結果(既定の動作もこれ)
Array
(
    [A] => Array
        (
            [0] => 0036
            [1] => 0037
            [2] => 0036
            [3] => 0038
        )
)
# どちらも"Array"という文字列として判断され一致するので、後者は除去される
a['A']: Array
a['B']: Array
# 型そのままだとそれぞれの配列内容は異なるので除去対象なし
Array
(
    [A] => Array
        (
            [0] => 0036
            [1] => 0037
            [2] => 0036
            [3] => 0038
        )

    [B] => Array
        (
            [0] => 0012
            [1] => 0013
            [2] => 0012
            [3] => 0014
        )
)
# 各下位階層内で重複除去するにはループ処理により可能
Array
(
    [A] => Array
        (
            [0] => 0036
            [1] => 0037
            [3] => 0038
        )

    [B] => Array
        (
            [0] => 0012
            [1] => 0013
            [3] => 0014
        )
)
      

配列を1つにマージ

コマンド類 文字列キー要素 数値キー要素
array_merge 同一のキーを持つ要素があった場合、後の配列の値で上書き。 キー値を0から割り振り直して、前の配列の要素、後の配列要素の順で全て追加。
加算演算子(+) 同一のキーを持つ要素があった場合、前の配列の値をそのまま残す。 前の配列にないキー値の要素のみ追加。前の配列にあるキー値の要素は前の配列の要素のまま。

array_mergeは指定した1つ以上の配列に含まれる全要素を1つの配列に格納して返す。 文字列をキーにもつ要素(連想配列要素)で同じキーを持つ要素が存在した場合、後に登場した値で上書きされる。数字をキーに持つ要素の場合、登場順に0からの通しの連番が振り直される。

【書式】
array_merge(配列,配列...);
配列 + 配列 + 配列...;

【例】
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result_merge = array_merge($array1, $array2);
$result_add = $array1 + $array2;
echo '$array1:';
print_r($array1);
echo '$array2:';
print_r($array2);
echo '$result_merge:';
print_r($result_merge);
echo '$result_add:';
print_r($result_add);
【結果】
$array1:Array
(
    [color] => red
    [0] => 2
    [1] => 4
)
$array2:Array
(
    [0] => a
    [1] => b
    [color] => green
    [shape] => trapezoid
    [2] => 4
)
$result_merge:Array
(
    [color] => green ←後の配列($array2)がセットされている
    [0] => 2
    [1] => 4
    [2] => a
    [3] => b
    [shape] => trapezoid
    [4] => 4
)
$result_add:Array
(
    [color] => red ←前の配列($array1)がセットされている
    [0] => 2
    [1] => 4
    [shape] => trapezoid
    [2] => 4 ←後の配列($array2)にしかないキー要素のみ追加
)

      

キー値が同一であっても両方とりこみたいなら、foreachを使って別の配列に各要素を格納していけばよい(但し、キーと値の関係は崩れる)。

【例】
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
foreach ($array1 as $val) {
  $result[] = $val; ←キーを指定しない場合、最大数字キーの次の番号が自動で設定される
}
foreach ($array2 as $val) {
  $result[] = $val;
}
print_r($result);
【結果】
Array
(
    [0] => red
    [1] => 2
    [2] => 4
    [3] => a
    [4] => b
    [5] => green
    [6] => trapezoid
    [7] => 4
)
      

複数配列に共通する要素を得る

array_intersectは複数配列に共通する要素を返す。戻り値となる配列のキーは比較元配列のキーが維持される。

array_intersect(比較元配列,比較対象配列,比較対象配列)
      

変数が配列であるか調べる(is_array)

is_arrayは変数が配列であるかどうかを調べる。配列型の場合はtrue、それ以外はfalseを返す。

is_array(変数)
      

制御構造

条件分岐(if)

ifは処理の条件分岐を記述する。elseelse ifを併用することにより複数の条件分岐を記述することができる。また入れ子構造にすることも可能。

条件分岐(switch)

switchは単一の変数の値によって処理を分岐させるのに用いることができる。なお、swtichcaseで行われる比較は緩やかな比較(データ型が一致しているかどうかまでは見ない)となる。

caseで指定する条件にマッチした場合、breakに出会うまでの内容が処理される。defaultはどのcaseにもマッチしなかった場合に適用される。

switch(変数名) {
  case 値1;
    式1;
    break;
  case 値2;
    式2;
    break;
  …
  case 値n;
    式n;
    break;
  default;
    式(n+1);
    break;
}

評価の対象となる変数を変数名で指定し、その後case節で条件を記述する。if...else if...文と異なるのは、breakを記さないと、switch文の最後まで処理されてしまう点。逆にそれを利用して複数の条件を束ねることができる(式1とその後のbreakを記さないと、値1または値2の場合に式2が処理される。

switch($obj) {
  case "Nara";
  case "Osaka";
  case "Kyoto";
  case "Hyogo";
  case "Shiga";
  case "Wakayama";
    echo "It's in the Kinki region.";
    break;
  case "Kagawa";
  case "Tokushima";
  case "Ehime";
  case "Kochi";
    echo "It's in the Shikoku region.";
    break;
  default;
    echo "It's neither in the Kinki region nor in the Shikoku region.";
    break;
}
      

標準入力待ち

fgets(Enter入力または指定文字数まで)、fgetc(1文字)を用いる。いずれもファイルリソースには"STDIN"を指定する。

【例1】
echo "IDを入力して下さい(8文字以内)";
fgets(STDIN,8);

【例2】
echo "これでよろしいですか(y/n)?";
fgetc(STDIN);
      

参考文献・サイト:

スクリプト終了

exitはメッセージを出力して、現在のスクリプト処理を終了する。dieも働きは同じ。戻り値はなし。

【書式】メッセージを出力して終了する
exit(文字列);

【例】
exit("エラーが発生しました!");
      

引数に整数を指定した場合は、エラーコードを設定して終了する。指定できる値は0〜254の整数。0はプログラムを正常終了させるのに用いる。値の指定がない場合の既定値は0。

【書式】エラーコードを設定して終了する
exit(整数)

【例】正常終了
exit;
exit();
exit(0);
      

MySQL関数

MySQLデータベースを操作するための関数。PHP3以降で利用可能。MySQL 4.1.3以前のMySQLを扱うことを意図した手続き型インタフェースを提供する。この拡張モジュールは PHP 5.5.0 で非推奨になり、PHP 7.0.0で削除された1-2-2-1。PHP5以降ではMySQL改良版拡張モジュール「MySQLi」またはPHP Data ObjectのMySQL関数(PDO_MySQL)を使うことが推奨される。また、使用するMySQLのバージョンが4.1.3以降である場合もMySQLiの使用を強く推奨する。MySQL APIに関する概要も参照のこと。

メール

概要

mailコマンドによってメールを送信することができる。なお、メールに関するマルチバイト関数をオーバーロードする設定を行っていると、mb_send_mail関数に読み替えて実行される。

【書式】
mail(宛先,件名,本文,追加ヘッダ,追加オプション)
mb_send_mail(宛先,件名,本文,追加ヘッダ,追加オプション)

【戻り値】
メール送信に成功→true
メール送信に失敗→false
      
宛先
RFC 2822を満たす書式で書かれたメールの送信先。電子メールアドレスをそのまま記すか、あるいは不等号(< ... >)で囲んでその前に別名を記す。複数のアドレスを併記する場合はコンマ(,)で区切る。
user@example.com
user@example.com, anotheruser@example.com
User <user@example.com>
User <user@example.com>, Another User <anotheruser@example.com>
なお、名前部分に日本語を使っている場合、mb_encode_mimeheaderを使ってmimeエンコード処理を行わないと受信されたメールの宛先名前部分が文字化けしてしまう。追加ヘッダ中のFrom, Cc, Bccについても同様。
【例】宛先をmimeエンコードする
<?php
$to  = mb_encode_mimeheader('くいだおれ太郎');
$to .= sprintf(' <%s>',taro@kuidaore.com);
...
mail($to,$subject,$body,$addheader);
?>
件名
RFC 2047を満たすメールの件名。
本文
メール本文。改行コードはLF(\n)で各行の長さは70文字以下にすること(参照:wordwrapコマンド)。 Windows環境の場合、ピリオドから始まる行は無視されるが、これを防ぐには、行頭のピリオドをピリオド 2 つに置換すればよい(例:$body = str_replace("\n.","\n..",$body);)。
追加ヘッダ

送信元(From)、カーボンコピー(Cc)、ブラインドカーボンコピー(Bcc)の挿入に用いる。複数のヘッダを追加する際はCRLF(\r\n)で区切る。Fromは必須だが、php.iniで既定値を指定していれば省略可能。

またここに記す文字列はmb_encode_mimeheaderを使って文字エンコーディング変換を行い、適正な言語設定を行わないと文字化けすることがある(mb_languagemb_internal_encoding参照)1116

追加オプション
sendmailなどのメール配信エージェント(MTA)にコマンドラインオプションを渡す際に用いる。
【例】
<?php
$from = "white@yagisan.net"; ←送信者アドレス
$fromname = "しろやぎ"; ←送信者名
$to = "black@yagisan.net"; ←宛先アドレス
$toname = "くろやぎ"; ←宛先人名
$subject = "こんにちわ"; ←件名
$body = <<< DOC_END
こんにちは、お元気ですか。
またメールします。
DOC_END;

$addheader  = "From: " . mb_encode_mimeheader($fromname);
$addheader .= "<" . $from . ">\r\n";

mb_language("ja");
mb_internal_encoding("UTF-8");
mb_send_mail($to,$subject,$body,$addheader);
?>
      

なお、Unicodeメールを送るには以下の2行を追加ヘッダに記述する必要あり12

Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 8bit

あるいはこう?22

Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: BASE64

それと、メールエンベロープにもfromアドレスを設定した方がいいみたい(迷惑メールとみなされるのを抑制するため)。そのためにはmail(mb_send_mail)の第5引数に「-f [fromアドレス]」を指定しておく22

メールアドレスの仕様

メールアドレス全体でASCII文字256文字以下。

ローカル部(@の前)

以下のASCII文字が使用可能。文字数は最大64文字(プロバイダやメールソフトの制約のため実際使えるのはこれより少ない場合がある)。

  • 英字(本来は大文字小文字は区別されるが、実際は区別されない実装が大半)
  • 数字
  • ! # $ % & ' * + - / = ? ^ _ ` { | } ~(実際はこのうちの一部のみを許可するの制限を加えた実装が多い)
  • .(ピリオド、先頭と末尾以外で使用可能。2個以上連続してはいけない。)

" "で囲んだquoted-stringの形式であれば以下のASCII文字も使用可能

  • # ( ) < > [ ] : ; @ ,
  • .(ピリオド、quoted-string内での制限はなし)
  • 空白(スペース)
ドメイン部(@の後)

次のいずれかが使用可能。文字数は最大255文字。

  • サブドメイン(ASCII文字のうち、英数字とハイフン(-)、但し先頭は英数字)をピリオド(.)でつないだもの(完全修飾ドメイン名、FQDN)
  • "[ ]"でくくったIPアドレス

  • mail.hoge-fuga.com
  • [192.168.0.100]

メールアドレスチェック例

<?php
$addresses = "user1@mail.hoge-fuga.com, user2@mail.foofoo.net";
#- エラーコードとメッセージの定義
$errmsg = array(0 => 'メールアドレスに使えない文字が含まれています(使用できるのは半角英数字記号です)。',
                1 => 'メールアドレスの文字数が多すぎます。256文字以下にして下さい。',
                2 => '@がないか、または2個以上あります。@は1つのメールアドレスにつき1個にして下さい。',
                3 => '@の前(ローカル部)の文字が多すぎます。@の前は64文字以下にして下さい。',
                4 => '@の前(ローカル部)に使用できない文字が含まれています。使用できる文字は半角英数字と!#$%&'*+-/=?^_`{|}~.のいずれかです。',
                5 => '@の前(ローカル部)の先頭末尾にピリオドは使用できません。',
                6 => '@の前(ローカル部)に連続したピリオドは使用できません。',
                7 => '@の後(ドメイン部)の文字が多すぎます。@の後は255文字以下にして下さい。',
                8 => '@の後(ドメイン部)に使用できない文字が含まれています。使用できる文字は半角英数字とハイフン、ピリオド(-.)のいずれかです。',
                9 => '@の後(ドメイン部)の先頭に使用できる文字は半角英数字のみです(先頭にはハイフンやピリオドは使えません。)');
#- チェックフラグ初期値
$check = true;
#- 空白類(タブ、リターン、改行、NUL、垂直タブも含む)を除去
$addresses = preg_replace_all('/[ \t\n\r\0\x0B]/','',$address);
#- ASCII英数字記号以外があればチェックfalse
if (preg_match('/[^\x21-\x7e]/',$addresses) != false) {
  $check = false;
  $errcode = 0;
} else {
  #- メールアドレスをコンマで分割して配列に格納
  $address_array = implode(",",$addresses);
  #- 各メールアドレスをチェック
  foreach ($address_array as $address) {
    #- 文字数が256文字を越えていたらチェックfalse
    if (strlen($address) > 256) {
     $check = false;
     $errcode = 1;
    #- @が1個でなかったらチェックfalse
    } else if (preg_match_all('/@/',$address) !== 1) {
     $check = false;
     $errcode = 2;
    } else {
      $local = substr($address,0,strpos($address,'@'));
      #- ローカル部が64文字を越えていたらチェックfalse
      if (strlen($local) > 64) {
        $check = false;
        $errcode = 3;
      #- ローカル部に許容される文字以外があればチェックfalse
      } else if (preg_match("/[^0-9A-Za-z!#$%&'*+\-/=?^_`{|}~.]/",$local) != false) {
        $check = false;
        $errcode = 4;
      #- ローカル部先頭末尾にピリオドがあればチェックfalse
      } else if (preg_match('/(^\.|\.$)/',$local) != false) {
        $check = false;
        $errcode = 5;
      #- ローカル部に連続するピリオドがあればチェックfalse
      } else if (preg_match('/\.\./',$local) != false) {
        $check = false;
        $errcode = 6;
      }
      $domain = substr($address,(strpos($address,'@')+1));
      #- ドメイン部が255文字を越えていたらチェックfalse
      if (strlen($local) > 255) {
        $check = false;
        $errcode = 7;
      #- ドメイン部に許容される文字以外があればチェックfalse
      } else if (preg_match('/^[^0-9A-Za-z\-.]/',$local) != false) {
        $check = false;
        $errcode = 8;
      #- ドメイン部の先頭が英数字でなればチェックfalse
      } else if (preg_match('/^[0-9A-Za-z]/',$local) == false) {
        $check = false;
        $errcode = 9;
      }
    }
  }
  if ($check === false) {
    echo "Error was found!\n" . $errmsg[$errcode] . "\n";
  } else {
    echo "Address checking OK!\n";
  }
}
?>
      

メールアドレス確認の仕組みを加えたメールシステム

メールフォームでsubmit→送られてきたメールに記載されたURLをクリック→送信実行、というメールアドレスが有効なものであるかを確認してから送信するメールシステムの作り方について。参考サイト2で紹介されている会員登録システムとは異なり、1回限り有効であればよいものを作る。

1. 確認コードを保存するMySQLテーブルを作る
カラム名 データ型 内容
confirm_code varchar(64) 確認コード
received_date date 送信リクエスト受信日時
from_name varchar(192) 送信者名(64文字以内)
from_address varchar(256) 送信者メールアドレス(256文字以内)
subject varchar(192) 件名(64文字以内)
body text 本文
mysql> CREATE TABLE mail_queue (confirm_code VARCHAR(32),received_date DATE,from_name VARCHAR(192),from_address VARCHAR(256),subject VARCHAR(192),body TEXT);
	  
2. メールフォームからsubmitされると確認メールを送信
3. 確認メールのURLにアクセスすると本来の内容が送信される

ファイルシステム関係

ファイルを開く

fopenは指定したファイルを開いてアクセス可能な状態にする。戻り値はファイルアクセスの際に指定するファイルポインタ(ファイルポインタリソース、オープンに失敗した場合は false)。gzopenの場合はgzip圧縮ファイルでも扱える(圧縮解凍操作を意識しなくてもアクセスできる)。

【書式】
fopen(ファイル名,アクセスモード)

gzopen(ファイル名,アクセスモード)
【戻り値】
正常にオープン→ファイルポインタリソース
not→false

引数

ファイル名(データ型:文字列)

"スキーム://..." の形式である場合はURLとみなし、そのプロトコルのハンドラ(ラッパー)を探す。そのプロトコルに対するラッパーが登録されていなければスクリプトに潜在的な問題があることを示す NOTICE を発行したうえで、ファイル名を通常のローカルファイルとみなして開くことを試みる。

ファイルがローカルファイルを示していると判断されると、そのファイルへのストリームを開く。

ファイル名が登録されているプロトコルを示していると判断され、かつそのプロトコルがネットワーク URL として登録されていれば、 PHP は allow_url_fopen が有効となっているかどうかチェックする。 もしこれがオフになっていると、PHP は warning を発行し fopen は失敗する。

アクセスモード(データ型:文字列)

指定可能な値は以下の通り。

モード 読み 書き ファイルポインタ ファイル既存 ファイル未存 備考
'r' × 先頭 エラー
'r+' 先頭 エラー
'w' × 先頭 消去 新規作成
'w+' 先頭 消去 新規作成
'a' × 末尾 追記 新規作成
'a+' 末尾 追記 新規作成
'x' × 先頭 エラー
'x+' 先頭 エラー

戻り値

ファイルオープン成功→ファイルポインタリソース(リソース (resource) 型)fgets/gzgetsによるファイル内容の取得などで用いる。

ファイルオープン失敗→false(論理 (boolean) 型)

↑上位メニュー(ファイルシステム関係)に戻る

ファイル閉じる

fcloseはファイルを閉じる。fopenでファイルを開いた時に戻り値として得られるファイルポインタを引数に指定。gzopenで開いた場合はgzcloseで閉じる。

【書式】
fclose(ファイルポインタ)
gzclose(ファイルポインタ)

標準出力から読み込むにはファイルポインタとしてSTDINを指定する。これはファイルオープン・クローズのの手続きを踏む必要はない(fopen、fcloseの手続きを踏まなくてもfgetsで1行取得可能)[2]

↑上位メニュー(ファイルシステム関係)に戻る

ファイル終端検出(feof)

feofはファイルポインタがファイルの終端に達しているかを返す。終端、エラーの場合true、その他の場合はfalseを返す。gzeofgzopenで開いたファイルを扱う以外は同じ。

【書式】
feof(ファイルポインタ)
gzeof(gzファイルポインタ)
【戻り値】
ファイルポインタがEOFではない位置を指す→false
ファイルポインタが EOF に達している→true
エラー発生(ソケットタイムアウトを含む)→true
      

ファイルポインタにはfopenなどで開いたファイルのポインタを指定する。無効なファイルポインタ(無効なファイルを開こうとすると、fopenはfalseを返す)を渡すと、いつまでもEOFに達せず(feofの戻り値がtrueにならず)無限ループに陥ることがあるので注意。 ファイルポインタがfalseでない場合のみファイル読み込みを行うようなエラー回避の条件分岐を設ける方が安全。

↑上位メニュー(ファイルシステム関係)に戻る

ディレクトリの開閉

opendirはディレクトリを開く。戻り値は処理に成功するとファイル名取得アクセスの際指定するディレクトリハンドル、失敗するとfalse。

closedirはディレクトリを閉じる。引数にはopendirで開いた時の戻り値として得られるディレクトリハンドル。

【書式】
opendir(パス)
closedir(ディレクトリハンドル)
      

ディレクトリ内のファイル等の情報を得る

readdirは、opendirで開いたディレクトリ内のアイテム(ファイルやディレクトリなど)の情報を1つ読む。成功すればファイル名を、失敗すればfalseを返す。戻り値にはfalseとして評価される0や""が来る可能性があるため、失敗(=これ以上読むべきものがないなど)を検知するには型まで識別する"==="演算子や"!=="演算子を用いること。

【書式】
readdir(ディレクトリハンドル)

【例】ユーザホームディレクトリの一覧を標準出力へ出力
if ($dir_handle = opendir("~")) { # 代入した結果を条件にしている(代入なので等号は一つ)
  while (($file = readdir($dir_handle)) !== false) {
    echo $file . "\n";
  }
}

【例】ユーザホームディレクトリの一覧を標準出力へ出力(. と .. を除く)
if ($dir_handle = opendir("~")) {
  while (($file = readdir($dir_handle)) !== false) {
    if (($file != ".") and ($file != "..")) {
      echo $file . "\n";
    }
  }
}
      

ファイル存在判定(file_exists)

file_existsはファイルまたはディレクトリが存在するかを調べる。ファイルが存在すればtrue、存在しなければfalseを返す。

【書式】
file_exists(ファイル名)
      
ファイル名
ファイルあるいはディレクトリへのパス。

ファイル属性判定(is_file、is_dir、id_link)

ファイル等の属性を判定する関数を以下に示す。

【書式】
is_file(文字列)
is_dir(文字列)
is_link(文字列)
【戻り値】文字列に指定したファイル等が
is_file:通常ファイル→true、それ以外→false
is_dir:ディレクトリ→true、それ以外→false
is_link:シンボリックリンク→true、それ以外→false

ディレクトリ作成(mkdir)

mkdirはディレクトリを作成する。ディレクトリ作成に成功すれば true、失敗すれば false を返す。ディレクトリを削除するのはrmdir

【書式】
mkdir(パス名,モード,recursive,コンテキスト);

【戻り値】データ型:論理値(boolean)
処理に成功→true
処理に失敗→false
パス名
ディレクトリのパス
モード
アクセス権のモードを8進数で指定する。先頭に0を付けて8進数であることを明示する必要がある。既定値は0777(全てのユーザが読み書き実行可能)。Windowsではこの設定は無視される。
recursive
パス名で指定したディレクトリの上位ディレクトリが存在しない場合に合わせて作成するかどうかを指定する。trueを指定すれば上位ディレクトリも合わせて作成し、falseを指定すれば作成しない。既定値はfalse。

ファイルサイズ取得(filesize)

filesizeは指定ファイルのファイルサイズ(単位はバイト)を返す。エラーの場合は false を返すか、または E_WARNING レベルのエラーを発生させる。

【書式】
filesize(ファイル名)

引数

ファイル名
[文字列] ファイルへのパス

戻り値

正常時:バイト単位でのファイルサイズ
エラー時:false またはE_WARNING レベルのエラー
注意:PHP の数値型は符号付整数であり、多くのプラットフォームでは 32 ビットの整数を取るため、ファイルシステム関数の中には 2GB より大きなファイルについては期待とは違う値を返すものがある。
【例】
$ php -r 'echo filesize("test.txt")."\n";'
1234

ファイルのMIME Content-typeを取得(mime_content_type)

mime_content_typeはファイルの MIME Content-type を返す。取得に失敗した場合は false を返し、E_WARNING レベルのエラーを発生させる。

【書式】
mime_content_type(ファイル名)

引数

ファイル名
[文字列/リソース] 調べる対象とするファイルへのパス、または対象のリソース

戻り値

正常時:[文字列]mime形式のContent type(例:text/plain)
エラー時:false(E_WARNING レベルのエラー)
【例】
$ php -r 'echo file_mime_type("test.txt")."\n";'
test/plain

1行取得(fgets, gzgets, fgetcsv)

fgetsfopenで開いたファイルのポインタ位置から1行分を取得して返す。戻り値には末尾の改行文字も含む。gzgetsgzopenで開いたファイルを扱うこと以外は同等。

【書式】
fgets(ファイルポインタ,読み込み長);
gzgets(ファイルポインタ,読み込み長);
【戻り値】
ファイルポインタがファイルの末端ではない→ファイルポインタで指定したファイルポインタから最大読み込み長-1 バイトを読み出して得られた文字列(gzgetsの場合は解凍後の文字列)
ファイルポインタがファイルの末端→false
エラー→false

ファイルポインタにはfopenfsockopenで正常にオープンされ、まだcloseされていないファイルポインタを指定する(gzgetsの場合はgzopen)。読み込み長を指定した場合、指定値-1バイトを読み出すか、または改行、ファイルの終端(EOF)を検出した時点で読み込みを終了する。指定がない場合は改行またはファイルの終端を検出するまで読み続ける。戻り値は正常に内容を取得できればその読み込んだ文字列、エラーがあればfalse。

【例1】単にファイルを読んで1行ずつ出力
<?php
$handle = fopen('hoge.txt','r');
#-- ファイルopenに成功した場合
if ($handle) {
  while (!feof($handle)) {
    echo fgets($handle);
  }
#-- ファイルopenに失敗した場合
} else {
  echo "hoge.txt は開けませんでした。\n";
}
?>
※上記の内容なら、freadを使うなどした方が簡単

【例2】ファイルの各行を読み込んで 「行頭が#」または「#の前に空白文字しかない」行を除いて出力
<?php
$handle = fopen('hoge.txt','r');
#-- ファイルopenに成功した場合
if ($handle) {
  #-- 最初の1行を読み込み($lineの初期値定義も兼ねて)
  $line = fgets($handle);
  #-- ファイルの最終行まで処理を繰り返し
  #-- 行コンテンツチェックも入れないと、最後の1行が処理されずループが終わる
  while ((!feof($handle)) or ($line !== false)) {
    #-- 「行頭が#」または「#の前に空白文字しかない」行を除いて出力
    if (preg_match('/^\s*#/',$line) == false) {
      echo $line;
    }
    #-- 次の1行を読み込み
    $line = fgets($handle);
  }
#-- ファイルopenに失敗した場合
} else {
  echo "hoge.txt は開けませんでした。\n";
}
?>

標準入力から1行ずつ読み込む例:

$ cat test.php
<?php
while (($line = fgets(STDIN)) !== false) {
  echo 'あなたは「'.trim($line)."」と入力しましたね\n";
}
?>
$ php test.php -
hoge
あなたは「hoge」と入力しましたね
foo
あなたは「foo」と入力しましたね
(Ctrl-D)
$ 

csvファイルを1行読み込む際はfgetcsvを使うと便利

ただし、この関数はロケール設定を考慮するため、設定とは異なる文字コードで書かれたCSVファイルを読み込むと値が文字化けする可能性がある。これに対処する方法として、ストリームフィルタをつくる方法がある21。あるいはmb_convert_encodingコマンドを使って読み込んだ文字列を変換する、あらかじめエディタで文字コードを変換したファイルを入力ファイルとして用いる、という方法が考えられる。

【書式】
fgetcsv(ファイルポインタ,読み込み長,フィールド分割文字,フィールド囲み文字,エスケープ文字);
【戻り値】
指定されたファイルポインタが有効でファイルポインタがファイルの末端ではない→読み込んだフィールドの内容を含む数値添字配列
※空行であった場合、nullフィールドを1つだけ含む配列を返す
ファイルポインタがファイルの終端、その他エラー→false
指定されたファイルポインタが無効→null
ファイルポインタ
fopen(), popen(), もしくは fsockopen() で正常にオープンされたファイルを指す有効なファイルポインタを指定する必要がある。
読み込み長
読み込むCSVファイルの最長行よりも大きな値を指定する必要がある(行末文字も考慮した上で)。そうしないと、ここで指定した文字数を超える長さを持つ行は複数行に分割されてしまう。ただし、フィールド囲いこみ文字の内部では、この分割は発生しない。このパラメータを省略 (もしくは PHP 5.1.0 以降で 0 を設定) すると、 最大行長は制限されないが、若干動作が遅くなる。 既定値は0(制限なし)。
フィールド分割文字
各フィールドを区切る文字をシングルバイト1文字で指定する。既定値はコンマ(,)。
フィールド囲み文字
各フィールドを囲む文字をシングルバイト1文字で指定する。既定値はダブルクオート(")。
エスケープ文字
エスケープ文字をシングルバイト1文字以内で指定する。空文字("")を指定するとエスケープの機能は無効化される。既定値はバックスラッシュ・円マーク(\)。

ファイル全体を読み込む

関数 ファイル指定 読み込み開始位置 戻り値 テキスト バイナリ 備考
fread ファイルポインタ ポインタ位置 ポインタ位置以降残り全部を出力する時、画像などのバイナリファイルを扱う時に有効。
filegzfile ファイル名 先頭 配列 × 巨大なファイルを指定するとメモリ不足でエラーになることがある。
readfilereadgzfile ファイル名 先頭 (解凍後の)データバイト数 × ファイルを読み込み、解凍し、標準出力に書き込む。
file_get_contents ファイル名 指定可能 × テキストデータを全て出力するのに有用。

freadは指定したファイルポインタが指すファイルポインタ(ファイル上で処理を行う位置)から以下の条件に適合するまで読み込みを行う。正常に読み込めた場合はその文字列を、何らかのエラーがあった場合はfalseを返す。

  • 読み込んだ量が指定したバイト数に達した
  • ファイルの終端(EOF)を検出した
  • パケットが利用可能になった(ネットワークストリームの場合)
  • 8192バイト分読み込んだ(ユーザ定義ストリームをオープンした後)
【書式】
fread(ファイルポインタ,整数);

【例】ファイル全体を出力
<?php
$handle = fopen('test.txt','r'); # 読み取り専用モードでファイルを開く
echo fread($handle,filesize('test.txt')); # ファイル全体を出力
fclose($handle); # ファイルを閉じる
?>
      

freadは画像ファイルなどのバイナリファイルでも扱うことができる。但し、その場合はバイナリモードでファイルを開く必要がある(fopenのモードパラメータに'b'を指定)。

freadはファイル全体を「1つの値」として返すが、fileはファイル全体を読み込んで改行文字で区切り、「各行を要素に格納した配列」を返す。gzfileは対象がgzip圧縮されたファイルであること以外は同じ。

【書式】
file(ファイル名, フラグ);
【戻り値】
正常取得→ファイルの改行を区切りとした各行を要素とする配列('FILE_IGNORE_NEW_LINES'フラグの指定がない場合は各行末尾の改行記号はついたまま)
取得に失敗→false
      
フラグ
以下の値のうち1つ以上指定できる。クォート記号などで囲まずそのまま指定する。複数のフラグを指定するには縦棒('|')を挟んで複数のフラグ値を記す。
  • FILE_USE_INCLUDE_PATH…ファイル検索場所にinclude_pathを含める
  • FILE_IGNORE_NEW_LINES…各配列要素の末尾に改行文字を含めない
  • FILE_SKIP_EMPTY_LINES…空行を読み飛ばす
  • FILE_TEXT…値をUTF-8のテキストで保存。FILE_BINARYとの同時指定は不可。
  • FILE_BINARY…値をバイナリデータ(そのままの値)で保存。FILE_TEXTとの同時指定は不可。

readfilegzfileとほぼ同等だが、戻り値が得た内容の配列ではなくデータバイト数。得た内容は標準出力に出力される。readgzfileについても同様。gzip圧縮されたファイルでも扱える。gzfileとの違いは、戻り値が得た内容の配列ではなく解凍後のデータバイト数。得た内容は標準出力に出力される。

【書式】
readfile(ファイル名,use_include_path,コンテキスト);
readgzfile(ファイル名,use_include_path);
【戻り値】
読み込みに成功→[整数](解凍後の)データバイト数
読み込みに失敗→false
      
ファイル名
[文字列]読み込み対象ファイルのファイル名
use_include_path

(readfileの場合)[真偽値]include_pathにあるファイルも検索したい場合 true を指定する。指定がない場合の既定値は false。

(readgzfileの場合)[整数]include_pathにあるファイルも検索したい場合 1 を指定する。指定がない場合の既定値は 0。

コンテキスト
コンテキストストリームリソース。

file_get_contentsは指定したテキストファイルの中身を全て返す。バイナリファイルを扱うことがないのであればfreadより効率的。

【書式】
file_get_contents(ファイル名またはURL,フラグ,コンテキストリソース,読み込み開始位置,読み込み長);
【戻り値】
読み込みに成功→読み込んだ文字列
読み込みに失敗→false
      
フラグ
file参照(FILE_IGNORE_NEW_LINES, FILE_SKIP_EMPTY_LINESを除く)。
コンテキストリソース
stream_context_createで作成したコンテキストリソース。これを使えば、httpフォームでPOSTした結果を得たりすることができる。独自のコンテキストを使用する必要がない場合は、このパラメータに NULL を指定する。
[test.php]
#!/usr/bin/php
<?php

?>

$ chmod +x test.php
$ ./test.php
→POSTした結果がファイルで得られる
読み込み開始位置
何文字目から読み込みを開始するかを指定する。先頭を0文字目と数える。
読み込み長
何バイト分読み込むかを指定する。指定がない場合の既定値はファイル終端まで。
【例】
$ cat test.php
#!/usr/bin/php
<?php
# POST先URLセット
$url = 'http://service.pdbj.org/mine/sql';
# POSTパラメータセット
$params['q'] = <<< SQL_DOC
SELECT e.id, e.pdbx_description FROM xmldoc d
JOIN entity e ON d.docid=e.docid
WHERE pdbid='1q48'
SQL_DOC;
$params['format'] = 'csv';
# リクエストコンテンツ作成
$data = http_build_query($params);
# リクエストヘッダセット
$header = array("Content-Type: application/x-www-form-urlencoded",
                "Content-Length: ".strlen($data));
# POSTするstreamを構築
$options = array('http'=>array('method'=>'POST',
                               'header'=>implode("\r\n",$header),
                               'content'=>$data));
# リクエストをPOST
$result = file_get_contents($url, NULL, stream_context_create($options));
# リクエスト結果を出力
echo $result;
?>
$ php test.php
id,pdbx_description
1,NifU-like protein

なお、リクエストヘッダがなくても一応動作するが、Content-typeが指定されていないのでapplication/x-www-form-urlencodedであると推定し処理しましたというNoticeが出る[2]

ファイルコンテキストの作成(stream_context_create)

stream_context_createは、httpフォームのGET/POSTリクエスト送信などのコンテキストを作成し、そのリソースを返す。これをfile_get_contents などで指定してリクエスト結果を得るのに用いることができる。

【書式】
stream_context_create(オプション,パラメータ);
【戻り値】
ストリームコンテキストリソース
オプション
「$連想配列変数名['ラッパー']['オプション']」の形式を取る連想配列を指定する。HTTPの場合
method 文字列 文字列にはGET、POSTなどのメソッド名を指定する
【例】
#!/usr/bin/php
<?php

?>
      
パラメータ

書き込み

fwritefopenで開いたファイルリソースのファイルポインタがある位置に書き込みを行う。fputsでも同じ。

gzopenで開いたgzファイルのファイルリソースに対してはgzwritegzputs)を用いる。

【書式】
fwrite(ファイルポインタ,書き込む文字列,バイト数);
gzwrite(ファイルポインタ,書き込む文字列,バイト数);
【戻り値】
書き込み成功→書き込んだバイト数(gzwriteの場合、解凍後のサイズ)
失敗→false
      
ファイルポインタ
fopenでファイルを開いて得たファイルポインタ。
バイト数(任意)
この指定を行うと、書き込んだバイト数が書き込む文字列が終わる前にこの指定値に達した場合、途中であっても書き込みを終了する。

パス、ファイル名情報

basename関数で、パス文字列からファイル名部分を取り出す。オプションで拡張子部分も除去可能。

dirname関数で、ディレクトリ名を返す。ディレクトリ区切り文字が見つからない場合はカレントディレクトリを示すドット(.)を、それ以外の場合はファイル名とその直前のスラッシュを除いた文字列が返る。

いずれも、Windows環境ではスラッシュ(/)およびバックスラッシュ(\)の両方が、その他の環境ではスラッシュ(/)のみがディレクトリの区切り文字とみなされる。

【書式】
basename(パス文字列,拡張子)
dirname(パス文字列)

【例】
$path = "/var/www/html/index.php";
echo basename($path); →index.php
echo basename($path,".php"); →index
echo dirname($path); →/var/www/html
      

ファイル名やディレクトリ名の情報を一括して配列変数で受け取るには、pathinfo関数を用いる。

【書式】
pathinfo(パス文字列,オプション)

【例】
$path = "/var/www/html/index.php";
print_r(pathinfo($path));

Array
(
    [dirname] => /var/www/html
    [basename] => index.php
    [extension] => .php
    [filename] => index
)
      

リンク元をたどり絶対パス化する(realpath)

realpath関数では、指定したパスのシンボリックリンクを展開し、「/./」「/../」「/」などの参照をすべて解決することにより、元のファイルに対する絶対パスを返す。ファイルが存在しないなど情報が取得できなかった場合はFALSEを返す。

【書式】
realpath(パス文字列)

【例】
shell> pwd
/var/www/html/
shell> ls -l ./jv.jar
lrwxrwxrwx 1 hoge hoge 37  1月  1日 12:00 ./jv.jar -> /usr/local/share/jV_3_6_5/jv3_6_5.jar

$path = "./jv.jar";
echo realpath($path); 
/usr/local/share/jV_3_6_5/jv3_6_5.jar
      

ファイルの日時情報取得

関数 戻り値
fileatime 最終アクセス日時
filectime inode変更日時
filemtime 最終更新日時
【書式】
fileatime(ファイルパス・ファイル名)
filectime(ファイルパス・ファイル名)
filemtime(ファイルパス・ファイル名)

正常に情報が取得できた場合はUNIXタイムスタンプ形式の時刻情報が、そうでない場合はfalseが返る。

【例】最終更新日から生成した拡張子を持つバックアップファイルを作成する
<?php
$srcdir = '/path/to/srcdir';
$dstdir = '/path/to/backupdir';
$dhandle = opendir($srcdir);
if ($dhandle) {
  while (($file = readdir($dhandle)) !== false) {
    echo 'cp -a '.$srcdir.'/'.$file.' '.$dstdir.'/'.$file.'.bak_'.date('Ymd',filemtime($srcdir.'/'.$file))."\n";
    exec('cp -a '.$srcdir.'/'.$file.' '.$dstdir.'/'.$file.'.bak_'.date('Ymd',filemtime($srcdir.'/'.$file)));
    echo 'ls -ltr '.$srcdir.'/'.$file.' '.$dstdir.'/'.$file.'.bak_*'."\n";
    echo shell_exec('ls -ltr '.$srcdir.'/'.$file.' '.$dstdir.'/'.$file.'.bak_*');
  }
}
?>

ファイルポインタ関係

rewindfopenで正常に開かれたファイルのファイルポインタ(参照するファイル上の位置)をファイルの先頭に戻す。処理に成功した場合はtrueを、失敗した場合はfalseを返す。gzopenで開いたファイルの場合は、gzrewindを使う。

【書式】
rewind(ファイルポインタ);
gzrewind(ファイルポインタ);

【例】
$ cat test.php
<?php
$handle = fopen('test.txt','w+');              # 読み書き可能モードでファイルを開く
fwrite($handle, '祇園精舎の金の声');           # 先頭から書き込み
fwrite($handle, ' 諸業無情の響き有り');       # 末尾に追記
rewind($handle);                               # ファイルポインタを先頭に戻す
fwrite($handle, '祇園精舎の鐘の声');           # 先頭から上書き
rewind($handle);                               # 再びファイルポインタを先頭に戻す
echo fread($handle,filesize('test.txt'))."\n"; # ファイル全体を出力→fread参照
fclose($handle);                               # ファイルを閉じる
?>
$ php test.php
祇園精舎の鐘の声 諸業無情の響き有り           # 「金」が「鐘」に書き換わっている

      

fseekfopenで正常に開かれたファイルのファイルポインタ(参照するファイル上の位置)を任意の位置に移動する。

【書式】
fseek(ファイルポインタ,オフセット,whence);
【戻り値】
ポインタ移動に成功→0
ポインタ移動に失敗→-1

オプション

ファイルポインタ
fopenで得られるファイルポインタ。
オフセット
バイト単位の移動量を整数値で指定する。ファイルの終端からの移動を指定するには、whence に "SEEK_END" を設定した上で、負の値をオフセットに指定する。
whence
移動の起点を指定する。指定できる値は以下の通り。指定がない場合の既定値は "SEEK_SET"(ファイルの先頭を起点とする)。
SEEK_SET
ファイルの先頭を起点とする(既定値)
SEEK_CUR
現在のポインタ位置を起点とする
SEEK_END
ファイルの終端を起点とする

ポインタをファイルの終端に移動させるには fseek(ファイルポインタ,0,SEEK_END)。ただし、この状態でfeofを使いファイル終端に達したかを判定してもfalseになる。ここで更に1行読めば判定結果はtrueになる。

ファイルをコピーする(copy)

copyはファイルをコピーする。

【書式】
copy(コピー元,コピー先)

【戻り値】
コピーに成功すればtrue、失敗すればfalse
コピー先
コピー先のパス、またはURL。コピー先のファイルが既に存在した場合は上書きされる。URLでコピー先を指定し、ファイルが既に存在した場合、ラッパーが上書きをサポートしていない場合はコピーに失敗する。UNIXのcpコマンドとは異なり、同じファイル名でコピーする場合でもコピー先にファイル名まで指定する必要あり(コピー先ディレクトリ名だけではエラーになる)。

ファイルの最終更新日を保持してコピーする(UNIXのcpコマンドに -a または -p オプションをつけて実行した場合に相当する操作を行う)場合、このcopyコマンドでコピーした後、touchコマンドでコピー元ファイルのタイムスタンプをコピー先ファイルに書き込めばよい

【例】
$ cat test.php
<?php
$orgfile = "hoge.txt";
$bakfile1 = "hoge.txt.bak1";
$bakfile2 = "hoge.txt.bak2";
copy($orgfile,$bakfile1);
copy($orgfile,$bakfile2);
touch($bakfile1,filemtime($orgfile));
?>
$ touch hoge.txt
$ ls -l --time-style long-iso
total 0
-rw-rw-rw- 1 oresama oresama   0 2019-09-20 15:28 hoge.txt
-rw-rw-rw- 1 oresama oresama 180 2019-09-20 15:38 test.php
$ touch test.php
$ ls -l --time-style long-iso
total 0
-rw-rw-rw- 1 oresama oresama   0 2019-09-20 15:28 hoge.txt
-rw-rw-rw- 1 oresama oresama   0 2019-09-20 15:28 hoge.txt.bak1
-rw-rw-rw- 1 oresama oresama   0 2019-09-20 15:40 hoge.txt.bak2
-rw-rw-rw- 1 oresama oresama 180 2019-09-20 15:38 test.php

ファイルのタイムスタンプを変更する(touch)

touchはファイルのタイムスタンプ(最終アクセス時刻と最終更新時刻)を変更する。引数の指定値に関わらずアクセス時刻は常に更新されることに注意。ファイルが存在しない場合はファイルが生成される。

【書式】
touch(ファイル名,最終更新時刻,最終アクセス時刻)

【戻り値】
設定に成功すればtrue、失敗すればfalse
【必須】(文字列)ファイル名
タイムスタンプを操作する対象となるファイルのファイル名。指定したファイルが存在しない場合、新たにファイルが作成される。
(整数)最終更新日時
設定する最終更新日時を表すUNIX時間(Epoch、1970/01/01 00:00:00からの積算秒数)。指定を省略した場合の既定値は現在時刻。
(整数)最終アクセス日時
設定する最終アクセス日時を表すUNIX時間(Epoch、1970/01/01 00:00:00からの積算秒数)。指定を省略した場合、最終更新日時の指定があればそれと同じ値を、最終更新日時の指定もなければ現在時刻が設定される。

ファイルの移動、ファイル名の変更を行う(rename)

renameはファイルの移動(場所のパス変更)や、ファイル名の変更を行う。新しいファイル名として指定したファイルが既に存在していた場合は暗黙のままに上書きされる(可能であれば)。

【書式】
rename(既存ファイル名,新しいファイル名);

処理に成功した場合は true が、失敗した場合は false が返る。

【例】
$ echo `date "+%Y-%m-%d %H:%M:%S"` > test.txt
$ echo `date "+%Y-%m-%d %H:%M:%S"` > test2.txt
$ cat test.txt test2.txt
2011-09-14 12:33:16
2011-09-14 12:33:19
$ php -r "rename('test.txt','test2.txt');"
$ cat test.txt test2.txt
cat: test.txt: No such file or directory
2011-09-14 12:33:16

ディレクトリ削除(rmdir)

rmdirはディレクトリを削除する。ディレクトリ削除に成功すれば true、失敗すれば false を返す。

【書式】
rmdir(パス名,コンテキスト);

【戻り値】データ型:論理値(boolean)
処理に成功→true
処理に失敗→false
(文字列型)パス名
ディレクトリのパス
(リソース型)コンテキスト

所有者・アクセスモードの変更(chmod、chown、chgrp)

chmodは指定したモードにファイルのアクセスモードを変更する。

chownはファイルの所有者を、chgrpはファイルのグループを変更する。ファイルの所有者はスーパーユーザのみ変更可能。ファイルのグループは一般ユーザの場合chgrpを実行するユーザの所属するグループにのみ変更可能。スーパーユーザは任意のグループに変更可能。

【書式】
chmod(ファイル名,モード);
chown(ファイル名,ユーザ名またはユーザID,);
chgrp(ファイル名,グループ名またはグループ番号);

【戻り値】
変更に成功→TRUE
変更に失敗→FALSE
ファイル名
(文字列 string)ファイルへのパス。
モード(chmodのみ)
(整数 integer)8進数で、1は実行権限、2は書き込み権限、4は読み込み権限を付与する。指定値は自動的に8進数とは判断されないため、明示的に8進数であることを示すには先頭に0を付けておく必要がある。
【例】755(rwxr-xr-x)の権限を設定
chmod('/somedir/somefile', 755); # 誤り 10進数の755は8進数の1363の意味になる
chmod('/somedir/somefile', 'rwxr-xr-x'); # 誤り 文字列による指定は受け付けない
chmod('/somedir/somefile', 0755); # 正しい
ユーザ名またはユーザ番号(chownのみ)
ユーザ名またはユーザ番号(uid)。
グループ名またはグループ番号(chgrpのみ)
グループ名またはグループ番号(gid)。

MD5ハッシュ値を得る(md5_file)

md5_fileは指定したファイルのMD5ハッシュ値を計算する。文字列のMD5ハッシュ値を計算する場合はmd5を用いる。

【書式】
md5_file(ファイル名,raw_output);
【戻り値】
計算成功:ダイジェスト計算結果
計算失敗:false      
【必須】(文字列)ファイル名
計算対象とするファイルのファイル名。URLも指定できるらしい。
(真偽値)raw_output
trueを指定すると長さ16のバイナリデータで計算値(ダイジェスト)を返す。falseを指定すると32文字の16進数でMD5ハッシュ値を返す。指定がない場合の既定値は false。

圧縮解凍関係

Zip関係

ZIP圧縮関係

Zlib関係

gzip圧縮関係

gzip圧縮ファイルの読み込み
コマンド 対象の指定 ファイルの扱い
gzread 圧縮ファイルポインタ ポインタ位置から指定長分の文字列を返す
readgzfile 圧縮ファイル名 読み込み解凍した内容全てを標準出力に出力する(戻り値は出力したバイト数)
gzfile 圧縮ファイル名 読み込み解凍した内容全てを、各行を要素に持つ配列で返す
gzread(ファイルポインタリソース,読み込むバイト数);
readgzfile(ファイル名,include_pathを検索対象に含めるかどうかのフラグ);
gzfile(ファイル名,include_pathを検索対象に含めるかどうかのフラグ);
	
ファイルポインタリソース
gzopenで得たファイルポインタリソースを指定する。
include_pathを検索対象に含めるかどうかのフラグ
1を指定するとinclude_pathにあるファイルも検索対象となる。既定値は0(含めない)。

ファイルポインタリソースが指すポインタ位置から、最大読み込むバイト数に指定したバイト数だけ読み込んで返す。指定バイト数に達する前にファイルの終端(EOF)に達した時も読み込みを終了して読み込んだ値を返す。

readgzfileは読み込みに成功すればデータのバイト数を、失敗すればfalseを返す。 gzfileは読み込んだファイルの各行を要素に持つ配列を返す。

gzip圧縮ファイルへの書き込み(gzwrite)

gzwriteはgzip圧縮ファイルへの書き込みを行う。ファイルは gzopen で得たgzip圧縮ファイルポインタで指定。戻り値は解凍状態での書き込んだバイト数。

gzwrite(ファイルポインタ,書き込む文字列,書き込む長さ);
	
gzip圧縮ファイルを閉じる(gzclose)

gzclosegzopenで開いたgzip圧縮ファイルを閉じる。

【書式】
gzclose(ファイルポインタ);
【戻り値】
成功→true
失敗→false

外部コマンドの実行

execは、外部コマンドを実行する。戻り値はコマンド出力の最終行。実行されたコマンドの全出力を得るには、出力を受領する変数を第2引数に指定する(出力の各行を要素とする配列が代入される)。shell_execも似ているが、戻り値が全てのコマンド出力である点が異なる。

systemは戻り値がコマンド出力の最終行である点は同じだが、PHPをサーバモジュールとして実行している場合、systemを呼び出すと、コマンド出力を出力した後、自動的にウェブサーバの出力バッファの内容を出力して消去される。

passthruも外部コマンドを実行するが、出力を整形することなくそのまま表示する。コマンドからの出力がバイナリデータで、ブラウザへ直接返す必要がある場合に用いることができる。

【書式と戻り値】
exec(コマンド, 出力受領変数, コマンド戻り値格納変数);
→コマンド出力最終行
shell_exec(コマンド);
→コマンド出力全体
passthru(コマンド,コマンド戻り値格納変数);
→なし
system(コマンド,コマンド戻り値格納変数);
→コマンド出力最終行(失敗時はfalse)
    
出力受領変数(execのみ)
この引数を指定すると、指定した配列変数にコマンド出力の各行を要素とする配列が追加される(既存の要素を残したくないのであればexec実行前にunsetコマンドで変数を消去するなどの措置が必要)。各要素には行末の空白文字群(改行など)は含まれない。
【例】hoge.txtの行数を得る(→wc=行数とファイル名を返す、gawk=テキスト切り出し)
[test.php]
<?php
$linenum = exec("wc -l hoge.txt | gawk '{print $1}'");
echo "行数は ".$linenum." です。\n";
?>

$ wc -l hoge.txt
150  hoge.txt
$ wc -l hoge.txt | gawk '{print $1}'
150
$ php ./test.php
行数は 150 です。

【例】ファイルリストを得る(execを利用した場合)
[test.php]
<?php
echo exec("ls",$output);
print_r($output);
?>

$ ls
2zuo.pdb1               mom072_rel_ja.html~     mom116_1.jmol
2zv4.pdb1               mom073_ja.html          mom116_1.pdb
2zv5.pdb1               mom073_rel_ja.html      mom116_2.jmol
Jmol.js                 mom073_rel_ja.html~     mom116_2.pdb
biolgen.php             mom074_ja.html          mom116_ja.html
biolgen.php~            mom074_rel_ja.html      mom116_jmol_1_ja.html
biolgen_pdbml.php~      mom074_rel_ja.html~     mom117_1.jmol
carbonext.php           mom075_ja.html          mom117_1.pdb
carbonext.php~          mom075_rel_ja.html      mom117_ja.html
$ php ./test.php
mom117_ja.html # コマンドの戻り値は最終行
Array # 出力受領変数の各要素に出力の各行が格納される
(
    [0] => 2zuo.pdb1
    [1] => mom072_rel_ja.html~
    [2] => mom116_1.jmol
    [3] => 2zv4.pdb1
    [4] => mom073_ja.html
    [5] => mom116_1.pdb
    [6] => 2zv5.pdb1
    [7] => mom073_rel_ja.html
    [8] => mom116_2.jmol
    [9] => Jmol.js
    [10] => mom073_rel_ja.html~
    [11] => mom116_2.pdb
    [12] => biolgen.php
    [13] => mom074_ja.html
    [14] => mom116_ja.html
    [15] => biolgen.php~
    [16] => mom074_rel_ja.html
    [17] => mom116_jmol_1_ja.html
    [18] => biolgen_pdbml.php~
    [19] => mom074_rel_ja.html~
    [20] => mom117_1.jmol
    [21] => carbonext.php
    [22] => mom075_ja.html
    [23] => mom117_1.pdb
    [24] => carbonext.php~
    [25] => mom075_rel_ja.html
    [26] => mom117_ja.html
)

【例】ファイルリストを得る(shell_execを利用した場合)
[test.php]
<?php
echo exec("ls",$output);
print_r($output);
?>

$ php ./test.php
2zuo.pdb1 # コマンドの戻り値は全ての出力
mom072_rel_ja.html~
mom116_1.jmol
2zv4.pdb1
mom073_ja.html
mom116_1.pdb
2zv5.pdb1
mom073_rel_ja.html
mom116_2.jmol
Jmol.js
mom073_rel_ja.html~
mom116_2.pdb
biolgen.php
mom074_ja.html
mom116_ja.html
biolgen.php~
mom074_rel_ja.html
mom116_jmol_1_ja.html
biolgen_pdbml.php~
mom074_rel_ja.html~
mom117_1.jmol
carbonext.php
mom075_ja.html
mom117_1.pdb
carbonext.php~
mom075_rel_ja.html
mom117_ja.html
    

なお、エラー出力も受領したい場合はエラーも標準出力に出力するよう指示する必要がある。

$ php -r '$lastline = exec("qstat 12345");echo "The last line of the command output is following:\n".$lastline."\n";'
qstat: Unknown Job Id 12345.server               ← エラー出力で出力された内容
The last line of the command output is following:
                                                 ← コマンド(標準)出力最終行は空

$ php -r '$lastline = exec("qstat 12345 2>&1");echo "The last line of the command output is following:\n".$lastline."\n";'
The last line of the command output is following:
qstat: Unknown Job Id 12345.server               ← エラー出力を標準出力にリダイレクトしたのでエラーがこちらに出ている

文字列をPHPコードとして処理

evalは、指定した文字列をPHPコードして評価する。

内部関数、サブルーチン

関数定義

ユーザ定義関数の定義書式は以下の通り。

function 関数名 (引数名,引数名...)
{
(処理内容)
}
      

戻り値を返したい場合はreturnを用いる。

function 関数名 (引数名,引数名...)
{
(処理内容)
return 変数名など
}
      

引数は、通常の指定では「値渡し」となり関数内での操作は関数外に影響しないが、「参照渡し」にすると関数外の値を操作できる。「参照渡し」を利用する場合、「参照渡し」としたい引数名の前にアンパサンド(&)をつけて関数定義する。複数の値を返したい場合などに便利(複数の値を配列に格納すれば、値渡しでも対応は可能)。

function 関数名 (&引数名,&引数名...)
{
(処理内容)
}
      

既定値を指定するには引数名の後に「 = 」を記す。なお、既定値を指定しない変数を先に記すこと。既定値のある引数は、関数を呼び出す際指定を省略できる。既定値は定数のみ指定できる(変数は指定できない)。

function 関数名 (引数名 = 既定値,&引数名 = 既定値...)
{
(処理内容)
}
      

参考文献・サイト

関数呼び出し

【書式】
call_user_func (関数名, パラメータ1, ...)
      
【例】
<ソース>
function hoge ()
{
echo "hogehoge";
}

echo "foo¥n";
call_user_func("hoge");

<実行結果>
foo
hogehoge
      

実はcall_user_funcを使わなくても、定義済み関数と同様に呼び出せる。

【例】
<ソース>
function hoge ()
{
echo "hogehoge";
}

echo "foo¥n";
hoge();
      

また、複数の引数を返したい場合は、参照渡しを使うと便利。

【コード】
<?php
function double_val($val) {
  $val = $val * 2;
}
function double_ref(&$val) {
  $val = $val * 2;
}
$i = 10;
echo "値渡しの場合、" . $i . " は ";
double_val($i);
echo $i . " のままです。<br />";
echo "参照渡しの場合、" . $i . " は ";
double_ref($i);
echo $i . " になります。<br />";
?>

【結果】
値渡しの場合、10 は 10 のままです。
参照渡しの場合、10 は 20 になります。
      

呼び出す関数を動的に指定するには、あらかじめ変数に関数名をセットしておき、${変数名}(引数)のように指定する3

【例】(現実的な例ではないが...)
$funcname = "func_" . date("M"); #- date("M") は アルファベット3文字の月名略称を返す
${$funcname}(); #- 4月なら "func_Apr"が呼び出される
      

参考文献・サイト:

値を返す(return)

returnが、関数内で呼び出されるとその関数の実行を即座に停止し、引数を関数の戻り値として返す。グローバルスコープ(スクリプトのメイン部分)で呼び出されると、実行中のスクリプトが終了する。なお return は関数ではなく言語構造であるため引数を括弧で囲む必要はない(囲むと囲まれた値や変数を評価したものを戻り値として扱う)。

return 戻り値
      

外部スクリプトファイルの読み込み(include, require)

include文は、外部スクリプトファイルを読み込んで評価する。他のファイルに記述した関数を取り込んで利用することができる。ファイル名のみの場合は、include_pathに設定されたパスを探し、相対パスまたは絶対パスを指定した場合はその指定パスを探しに行く。requireも同等だが、読み込みに失敗した際、E_ERRORレベルの致命的エラーを発生してスクリプト処理を停止する点が異なる(includeは警告(E_WARNING)を発するがスクリプト処理は継続される)。

[common.php](読み込まれるファイル)
<?php ←読み込まれるファイルにもPHP開始タグは必要
$subway = array(
  '1'=>array('name'=>'御堂筋','length'=>'24.5','color'=>'red'),
  '2'=>array('name'=>'谷町','length'=>'28.3','color'=>'purple'),
  '3'=>array('name'=>'四つ橋','length'=>'11.8','color'=>'blue'),
  '4'=>array('name'=>'中央','length'=>'17.9','color'=>'green'),
  '5'=>array('name'=>'千日前','length'=>'13.1','color'=>'pink'),
  '6'=>array('name'=>'堺筋','length'=>'8.1','color'=>'brown'),
  '7'=>array('name'=>'長堀鶴見緑地','length'=>'15.0','color'=>'lightgreen'),
  '8'=>array('name'=>'今里筋','length'=>'11.9','color'=>'orange'));
?>

[index.php]
<?php
include 'common.php'; ←外部ファイルの指定
echo "<ul>\n";
foreach ($subway as $val) {
  echo "<li>" . $val['name'] . "線(" . $val['length'] . "km, color " . $val['color'] . ")</li>\n";
}
echo "</ul>\n";

【出力】
<ul>
<li>御堂筋線(24.5km, color red)</li>
<li>谷町線(28.3km, color purple)</li>
<li>四つ橋線(11.8km, color blue)</li>
<li>中央線(17.9km, color green)</li>
<li>千日前線(17.9km, color pink)</li>
<li>堺筋線(8.1km, color brown)</li>
<li>長堀鶴見緑地線(13.1km, color lightgreen)</li>
<li>今里筋線(11.9km, color orange)</li>
</ul>
      

読み込む際、PHPモードが一時解除されるので、PHPスクリプトを記述するのであれば、読み込む先のファイルにPHP開始終了タグ(<?php ... ?>)が必要。 関数内で呼び出すと、関数内だけで有効。 ファイルにリモートサーバのPHPスクリプトURLを指定した場合、リモートサーバで処理された結果が、読み込まれる。

参考文献・サイト:

スクリプト処理の終了(exit、die)

exitはスクリプト処理を終了する。戻り値はなし。dieも機能は同じ。

【書式】
exit(文字列);
exit(整数);
      
文字列
文字列を引数に指定した場合、指定した文字列を表示して終了する。
整数
整数を引数に指定した場合、その値は終了ステータスとして利用され、表示することなく終了する。指定できる整数は0〜254。0はプログラムを正常終了させるのに用いる。
【例】
<?php
$link = mysql_connect('localhost'.'hoge')
  or exit("MySQLサーバに接続できません。");
?>
      

ネットワーク関数

ホスト名を得る(gethostname)

gethostnameはローカルのマシンに設定されている標準的なホスト名を返す。PHP 5.3.0より使用可能。

【書式】
gethostname();
【戻り値】
成功→得られたホスト名
失敗→false

ホスト名からIPアドレスを得る(gethostbyname)

gethostbynameは指定したインターネットホストの IPv4 アドレスを返す。

【書式】
gethostbyname(ホスト名);
【戻り値】
成功→IPv4アドレス(文字列型)
失敗→指定したホスト名をそのまま文字列で返す

FTP関数

FTPサーバとの接続を開く(ftp_connect)

ftp_connectは指定したサーバへのFTP接続を開く。実際にやりとりするにはftp_loginコマンドでログインする必要がある。

【書式】
ftp_connect(FTPサーバ,ポート番号,タイムアウト時間);
      
FTPサーバ
FTPサーバのアドレス。前に「ftp://」を付けたり、最後にスラッシュをつけたりしないこと。
ポート番号
FTP制御用セッションのサーバ側ポート番号を指定する。指定がない場合の既定値は21。
タイムアウト時間
以降のネットワーク操作時のタイムアウト時間を指定する。指定がない場合の既定値は90秒。

戻り値は、接続に成功した場合はその接続のリンクID(FTPストリーム)、そうでない場合はfalse。

FTPサーバとの接続を閉じる(ftp_close、ftp_quit)

ftp_closeftp_quitは指定した接続IDのFTP接続を閉じる。

【書式】
ftp_close(接続ID);
      

FTPサーバにログインする(ftp_login)

ftp_loginは指定したFTPストリームにログインする。

【書式】
ftp_login(接続ID,ユーザ名,パスワード);
      

ログインに成功した場合はtrueを返す。失敗した場合はfalseを返した上でPHPの警告が発生する。

カレントディレクトリを表示(ftp_pwd)

ftp_pwdはFTPサーバ上でのカレントディレクトリを表示する。

【書式】
ftp_pwd(接続ID);
      

カレントディレクトリの取得に成功した場合はそのディレクトリ名を、失敗した場合はfalseを返す。

ディレクトリを移動する(ftp_chdir)

ftp_chdirはFTPサーバ上でのカレントディレクトリを移動する。

【書式】
ftp_chdir(接続ID,移動先ディレクトリ);
      

ディレクトリ変更に成功した場合はtrueを返す。失敗した場合はfalseを返した上でPHPの警告が発生する。

ファイルをダウンロードする

コマンド 保存先ファイル指定 同期モード
ftp_get 引数指定 同期(ブロッキング)
ftp_fget ファイルポインタ 同期(ブロッキング)
ftp_nb_get 引数指定 非同期(非ブロッキング)
ftp_nb_fget ファイルポインタ 非同期(非ブロッキング)

ブロッキングの場合、ダウンロードに成功した場合の戻り値はtrue、失敗した場合の戻り値はfalse。 非ブロッキングの場合、「FTP_FAILED」(失敗)、「FTP_FINISHED」(完了)、「FTP_MOREDATA」(途中)のいずれかが返る。

非ブロッキング(非同期モード)の場合、ダウンロード中でも別の処理が実行可能。他の処理を行うと一時停止するが、ftp_nb_continueコマンドにて再開できる。

【書式】
ftp_get(接続ID,保存先ファイル名,取得元ファイル名,モード,ダウンロード開始位置);
ftp_fget(接続ID,ファイルポインタ,取得元ファイル名,モード,ダウンロード開始位置);
ftp_nb_get(接続ID,保存先ファイル名,取得元ファイル名,モード,ダウンロード開始位置);
ftp_nb_fget(接続ID,ファイルポインタ,取得元ファイル名,モード,ダウンロード開始位置);
      
接続ID
ftp_connectで得た接続ID。
保存先ファイル名
保存先となるローカルのパス・ファイル名。同名のファイルが存在した場合は上書きされる。
ファイルポインタ
fopenで得たファイルポインタリソース。
取得元ファイル名
取得元となるリモートサーバ上のファイル名。
モード
通信モードを FTP_ASCII または FTP_BINARY のどちらかで指定する。
ダウンロード開始位置
リモートファイルのダウンロード開始位置。指定がない場合の既定値はファイルの先頭(0)。

ファイルをアップロードする

ファイルの最終更新日を取得する(ftp_mdtm)

ftp_mdtmは指定ファイルの最終更新日を返す。

【書式】
ftp_mdtm(接続ID,ファイル名);
      

情報取得に成功した場合はUNIXタイムスタンプを、エラー時には -1 を返す。

ファイルサイズを取得する(ftp_size)

ftp_sizeは指定ファイルのサイズを返す。

【書式】
ftp_size(接続ID,ファイル名);
      

情報取得に成功した場合はファイルサイズを、エラー時には -1 を返す。

ファイル・ディレクトリ名を変更する(ftp_rename)

ファイルを削除する(ftp_delete)

ファイル一覧を取得(ftp_nlist)

ftp_nlistは指定ディレクトリのファイル一覧を配列で返す。

【書式】
ftp_nlist(接続ID,ディレクトリ名、引数);

【戻り値】
情報取得に成功 → ファイル一覧の配列
情報取得に失敗 → false
ディレクトリ名、引数
ファイル一覧を取得するディレクトリ名。FTPのlsコマンドの引数も指定することができる(例:"-la /subdir")。

PHPでのFTPに関する参考文献・サイト

XML関数

XMLファイルを扱うには、--enable-libxmlオプション付きでインストールし、libxml拡張モジュールを有効にしておく必要あり。但し、デフォルトで有効になっているとのこと[3]。RHEL5/CentOS5ではデフォルトでは入っていない? php-xml RPMパッケージを追加インストールする必要があった。

上記の通り、利用できる環境を用意した上で、DOMDocumentクラスのインスタンス(オブジェクト)を定義する。

DOMNodeを拡張して、DOMDocument(XML文書)、DOMAttr(属性ノード)、DOMElement(要素ノード)が作られる。DOMNodeの配列がDOMNodeList。

DOMノードについて

DOMノードは文書オブジェクトモデル(Document Object Model、DOM)全体を通して基本となるデータ型(クラス)[xml2]DOM文書(DOMDocument)、DOM要素(DOMElement)、DOM属性(DOMAttr)などはDOMノードの拡張で定義される。

プロパティ
書式 戻り値の型 拡張型での利用 内容
DOM文書 DOM要素 DOM属性
DOMノード->nodeName 文字列 ノードのタグ名を返す。
DOMノード->nodeValue 文字列 ノードの値を返す。
DOMノード->parentNode DOMノード 親ノードを返す。
DOMノード->childNodes DOMノードリスト 子ノード群を含むノードリストを返す。
DOM文書->formatOutput 論理値(true/false) 字下げや空白を考慮して整形した出力を行うかどうか。trueなら行い、falseなら行わない。
【例】整形を行うよう設定する
$xml = new DOMDocument('1.0','utf-8');
$xml->formatOutput = true;
メソッド
書式 戻り値の型 拡張型での利用 内容
DOM文書 DOM要素 DOM属性
追加先DOMノード->appendChild(追加するDOMノード) DOMノード 子ノードを追加し、追加済みのノードを返す。
DOMノード->replaceChild(新DOMノード,旧DOMノード) DOMノード 子ノードを置き換え、置き換え前のノードを返す。
DOMノード->removeChild(削除するDOMノード) DOMノード 指定した子ノードを削除し、削除したノードを返す。
DOM文書->createElement(要素名,要素値) DOM要素 DOM文書で指定したDOM文書に所属するDOM要素オブジェクトを作成する。実際追加するには appendChild を使う。
DOM文書->createAttribute(属性名) DOM属性 DOM文書で指定したDOM文書に所属するDOM属性オブジェクトを作成する。実際追加するには appendChild を使い、属性値を設定するには createTextNode でテキストノードを作成し、appendChild でDOM属性ノードに子要素を追加する。操作としてはDOM要素に setAttribute メソッドを使って設定した方が簡単。
DOM要素->setAttribute(属性名,属性値) DOM属性 DOM要素で指定したDOM要素に属性名属性値で指定したキーと値を持つ属性を設定する。属性名で指定したキーが存在しない場合は新たな属性が作成される。
DOM文書->createTextNode(文字列) DOMテキストノード DOM文書で指定したDOM文書に所属するDOMテキストノードオブジェクトを作成する。実際追加するには appendChild を使う。要素値や属性値の設定に利用できる。
DOM文書->getElementById(ID属性値) DOM要素 指定したID属性値を持つ要素ノードを返す。
DOM文書->getElementByTagName(タグ名) DOMノードリスト 指定したタグ名を持つノード(要素、属性)のリストを返す。
DOM要素->getAttribute(属性名) 文字列 指定した属性名の属性値を文字列で返す。

インスタンス(オブジェクト)の作成

参照:DOMDocument::__construct

【書式】
DOMDocument(バージョン,エンコーディング);
      
バージョン
XML宣言の一部である、ドキュメントのバージョン番号。これを指定すると「<?xml version="バージョン">」が作成するオブジェクトの先頭に付加される。
エンコーディング
XML宣言の一部である、ドキュメントのエンコーディング。これを指定すると「<?xml encoding="エンコーディング">」が作成するオブジェクトの先頭に付加される。
【例】test.php
<?php
$xml = new DOMDocument('1.0','utf-8');
echo $xml->saveXML();
?>
【実行結果】
$ chmod +x test.php
$ php test.php
<?xml version="1.0" encoding="utf-8"?>
      

XML/HTMLを読み込む

DOMDocument::loadは、あらかじめ作成したDOMDocumentオブジェクトに指定したXMLファイルを読み込む。文字列からXMLを読み込むにはDOMDocument::loadXMLを使う。 HTML文字列を読み込むにはDOMDocument::loadHTML、HTMLファイルを読み込むにはDOMDocument::loadHTMLFileを使う。
【書式】
DOMDocumentオブジェクト->load(ファイル名,オプション);
DOMDocumentオブジェクト->loadXML(変数,オプション);
DOMDocumentオブジェクト->loadHTMLFile(ファイル名,オプション);
DOMDocumentオブジェクト->loadXML(変数,オプション);
DOMDocumentオブジェクト
あらかじめDOMDocumentクラスのインスタンスとして作成したDOMDocumentオブジェクト。
オプション
libxml オプション定数をビットORで連結したもの。既定値は0。
【例】
<?php
$xml = new DOMDocument();
$xml->load("hoge.xml");

$xml_src = <<< XML_END
<?xml version="1.0" encoding="utf-8" ?>
<stations>
  <line name="御堂筋">
    <station id="11">江坂</station>
    <station id="12">東三国</station>
    <station id="13">新大阪</station>
    <station id="14">中津</station>
    <station id="15">梅田</station>
  </line>
  <line name="谷町">
    <station id="11">大日</station>
    <station id="12">守口</station>
    <station id="13">太子橋今市</station>
    <station id="14">千林大宮</station>
    <station id="15">関目高殿</station>
  </line>
</stations>
XML_END;

$xml2 = new DOMDocument();
$xml2->loadXML($xml_src);
?>
      

XMLを書き出す

DOMDocument::saveは、DOM 表現からXMLドキュメントを作成しファイルに出力する。 DOMDocument::saveXMLは、DOM 表現からXMLドキュメントを作成し文字列に出力する。
【書式】
DOMDocumentオブジェクト->save(ファイル名,オプション);
【戻り値】

【書式】
DOMDocumentオブジェクト->saveXML(ノード,オプション);
【戻り値】
エラーなし→XML
エラーあり→false
      
DOMDocumentオブジェクト
あらかじめDOMDocumentクラスのインスタンスとして作成したDOMDocumentオブジェクト。
ノード
XML文書全体ではなく、XML宣言以外の特定のノードだけを取り出して出力したい場合、その取り出したいノードの要素名を指定する。
オプション
現在は LIBXML_NOEMPTYTAG のみサポートされている。このオプションを指定すると、空要素を省略形を用いず表現する(例:<br/> → <br></br>)。
【例】
<?php
$xml = new DOMDocument();
$xml->save("hoge.xml");
?>
      

指定したタグ名を持つ要素全てを得る

DOMDocument::getElementsByTagNameは、DOMDocumentオブジェクトから指定したタグ名を持つ要素全てを抽出したDOMNodeListオブジェクトを返す。各ノードを取り出すにはDOMNodeList::itemを使う。
【書式】指定したタグ名を持つ要素を全て含むノードリストを得る
DOMDocumentオブジェクト->getElementsByTagName(タグ名);
【書式】指定したタグ名を持つ要素で、指定番目に登場したノードを得る
DOMDocumentオブジェクト->getElementsByTagName(タグ名)->item(位置番号);
【書式】指定したタグ名を持つ要素で、指定番目に登場したノード(要素)の値を得る
DOMDocumentオブジェクト->getElementsByTagName(タグ名)->item(位置番号)->nodeValue;
      

位置番号は登場順に0からの連番が割り振られる。

【例】
--- test.php
<?php
$pdbml = new DOMDocument();
$pdbml->load("148l-noatom.xml");
$descriptions = $pdbml->getElementsByTagName('pdbx_description');
foreach ($descriptions as $key => $val) {
  echo "[$key] -> " . $val->nodeValue . "\n";
}
?>
--- 148l-noatom.xml
<?xml version="1.0" encoding="UTF-8" ?>
...
<PDBx:datablock datablockName="148L"
   xmlns:PDBx="http://pdbml.pdb.org/schema/pdbx-v32.xsd"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://pdbml.pdb.org/schema/pdbx-v32.xsd pdbx-v32.xsd">
...
  <PDBx:entityCategory>
    <PDBx:entity id="1">
      ...
      <!-- 1個目の pdbx_description 目の要素 -->
      <PDBx:pdbx_description>T4 LYSOZYME</PDBx:pdbx_description>
      ...
    </PDBx:entity>
    <PDBx:entity id="2">
      ...
      <!-- 2個目の pdbx_description 目の要素 -->
      <PDBx:pdbx_description>SUBSTRATE CLEAVED FROM CELL WALL OF ESCHERICHIA COLI</PDBx:pdbx_description>
      ...
    </PDBx:entity>
    <PDBx:entity id="3">
      ...
      <!-- 3個目の pdbx_description 目の要素 -->
      <PDBx:pdbx_description>SUGAR (2-MER)</PDBx:pdbx_description>
      ...
    </PDBx:entity>
    <PDBx:entity id="4">
      ...
      <!-- 4個目の pdbx_description 目の要素 -->
      <PDBx:pdbx_description>BETA-MERCAPTOETHANOL</PDBx:pdbx_description>
      ...
    </PDBx:entity>
    <PDBx:entity id="5">
      ...
      <!-- 5個目の pdbx_description 目の要素 -->
      <PDBx:pdbx_description>water</PDBx:pdbx_description>
      ...
    </PDBx:entity>
  </PDBx:entityCategory>
...
</PDBx:datablock>
------

$ php test.php
[0] -> T4 LYSOZYME
[1] -> SUBSTRATE CLEAVED FROM CELL WALL OF ESCHERICHIA COLI
[2] -> SUGAR (2-MER)
[3] -> BETA-MERCAPTOETHANOL
[4] -> water
      

なぜか数値のnodeValueは echo で出力はできるが、変数への代入ができなかった。

=== 読み込むXML(一部)
...
<PDBx:pdbx_struct_oper_listCategory>
  <PDBx:pdbx_struct_oper_list id="P">
    <PDBx:matrix11>0.30901699</PDBx:matrix11>
...
  </PDBx:pdbx_struct_oper_list>
  <PDBx:pdbx_struct_oper_list id="X0">
    <PDBx:matrix11>1.00000000</PDBx:matrix11>
...
  </PDBx:pdbx_struct_oper_list>
...
</PDBx:pdbx_struct_oper_listCategory>
...

=== PHPコード

#-- DOMインスタンス宣言
$pdbml_noatom = new DOMDocument();
#-- noatomのPDBMLを読み込む
$pdbml_noatom->load("~/1sva-noatom.xml");
#-- タグ名 pdbx_struct_oper_list の要素を全て取得
$nodelist = $pdbml_noatom->getElementsByTagName('pdbx_struct_oper_list');
#== 行列取得
foreach ($nodelist as $node) {
  $val = sprintf('%.8f',$node->getElementsByTagName('matrix11')->item(0)->nodeValue);
/* 下記記述では値が代入されなかった
  $val = $node->getElementsByTagName('matrix11')->item(0)->nodeValue;
  但し、echo はOK
  echo $node->getElementsByTagName('matrix11')->item(0)->nodeValue . "\n";
*/
  echo sprintf('%2d',$node->getAttribute('id')) . ": " . $val . "\n";
}

↓
 1: 0.30901699
 2: 1.00000000
...
      

指定したIDを持つ要素全てを得る

DOMDocument::getElementsByIdは、DOMDocumentオブジェクトから指定したIDを持つ要素を持つDOMElementオブジェクトを返す。 実際この関数を使用するには下記いずれかの方法でIDを参照できる状態にしておく必要がある。
DOMElement::setIdAttribute でIDを設定する
DTDでID型の属性を定義し、ドキュメントを検証する
【書式】
DOMDocumentオブジェクト->getElementsById(ID値);

ノードのプロパティ

書式 戻り値
ノード->nodeName; ノード(要素)名
ノード->nodeValue; ノード(要素)の値
ノード->childNodes; 全ての子要素を含むノードリスト(子がなければ空のノードリストを返す)
ノード->textContent; 指定したノードおよび子ノードのテキスト
【XML例】sample.xml
<?xml version="1.0" encoding="utf-8" ?>
<stations>
  <line name="御堂筋">
    <station id="11">江坂</station>
    <station id="12">東三国</station>
    <station id="13">新大阪</station>
    <station id="14">中津</station>
    <station id="15">梅田</station>
  </line>
  <line name="谷町">
    <station id="11">大日</station>
    <station id="12">守口</station>
    <station id="13">太子橋今市</station>
    <station id="14">千林大宮</station>
    <station id="15">関目高殿</station>
  </line>
</stations>

【PHPスクリプト】
#!/usr/bin/php
<?php
#- XMLオブジェクトを作成
$xml = new DOMDocument('1.0','utf-8');
#- XMLを読み込む
$xml->load('sample.xml');
#- line要素を全て含むノードリストを得る
$nodes_line = $xml->getElementsByTagName('line');
...
?>
      

ノードの要素値を得る

ノード(要素)のnodeValueプロパティを参照すればよい。

ノード->nodeValue;
      

ノードの属性値を得る

getAttributeNodeを使って要素から属性ノードを生成することができる。属性値はnodeValueを使って属性ノードの値を参照しても得られるが、属性値のみが必要なのであれば、属性値を返すgetAttributeを使う方が便利。

【属性値を得る】
DOMElement->getAttribute(属性名);
DOMElement->getAttributeNode(属性名)->nodeValue;
【属性ノードを得る】
DOMElement->getAttributeNode(属性名);
      

子要素数を得る

参照:DOMNodeListクラス

ノードリスト->length;
      

要素の追加削除

DOMDocument::createElement は、新たなDOM要素を作成する。実際DOM文書内へ追加するには、DOMNode::appendChild などで挿入操作を行う必要がある。

DOMNode::appendChild は子要素群の最後に要素を追加する。

【書式】
(要素の作成)戻り値:DOM要素
DOMDocument->createElement(要素名,要素値);
(要素の挿入)戻り値:DOMノード(DOM要素を含む)
子要素が追加されるDOMノード->appendChild(追加するDOMノード);
要素名
要素のタグ名に当たる文字列を指定する。
要素値
要素値を指定する。指定しなければ空の要素が作成される。要素作成後に DOMElement->nodeValue で値を設定することもできる。
DOMノード
子要素が追加されるDOMノード」に指定したDOMノード(DOM文書、DOM要素など)の最後に「追加するDOMノード」指定した名前の子ノードを追加する。
【例】
[test.php]
<?php
#- 新たなDOM文書オブジェクトを作成する
$dom = new DOMDocument('1.0','utf-8');
#- DOM要素オブジェクトを作成する
$element = $dom->createElement('root','This is the root element');
#- DOM要素オブジェクトを $dom の最後に追加する
$dom->appendChild($element);
#- $dom の内容を標準出力(画面)に出力
echo $dom->saveXML();
?>
$ php ./test.php
<?xml version="1.0" encoding="utf-8"?>
<root>This is the root element.</root>
      

DOMNode::removeChild は指定した子要素を削除する。

【書式】
DOMDocument->removeChild(削除するノード);
【戻り値】
削除に成功→削除したノード
      

子ノードを置換する

DOMNode::replaceChild は、子ノードの置き換えを行う。

【書式】
DOMノード->replaceChild(新ノード,旧ノード);
      

新ノードが既に子ノードとして存在した場合は重ねて追加することはしない。 置き換えに成功すると、旧ノードが返される。

【例】
[test.php]
<?php
#- 新たなDOM文書オブジェクトを作成する
$dom = new DOMDocument('1.0','utf-8');
#- DOM要素オブジェクトを作成する
$element = $dom->createElement('root','This is the root element');
$element2 = $dom->createElement('root2','This is the other root element');
#- DOM要素オブジェクトを $dom の最後に追加する
$dom->appendChild($element);
#- $dom の内容を標準出力(画面)に出力
echo $dom->saveXML();
#- $elementの内容を$element2に置換
$dom->replaceChild($element2,$element);
#- $dom の内容を標準出力(画面)に出力
echo $dom->saveXML();

?>
$ php ./test.php
<?xml version="1.0" encoding="utf-8"?>
<root>This is the root element.</root>
<?xml version="1.0" encoding="utf-8"?>
<root2>This is the other root element.</root2>
      

属性の追加・更新・削除

属性を追加する方法は以下の通り。

(1)DOMElement::setAttribute を使う。
DOM要素ノード->setAttribute(属性名,属性値);
属性名で指定したキーを持つ属性が既に存在した場合は属性値のみが更新される。

(2)DOMDocument::createAttributeDOMDocument::createTextNodeDOMNode::appendChild を使う。
DOM属性ノード = DOM文書ノード->createAttribute(属性名 # 属性ノード作成
DOM要素ノード->appendChild(DOM属性ノード); # 属性ノードを要素ノードに追加
DOMテキストノード = DOM文書ノード->createTextNode(属性値); # テキストノードを作成
DOM属性ノード->appendChild(DOMテキストノード); # テキストノードを属性ノードに追加
DOM属性ノードの属性値が空ではなかった場合、後に追記される。置換する場合は replaceChild を使う。
DOM属性->replaceChild(新DOMテキストノード,旧DOMテキストノード);

(3)DOMAttrオブジェクトの新規作成DOMElement::setAttributeNode を使う。
DOM属性ノード = new DOMAttr(属性名,属性値); # 属性ノードを新規作成
DOM要素->setAttributeNode(DOM属性ノード); # 属性ノードを要素ノードに追加

【例】
[test.php]
<?php
$dom = new DOMDocument('1.0','utf-8'); #- 新規DOM文書作成
$element = $dom->createElement('root','This is the root element.'); #- DOM文書に属する要素作成
$dom->appendChild($element); #- 要素をDOM文書に追加
#- 方法(1)で追加
$element->setAttribute('attr1','setAttribute'); #- 要素ノードに属性追加
#- 方法(2)で追加
$node_attr = $dom->createAttribute('attr2'); #- DOM文書に属する属性ノードを作成
$element->appendChild($node_attr); #- 属性ノードを追加
$text_attr = $dom->createTextNode('createAttribute'); #- DOM文書に属するテキストノードを作成
$node_attr->appendChild($text_attr); #- テキストノードを属性ノードに追加
#- 方法(3)で追加
$node_attr = new DOMAttr('attr3','setAttributeNode'); #- 新規属性ノードを作成
$element->setAttributeNode($node_attr); #- 属性ノードを要素ノードに追加
#- 結果確認
echo $dom->saveXML(); #- XML文書全体を保存し標準出力へ出力
#- 方法(1)で更新
$element->setAttribute('attr1','setAttribute2'); #- 要素ノードに属性追加
#- 方法(2)で更新
$node_attr = $dom->createAttribute('attr2'); #- DOM文書に属する属性ノードを再作成
$element->appendChild($node_attr); #- 属性ノードを再追加
$text_attr = $dom->createTextNode('createAttribute2'); #- DOM文書に属するテキストノードを作成
$node_attr->appendChild($text_attr); #- テキストノードを属性ノードに追加
#- 方法(3)で更新
$node_attr = new DOMAttr('attr3','setAttributeNode2'); #- 新規属性ノードを作成
$element->setAttributeNode($node_attr); #- 属性ノードを要素ノードに追加
echo $dom->saveXML($element); #- $element要素のみ保存し標準出力へ出力
?>

$ php ./test.php
<?xml version="1.0" encoding="utf-8"?>
<root attr1="setAttribute" attr2="createAttribute" attr3="setAttributeNode">This is the root element.</root>
<root attr1="setAttribute2" attr2="createAttribute2" attr3="setAttributeNode2">This is the root element.</root>
	

属性値を更新する方法は以下の通り。

(4)DOMElement::setAttribute を使う。
DOM要素ノード->setAttribute(属性名,属性値);
※新規に属性を追加する手順と同じ。属性名で指定したキーを持つ属性が既に存在した場合は属性値のみが更新される。

(5)DOMDocument::createAttributeDOMDocument::createTextNodeDOMNode::replaceChild を使う。
DOM属性ノード = DOM文書ノード->createAttribute(属性名 # 属性ノード作成(作成済みならこの手順は不要)
DOM要素ノード->appendChild(DOM属性ノード); # 属性ノードを要素ノードに追加(作成済みならこの手順は不要)
新DOMテキストノード = DOM文書ノード->createTextNode(属性値); # テキストノードを作成
DOM属性->replaceChild(新DOMテキストノード,旧DOMテキストノード);
※appendChildを使うと既存の属性値の後に値が追記されてしまう。

(6)DOMAttrオブジェクトの新規作成DOMElement::setAttributeNode を使う。
DOM属性ノード = new DOMAttr(属性名,属性値); # 属性ノードを新規作成
DOM要素->setAttributeNode(DOM属性ノード); # 属性ノードを要素ノードに追加
※新規に属性を追加する手順と同じ。属性名で指定したキーを持つ属性が既に存在した場合は属性値のみが更新される。
	

属性を削除する方法は以下の通り。

(7)DOMElement::removeAttribute を使う。
DOM要素->removeAttribute(属性名);
※(1)〜(3)どの方法で作った属性に対しても使える。

(8)DOMElement::removeAttributeNode を使う。
DOM要素->removeAttributeNode(属性ノード);
※(2)では appendChild を使ったので、removeChild でも削除できる気がするがなぜかうまくいかない。
※方法(1)で作った属性の場合、一旦属性ノードを作成する必要があるので、(7)で削除する方が簡単。
DOM属性ノード = DOM要素->createAttributeNode(属性名);
	

事例

[test.php]
<?php
$dom = new DOMDocument('1.0','utf-8'); #- 新規DOM文書作成
$element = $dom->createElement('root','This is the root element.'); #- DOM文書に属する要素作成
$dom->appendChild($element); #- 要素をDOM文書に追加
#- 方法(1)で追加
$element->setAttribute('attr1','setAttribute'); #- 要素ノードに属性追加
#- 方法(2)で追加
$node_attr = $dom->createAttribute('attr2'); #- DOM文書に属する属性ノードを作成
$element->appendChild($node_attr); #- 属性ノードを追加
$text_attr = $dom->createTextNode('createAttribute'); #- DOM文書に属するテキストノードを作成
$node_attr->appendChild($text_attr); #- テキストノードを属性ノードに追加
#- 方法(3)で追加
$node_attr = new DOMAttr('attr3','setAttributeNode'); #- 新規属性ノードを作成
$element->setAttributeNode($node_attr); #- 属性ノードを要素ノードに追加
#- 追加結果確認
echo "== 追加結果 ==\n";
echo $dom->saveXML(); #- XML文書全体を保存し標準出力へ出力
#- 方法(4)で更新
$element->setAttribute('attr1','setAttribute2'); #- 要素ノードに属性追加
#- 方法(5)で更新
$text_attr2 = $dom->createTextNode('createAttribute2'); #- DOM文書に属するテキストノードを作成
$node_attr->replaceChild($text_attr2,$text_attr); #- 属性ノードの子要素であるテキストノードを置換
#- 方法(6)で更新
$node_attr = new DOMAttr('attr3','setAttributeNode2'); #- 新規属性ノードを作成
$element->setAttributeNode($node_attr); #- 属性ノードを要素ノードに追加
#- 更新結果確認
echo "== 更新結果 ==\n";
echo $dom->saveXML();
#- 方法(7)で削除
$element->removeAttribute('attr1'); #- 要素ノードから属性削除
#- 方法(7)による属性削除結果確認
echo "== 方法(7)による属性削除結果 ==\n";
echo $dom->saveXML();
#- 方法(8)で削除
$element->removeAttributeNode($node_attr2); #- 要素ノードから属性ノード削除
#- 方法(8)による属性削除結果確認
echo "== 方法(8)による属性削除結果 ==\n";
echo $dom->saveXML();
?>

$ php ./test.php
== 追加結果 ==
<?xml version="1.0" encoding="utf-8"?>
<root attr1="setAttribute" attr2="createAttribute" attr3="setAttributeNode">This is the root element.</root>
== 更新結果 ==
<?xml version="1.0" encoding="utf-8"?>
<root attr1="setAttribute2" attr2="createAttribute2" attr3="setAttributeNode2">This is the root element.</root>
== 方法(7)による属性削除結果 ==
<?xml version="1.0" encoding="utf-8"?>
<root attr2="createAttribute2" attr3="setAttributeNode2">This is the root element.</root>
== 方法(8)による属性削除結果 ==
<?xml version="1.0" encoding="utf-8"?>
<root attr3="setAttributeNode2">This is the root element.</root>
	

要素値・属性値を追加する

参照:DOMDocument::createTextNodeDOMNode::appendChild

XPathについて

「XPath」を使ってXML文書に対する問い合わせを行う場合、XML文書に対するXPathオブジェクトを作成した上で、XPathによる問い合わせを実行する。

1. XPathオブジェクトを作成(DOMXPath::__construct
【書式】
new DOMXPath(XMLオブジェクト);

【例】
$xpath = new DOMXPath($xml);
2. XPathクエリ発行(DOMXPath::query
【書式】
XPathオブジェクト->query(XPath問い合わせ文,基準ノード,基準ノード自動登録);
基準ノード
XPath問い合わせ文の起点となるノードを指定する。指定がない場合の既定値は最上位(root)要素。
基準ノード自動登録
基準ノードの自動登録を無効化する場合は false、そうでない場合は true を指定。指定がない場合の既定値は true。
【例】
$xmlnodes = $xpath->query('/datablock/citationCategory/citation[@id = "primary"]');

HTTP関係

HTTP通信について

Webページの内容(htmlコード)を取得する

fopenのファイル名にURLを指定する方法や、cURLを使う方法がある。

HTTP応答のCodeを取得する

HEADリクエストを発行し、返ってきた応答のhttp headerを確認すれば応答のcodeが分かる。これもページ内容を取得する場合と同等の方法が使える。

【fopenを使う方法】
$ cat test.php
<php

HTTPヘッダを生成する(header)

headerは生のHTTPヘッダを生成する。この関数を呼び出すタイミングは、あらゆる出力の前である必要がある。HTTP/1.1 の仕様詳細についてはこちら

【書式】
header(ヘッダ文字列,置換フラグ,httpレスポンスコード);
【戻り値】
なし
ヘッダ文字列

送信する HTTP ステータスコードを示すには、HTTP/で始まる文字列を指定する(例:HTTP/1.1 404 Not Found)。

例:
<?php
header("HTTP/1.1 404 Not Found");
...
?>
→apache のアクセスログでは
xxx.xxx.xxx.xxx - - [27/Jan/2012:10:00:00 +0900] "GET /index.php HTTP/1.1" 404 12345 - ...
のようになる。

リダイレクトをかけるには「Location:リダイレクト先URL」を指定する19

例:
<?php
header("Location: https://hoge.org/");
exit;
?>
置換フラグ
httpレスポンスコード
HTTP レスポンスコードを強制的に指定した値に設定する。この指定は「ヘッダ文字列」に空でない文字列を設定している場合にのみ有効。

ウェブページで開かず強制的にダウンロードさせる

[3]

配列変数からクエリ文字列を生成

http_build_queryは与えられた連想配列 (もしくは添字配列) から URL エンコードされたクエリ文字列を生成する。

【書式】
http_build_query(クエリデータ,数値プレフィックス [, string $numeric_prefix [, string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )

【戻り値】
(文字列型)URL エンコードされた文字列
クエリデータ
(混合型)元データとなる情報を含んだ配列またはオブジェクト。
数値プレフィックス
(文字列)クエリデータに指定した配列に数値インデックスを持つ要素が含まれている場合、この数値プレフィックスの指定を行うと、数値インデックスに対してのみ指定した文字列をインデックスの先頭に付加してURLを生成する。
セパレータ
(文字列)arg_separator.output が各キー・値セットを区切るためのセパレータとして使用されます(通常はアンパサンド?)。ただし、このパラメータが指定されていた場合はこちらが優先されます。
エンコードタイプ
データ型は「整数」と記載されているが、各指定に対応する値は不明。PHP_QUERY_RFC1738 またはPHP_QUERY_RFC3986 を指定する。
  • PHP_QUERY_RFC1738:(既定値)RFC 1738 に従ってエンコードされ、メディアタイプは application/x-www-form-urlencoded となる。スペースはプラス記号 (+) にエンコードされる。
  • PHP_QUERY_RFC3986:RFC 3986 に従ってエンコードされ、スペースはパーセント形式 (%20) となる。
【例】
$ cat test.php
<?php
$array = array('H'=>'Hydrogen','O'=>'Oxygen','1'=>'One','CO2'=>'Carbon Dioxide');
print_r($array);
echo http_build_query($array,'No','&')."\n";
echo http_build_query($array,'No','&',PHP_QUERY_RFC1738)."\n";
echo http_build_query($array,'No','&',PHP_QUERY_RFC3986);
?>
$ php test.php
Array
(
    [H] => Hydrogen
    [O] => Oxygen
    [1] => One
    [CO2] => Carbon Dioxide
)
H=Hydrogen&O=Oxygen&No1=One&CO2=Carbon+Dioxide
H=Hydrogen&O=Oxygen&No1=One&CO2=Carbon+Dioxide
H=Hydrogen&O=Oxygen&No1=One&CO2=Carbon%20Dioxide

フォーム関係

htmlのフォームで送信されたデータの参照方法について。

GET/POST

書式 内容
$_GET GETメソッドで送信されたデータの配列。キーはフォーム内要素のname属性値、値はキーに対応する値。
$_POST POSTメソッドで送信されたデータの配列。キーはフォーム内要素のname属性値、値はキーに対応する値。

ファイルのアップロードの準備

POSTメソッドを用いてファイルをサーバにアップロードする仕組みを構築する際、以下の点に注意が必要。

アップロードファイルのサイズ
送信元フォームの<input name="MAX_FILE_SIZE"/>でアップロード可能なファイルサイズの上限を規定できるが、この値はPHP設定ファイル(UNIX系OSの場合、既定では/etc/php.ini)中の「upload_max_filesize」の指定値を超えることはできない(既定は2M(B)、値は整数または K(キロ), M(メガ), G(ギガ)のいずれか一つを直後に記した整数)。
【設定例】100MBのファイルまでアップロードできるようにする
[/etc/php.ini]
upload_max_filesize = 2M
↓
upload_max_filesize = 100M
POSTデータサイズ
PHP設定ファイル(/etc/php.ini)の「post_max_size」の指定値を超えることはできない(既定は8M(B))。upload_max_filesize 以上の値に設定しておく。
【設定例】250MBのデータまでPOSTできるようにする
[/etc/php.ini]
post_max_size = 8M
↓
post_max_size = 250M
スクリプト実行時間の最大値
スクリプト実行時間の最大値はPHP設定ファイル(/etc/php.ini)の「max_execution_time」で設定されている(既定値は30(秒))が、この時間が短すぎるとアップロードが終わる前にタイムアウトしてしまう。
入力時間の最大値
スクリプトで入力を受け付けることができる最大時間はPHP設定ファイル(/etc/php.ini)の「max_execution_time」で設定されている(既定値は60(秒))が、この時間が短すぎるとアップロードが終わる前にタイムアウトしてしまう。
formのenctype設定
ファイル送信元のhtml form要素のenctype属性値は「multipart/form-data」に設定しておくこと。
【例】
<form enctype="multipart/form-data"
      method="post"
      action="nantoka.php">
...

ファイルのアップロードに関する情報参照

フォームで送られてきたファイルデータや情報は $_FILESスーパーグローバル変数(スクリプト全体で全てのスコープにおいて使用できる変数)に格納される(PHP 4.1.0以降)。第1キーはフォーム内要素のname属性値。第2キーの内容および対応する値は以下の通り。

第2キー 内容
name ウェブクライアント側での元のファイル名
type ウェブクライアント(ブラウザ)が通知してきたファイルのMIMEタイプ
size アップロードされたファイルのバイト単位のファイルサイズ
tmp_name アップロードされたファイルのサーバ上での一時ファイル名
error ファイルアップロードに関するエラーコード(PHP 4.2.0以降)。正常であれば 0。

アップロードされたファイルはサーバ既定の一時ディレクトリに保存される。このファイルを移動させるにはmove_uploaded_file関数を用いる。

【書式】
move_uploaded_file(アップロードファイル名,移動後のファイル名);
【戻り値】
成功→true
PHPでアップロードされた有効なファイルではない→false
PHPでアップロードされた有効なファイルだが、移動に失敗した場合→false(あわせて警告が出力される)
アップロードファイル名
PHPでアップロードされた一時ファイルのフルパス。直接値で指定してもいいが、$_FILES[キー]['tmp_file']変数を参照するのが便利。
アップロードファイル名
移動後のファイル名
移動先となるパス・ファイル名。

なお、同名のファイルが既に存在した場合は上書きされる。

【例】
<form enctype="multipart/form-data" action="PHPスクリプトのURL" method="POST">
    <!-- MAX_FILE_SIZE は、必ず "file" input フィールドより前に置く -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- input 要素の name 属性の値が、$_FILES 配列の第1キーになる -->
    このファイルをアップロード: <input name="userfile" type="file" />
    <input type="submit" value="ファイルを送信" />
</form>

一時ファイルがHTTP POSTでアップロードされたものであるかどうかを調べるにはis_uploaded_fileを用いる。

【書式】
is_uploaded_file(ファイル名);
【戻り値】
HTTP POSTによりアップロードされたファイル→true
そうでない場合→false
ファイル名
検査対象とするファイルのフルパス。

セッション関係

セッション管理を使って、あるページを通ってこないと目的のページに到達できないようにすることができる(例:利用許諾に同意しないとダウンロードページを表示できないようにする)。

【例】
session_start();
if (empty($_SESSION['urlachecked'])) {
   $_SESSION['urlachecked'] = true;
   echo '<p>ようおこし</p>'."\n";
   echo '<a href="'.$_SERVER['SCRIPT_NAME'].'">次はこちらへどうぞ</a>'."\n";
} else if ($_SESSION['urlachecked']) {
   echo '<p>よくぞここまできた! あっぱれじゃ!</p>'."\n";
}
session_write_close();

情報取得

PHPのバージョン

phpversionは現在動作中の PHP パーサあるいは拡張モジュールのバージョンを表す文字列を返す。サブモジュールを指定しない場合は、PHPパーサ本体のバージョンを返す。指定した場合、そのサブモジュールが有効でバージョン情報があればその情報を、そうでなければ false を返す。

【書式】
phpversion(サブモジュール名); 

【例】
echo phpversion(); #→ 5.1.6
      

ホスト名

PHP 5.3からは gethostname でホスト名が取得できる。

[gethostname53.php]
<?php
echo gethostname();
?>

$ hostname
myserver
$ php gethostname53.php
myserver
      

PHP 5.3より前(PHP 4.0.2以降、およびPHP 5)では php_uname でホスト名が取得できる。

【書式】
php_uname(モード)
      

モード

's'
オペレーティングシステム名。 例: Linux
'n'
ホスト名。 例: www.foo.org
'r'
リリース名。 例: 2.6.18-164.15.1.el5
'v'
バージョン名。 例: #1 SMP Mon Mar 1 10:56:08 EST 2010
'm'
マシンのアーキテクチャタイプ。 例: x86_64
'a'
上記全モードを"s n r v m" の順で返す。
[gethostname.php]
<?php
echo php_uname('n');
?>

$ hostname
myserver
$ php gethostname.php
myserver
      

PHP各種設定

php -i コマンドでPHPの各種設定情報をみることができる。php -r "echo phpinfo();"と同じ。

画像関係

画像のサイズを取得

getimagesizeコマンドにより画像の縦横ピクセル数などの情報が得られる。この関数で得られる情報をHTMLのimgタグやHTTPのcotent typeとして利用することができる。

なお、この関数は適切な画像ファイルかどうかの判定は行わない。仮に画像ファイルでなくても関数処理は成功するかもしれないが、返る値には意味のない値が含まれる可能性がある。画像ファイルかどうかを判定するにはFileinfo拡張モジュールを使うのがよいとのこと。

【書式】
getimagesize(ファイル名);

【引数】
ファイル名:文字列
情報を取得したいファイルのファイル名。    

【戻り値】
成功:最大7つの要素を持つ配列、失敗:FALSE(指定したファイルにアクセスできない、読み込み時にエラーが発生したなど)
key: 値
0: 画像の幅(ピクセル数)
1: 画像の高さ(ピクセル数)
2: IMAGETYPE_XXX constants 定数のひとつで、 画像の形式を表す値。
3: imgタグで直接利用できる文字列(例:width="200" height="283")
bits: 個々の色のビット数。アニメーションGIFなど画像の形式によっては正しい値を表示できないことがあることに注意。
mime: 画像のMIMEタイプ。この情報は画像とともに正しい HTTP Content-type ヘッダを転送するために使える。
channels: RGB画像は3、CMYK画像の場合は4。アニメーションGIFなど画像の形式によっては正しい値を表示できないことがあることに注意。

【例】
$ php -r "print_r(getimagesize('hoge.png'));"
Array
(
    [0] => 1819
    [1] => 2573
    [2] => 3
    [3] => width="1819" height="2573"
    [bits] => 8
    [mime] => image/png
)

コマンドラインからの実行

概要

PHPスクリプトをコマンドラインから実行するには、(1)php コマンドの引数としてPHPスクリプトファイルを指定する (2) phpスクリプトファイルを実行可能にして実行する (3)php -r 'phpスクリプト'の形で直接phpコードを記述、という方法がある。

【例】sample.phpを実行する(UNIX系OSの場合)
shell> ls -l sample.php
-rwxrwxr--   1 user  user  1234 11 30 09:00 sample.php ←実行権限(x)があればOK(但し、現在のユーザに権限があること)
↑この場合、ユーザuserまたはグループuserに属するユーザのみ実行権限あり
↓権限を追加する必要がある場合は
shell> chmod +x sample.php
↓実行するにはファイル名を指定するだけでOK
shell> ./sample.php
    

直接コマンドライン上にコードを記述する

ちょっとした処理の確認ならコマンドラインで直接書いた方が便利かも。

【書式】
php -r 'PHPコード'
【例】
shell> php -r 'echo "hogehoge";'
hogehoge
    

引数の指定と参照

コマンドライン引数を指定し、スクリプト内で参照するには$argvphp.iniregister_argc_argvの値をTRUEに設定している場合に利用可能、そうでない場合でも$_SERVER['argv']で参照可能)は各引数を要素に持つ配列、$argc$_SERVER['argc'])は$argvの配列要素数を持つ。$argv[0]はスクリプトファイル名(入力元が標準入力または-rオプションを使ってコマンドライン上に直接コードを指定した場合は-)が格納される。

shell> cat test.php
#!/usr/bin/php
<?php
var_dump($argv);
var_dump($argc);
?>
shell> php test.php hoge fuga
array(3) {
  [0]=>
  string(10) "./test.php"
  [1]=>
  string(4) "hoge"
  [2]=>
  string(4) "fuga"
}
int(3)
※実行権限を与えてあれば以下のようにスクリプトファイルを実行しても同じ
shell> ./test.php hoge fuga

入力元が標準入力の場合、または-rオプションを使って直接コードを記述した場合
shell> php -r 'var_dump($argv);'
array(1) {
  [0]=>
  string(1) "-"
}
shell> php -r 'var_dump($argv);' hoge fuga
array(3) {
  [0]=>
  string(1) "-"
  [1]=>
  string(4) "hoge"
  [2]=>
  string(4) "fuga"
}
    

引数の先頭文字が - の場合、PHPの実行オプションと解釈されるため意図しない実行結果となりうる。それを防ぐには引数群の前に引数リストセパレータ -- を置く必要がある

"-h"オプションが指定されたと解釈され、ヘルプが表示されてしまう
shell> php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [--] [args...]
       php [options] -r <code> [--] [args...]
       php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
       php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
       php [options] -- [args...]
       php [options] -a

  -a               Run interactively
...
"--"以降は引数と解釈される
shell> php -r 'var_dump($argv);' -- -h
array(2) {
  [0]=>
  string(1) "-"
  [1]=>
  string(2) "-h"
}
    

標準入力からの入力

引数に「`cat -`」を指定すればよい。

$ which php
/usr/bin/php
$ cat test.php
<?php
echo var_dump($argv);
?>
$ php 2513.php `cat -`
hoge
(Ctrl+D)
array(2) {
  [0]=>
  string(8) "2513.php"
  [1]=>
  string(4) "hoge"
}

事例集

複数のテキストファイルを連結

複数のhtmlファイル(header.htmlmain.htmlfooter.html)を連結して表示させる例(linked.php)。

header.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<title>test>/title>
</head>

<body>
<h1>test</h1>
	
main.html
<ul>
<li>東京</li>
<li>新横浜</li>
<li>小田原</li>
<li>熱海</li>
<li>三島</li>
<li>新富士</li>
<li>静岡</li>
<li>掛川</li>
<li>浜松</li>
<li>豊橋</li>
<li>三河安城</li>
<li>名古屋</li>
<li>岐阜羽島</li>
<li>米原</li>
<li>京都</li>
<li>新大阪</li>
</ul>
	
footer.html
<div>
Thank you for taking the Nozomi superexpress bound for Shin-Osaka.
</div>
	
linked.php
<?php
echo file_get_contents('header.html');
echo file_get_contents('main.html');
echo file_get_contents('footer.html');
?>
	

結果:

test

  • 東京
  • 新横浜
  • 小田原
  • 熱海
  • 三島
  • 新富士
  • 静岡
  • 掛川
  • 浜松
  • 豊橋
  • 三河安城
  • 名古屋
  • 岐阜羽島
  • 米原
  • 京都
  • 新大阪
Thank you for taking the Nozomi superexpress bound for Shin-Osaka.

URL引数を含むスクリプト名の取得

【例】http://www.hoge.com/index.php?y=2009&m=Jul
$getstr = "?";
$keys = array_keys($_GET);
foreach ($keys as $key) {
  $getstr .= $key . "=" . $_GET[$key];  
}
$getstr = substr($getstr,0, -5); ←最後のアンパサンドを削除

echo $_SERVER['SERVER_NAME']; ← www.hoge.com
echo $_SERVER['PHP_SELF']; ← index.php
echo $getstr; ← ?y=2009&m=Jul
    

エラー

unexpected T_IF

IFの前の行の最後のセミコロンが抜けているか、コメントアウト記号の#の前に空けていく空白に全角空白が使われている。

Parse error: syntax error, unexpected T_IF in (ローカルパス)on line (行番号)

参考サイト:unexpected T_IF? | studyasusual:日々の勉強メモ

unexpected T_ELSE

前項同様か。

PHPのRPMパッケージビルド時PDO関係のエラーで失敗

PHP5.4.19のRPMパッケージをビルドしようとしたが、以下のエラーによりビルド失敗。

make: *** [ext/pdo_sqlite/pdo_sqlite.lo] Error 1
make: *** [ext/pdo_sqlite/sqlite_driver.lo] Error 1
make: *** [ext/pdo_sqlite/sqlite_statement.lo] Error 1

エラーの出始め部分を見ると、「pdo/php_pdo.h、pdo/php_pdo_driver.h というファイルがない」というメッセージ。元のコンテンツのバックアップを取ってから、該当ファイル「php-5.4.19/ext/pdo_sqlite/{pdo_sqlite.c,sqlite_driver.c,sqlite_statement.c}」に以下の変更を適用。

[root@server ~]# cd /usr/src/redhat/SOURCES
[root@server SOURCES]# mv php-5.4.19 php-5.4.19_orig
[root@server SOURCES]# vim php-5.4.19/ext/pdo_sqlite/pdo_sqlite.c
# 以下の修正を適用、sqlite_driver.c、sqlite_statement.cも同様
#include "pdo/php_pdo.h"
#include "pdo/php_pdo_driver.h"
↓
#include "ext/pdo/php_pdo.h"
#include "ext/pdo/php_pdo_driver.h"

パッチファイルを作成[3]。そのパッチを適用するようSPECファイルを修正。これでbuildできた。

[root@server SOURCES]# diff -ru php-5.4.19_orig php-5.4.19 >php-5.4.19-1.patch
[root@server SOURCES]# cat php-5.4.19-1.patch こちらにUploadしています(但し拡張子は.txtに変更)
diff -ru php-5.4.19/ext/pdo_sqlite/pdo_sqlite.c php-5.4.19p/ext/pdo_sqlite/pdo_sqlite.c
--- php-5.4.19/ext/pdo_sqlite/pdo_sqlite.c	2013-08-20 13:42:41.000000000 +0900
+++ php-5.4.19p/ext/pdo_sqlite/pdo_sqlite.c	2013-08-29 10:59:02.000000000 +0900
@@ -25,8 +25,8 @@
 #include "php.h"
 #include "php_ini.h"
 #include "ext/standard/info.h"
-#include "pdo/php_pdo.h"
-#include "pdo/php_pdo_driver.h"
+#include "ext/pdo/php_pdo.h"
+#include "ext/pdo/php_pdo_driver.h"
 #include "php_pdo_sqlite.h"
 #include "php_pdo_sqlite_int.h"
 #include "zend_exceptions.h"
diff -ru php-5.4.19/ext/pdo_sqlite/sqlite_driver.c php-5.4.19p/ext/pdo_sqlite/sqlite_driver.c
--- php-5.4.19/ext/pdo_sqlite/sqlite_driver.c	2013-08-20 13:42:41.000000000 +0900
+++ php-5.4.19p/ext/pdo_sqlite/sqlite_driver.c	2013-08-29 11:08:16.000000000 +0900
@@ -25,8 +25,8 @@
 #include "php.h"
 #include "php_ini.h"
 #include "ext/standard/info.h"
-#include "pdo/php_pdo.h"
-#include "pdo/php_pdo_driver.h"
+#include "ext/pdo/php_pdo.h"
+#include "ext/pdo/php_pdo_driver.h"
 #include "php_pdo_sqlite.h"
 #include "php_pdo_sqlite_int.h"
 #include "zend_exceptions.h"
diff -ru php-5.4.19/ext/pdo_sqlite/sqlite_statement.c php-5.4.19p/ext/pdo_sqlite/sqlite_statement.c
--- php-5.4.19/ext/pdo_sqlite/sqlite_statement.c	2013-08-20 13:42:41.000000000 +0900
+++ php-5.4.19p/ext/pdo_sqlite/sqlite_statement.c	2013-08-29 11:19:57.000000000 +0900
@@ -25,8 +25,8 @@
 #include "php.h"
 #include "php_ini.h"
 #include "ext/standard/info.h"
-#include "pdo/php_pdo.h"
-#include "pdo/php_pdo_driver.h"
+#include "ext/pdo/php_pdo.h"
+#include "ext/pdo/php_pdo_driver.h"
 #include "php_pdo_sqlite.h"
 #include "php_pdo_sqlite_int.h"
[root@server SOURCES]# vim ../SPECS/php.spec
# 以下の修正を適用
...
URL: http://www.php.net/
Packager: PHP Group <group@php.net>
Patch0: php-5.4.19-1.patch ←追記
...
%prep
rm -rf ${RPM_BUILD_ROOT}
mkdir -p ${RPM_BUILD_ROOT}
%setup
%patch0 -p1 ←追記
%build
./configure ...

PHP省略タグ有効化に伴う弊害

PHP(7.1.0)の既定設定では、PHPコードの開始タグ <?php の省略形 <? が有効になっている。このままだと静的なxhtmlファイルの冒頭に記述される <?xml version="1.0"?> などがphp開始タグとして認識されてしまい、phpコードエラーを起こしてしまう。これを防ぐにはPHP設定ファイル(/etc/php.iniなど)に以下の記述を行って省略タグを無効にする[4]

short_open_tag = Off

MySQL関係

MySQLについてはこちらも参照のこと

データベース作成

1回作れば良い。これはわざわざPHPを介さず直接コマンドラインでやってしまうのが簡単。

shell> mysql -umysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 34
Server version: 5.0.67 MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> create database test2;
    

テーブル作成・構造定義

CSVデータによる一括データ登録

新規レコード追加

個別データ更新

レコード数取得

【例】
$link = mysql_connect('localhost', 'mysql') ←MySQLに接続
=== 接続に成功した場合 ===
if ($link !== false) {
$db_selected = mysql_select_db('データベース名,$link); データベース選択
=== データベース選択に成功した場合 ===
if($db_selected !== false) {
$count_resource = mysql_query("SELECT COUNT(*) from テーブル名"); レコード数を数えるクエリ文を送信
$count = mysql_fetch_array($count_resource); 結果を配列として取得
}
=== データベース選択に成功した場合おわり ===
mysql_close($link); MySQL接続を切断
}
=== 接続に成功した場合おわり ===
echo "レコード数は " . $count[0] . " です。"; $countの1つ目(0番目)の要素を参照

【結果例】
レコード数は 100 です。
    

参考文献・サイト:

データ一覧表示