$str = preg_replace('/\s+/', ' ', $str); // 連続するスペースを1つにする
<?php
$str = 'barking_cat';
if (function_exists($str)) {
$str(); // 出力 → ウオーン
} else {
echo "関数は存在せず";
}
function barking_cat(){
echo 'ウオーン<br>';
}
?>
<?php
$className = 'DogClass';
$methodName = "bark";
if (method_exists($className, $methodName)) {
echo "メソッド実行可<br>";
$obj = new $className;
$obj->$methodName(); // 出力→フォンフォン
} else {
echo "メソッドは使用できません。";
}
class DogClass{
function bark(){
echo 'フォンフォン';
}
}
?>
/**
* 拡張URLエンコード
*
* @note
* 多次元配列に対応
* 高速化のため、引数は参照(ポインタ)であり返値もかねている。
*
* @param any $data URLエンコード対象データ(参照型) | 値および配列を指定
* @return void
*/
protected function urlencodeEx(&$data){
if(is_array($data)){
foreach($data as &$val){
$this->urlencodeEx($val);
}
unset($val);
}elseif(gettype($data)=='string'){
$data = urlencode($data);// URLエンコード
}else{
// 何もしない
}
}
* CSV用データに変換
*
* @note
* 文字列データはダブルクォートで括る
* 多次元配列に対応
* 高速化のため、引数は参照(ポインタ)であり返値もかねている。
*
* @param array $data データ
* @return array CSV用のデータ
*/
protected function convToCsvData(&$data){
if(is_array($data)){
foreach($data as &$val){
$this->convToCsvData($val);
}
unset($val);
}elseif(gettype($data)=='string'){
$data = str_replace($data,'"','""');
$data = '"' . $data .'"';
}else{
// 何もしない
}
}
/**
* CSV読込
*
* @note
* 当サーバー上に配置してあるCSVファイルからデータを読み込む。
* ダブルクォートの括り内に存在する改行やコンマにも対応している。
*
* @version 4.1
* @date 2011-9-26 | 2017-7-4
*
* @param array $csv_fp CSVファイルパス
* @param array $delim 区分記号: 「,」や「¥t」を指定する。デフォルトは「,」。
* @param array $sjis_flg Shift-JISフラグ: true(デフォルト):Shift-JISからUTF8に変換
*
* @return array CSVデータ配列
* @throw エラーメッセージ
*/
public function load($csv_fp,$delim=',',$sjis_flg=true){
if(!file_exists($csv_fp) || !is_readable($csv_fp)){
throw new Error('There is no csv file!');
}
$data = array();
// Shift-JIS形式のCSVである場合
if($sjis_flg){
// CSVファイルをUTF8に書き換える
$buffer = mb_convert_encoding(file_get_contents($csv_fp), "UTF-8", "SJIS");
$csv_fp= tmpfile();
fwrite($csv_fp, $buffer);
rewind($csv_fp);
$header = NULL;
while (($row = fgetcsv($csv_fp, 0, $delim)) !== FALSE) {
if(!$header){
$header = $row;
}else{
$data[] = array_combine($header, $row);
}
}
fclose($csv_fp);
}
// UTF8形式のCSVである場合
else{
$header = NULL;
if (($handle = fopen($csv_fp, 'r')) !== FALSE)
{
while (($row = fgetcsv($handle, 1000, $delim)) !== FALSE)
{
if(!$header){
$header = $row;
}else{
$data[] = array_combine($header, $row);
}
}
fclose($handle);
}
}
return $data;
}
/**
* CSVテキストを2次元配列に変換する
* @note
* ExcelのCSVに対応
* ダブルクォート内の改行に対応
* 「""」エスケープに対応
*
* @param string $csv_text CSVテキスト
* @returns array 2次元配列
*/
private function csvTextToData($csv_text){
if($csv_text=='' || $csv_text==null) return null;
$ary = preg_split("//u", $csv_text, -1, PREG_SPLIT_NO_EMPTY);
// CSVテキストの末尾が改行でないければ改行を付け足す。
$csv_text_len = count($ary);
$last = $ary[$csv_text_len - 1];
if(preg_match("/¥r|¥n/", $last)){
$ary[] = "¥n";
}
$data = [];
$len = count($ary);
$enclose = 0; // ダブルクォート囲み状態フラグ 0:囲まれていない , 1:囲まれている
$cell = '';
$row = [];
for($i=0; $i<$len; $i++){
$one = $ary[$i];
// ダブルクォートで囲まれていない
if($enclose == 0){
if($one == '"'){
$enclose = 1; // 囲み状態にする
}
else if($one == ','){
$row[] = $cell;
$cell = '';
}
else if(preg_match("/¥r|¥n/", $one)){
$row[] = $cell;
$data[] = $row;
$cell = '';
$row = [];
// 次も改行文字ならインデックスを飛ばす
if($i < $len - 1){
$ns = $ary[$i+1];
if(preg_match("/¥r|¥n/", $ns)){
$i++;
}
}
}else{
$cell .= $one;
}
}
// ダブルクォートで囲まれている
else{
if($one == '"'){
if($i < $len - 1){
$s2 = $one . $ary[$i + 1]; // 2文字分を取得
// 2文字が「""」であるなら、一つの「"」とみなす。
if($s2 == '""'){
$cell .= '"';
$i++;
}else{
$enclose = 0; // 囲み状態を解除する
}
}
}
else{
$cell .= $one;
}
}
}
return $data;
}
$data = [
'"98","沖縄に生息するイモリ","TEST"',
'99,abc',
'100,シリケンイモリ,"沖縄に生息するイモリ"',
'100,シリケンイモリ,"沖縄に生息する,イモリ"',
'101,シリケンイモリ,"沖縄に生息するイモリ',
'101,シリケンイモリ,"沖縄に生息するイモリ,',
'102,シリケンイモリ,"沖縄に生息する',
'103,シリケンイモリ,"',
'104,シリケンイモリ,',
'104,シリケンイモリ,,',
'105,シリケンイモリ,"沖縄に""生息""するイモリ"',
'106,シリケンイモリ,"沖縄に""生息""する',
'107,シリケンイモリ,"""沖縄""に生息する,""イモリ"""',
'107,シリケンイモリ, """沖縄""に生息する,""イモリ"""',
'"イモリ"',
'"イモ',
'"',
'""""',
'"""',
'"シリケン","""',
'107,シリケンイモリ,"沖縄',
'に""生息""',
'するイモリ"',
'イモリ",',
];
echo "<table class='tbl2'><thead><tr><th>CSVの行</th><th>判定</th></tr></thead><tbody>";
foreach($data as $csv_line){
$msg = "<span class='text-success'>OK</span>";
if(idDuringLineFeed($csv_line)){
$msg = "<span class='text-danger'>改行中です</span>";
}
echo "<tr><td>{$csv_line}</td><td>{$msg}</td></tr>";
}
echo "</tbody></table>";
/**
* CSVの行が改行中であるか判定する
* @param string $csv_line CSVの行
* @return true:改行中の行である
*/
function idDuringLineFeed($csv_line){
if(empty($csv_line)) return false;
$csv_line = trim($csv_line); // スペースだけでなく末尾の改行を除く
$ary = preg_split("//u", $csv_line, -1, PREG_SPLIT_NO_EMPTY);
$state = 0; // 0:初期状態, 1:通常状態, 2:ダブルクォート監視状態, 3:ダブルクォート内状態
$dq_flg = 0; // 連続ダブルクォートフラグ ダブルクォート内状態においてダブルクォートが連続するときONになる。
$len = count($ary); // 文字数を取得する
foreach($ary as $i => $one){
// 文字が「,」である場合、
if($one == ','){
// 初期状態
switch ($state){
case 0: // 初期状態
$state = 1; // 通常状態にする
break;
case 1: // 通常状態
$state = 2; // ダブルクォート監視状態にする。
break;
case 2: // ダブルクォート監視状態
break;
case 3: // ダブルクォート内状態
break;
}
}
// 文字が半角スペースである場合
elseif($one == ' '){
switch ($state){
case 0: // 初期状態
$state = 1; // 通常状態にする
break;
case 1: // 通常状態
break;
case 2: // ダブルクォート監視状態
break;
case 3: // ダブルクォート内状態
break;
}
}
// 文字が「"」である場合
elseif($one == '"'){
switch ($state){
case 0: // 初期状態
$state = 3; // ダブルクォート内状態
break;
case 1: // 通常状態
break;
case 2: // ダブルクォート監視状態
$state = 3; // ダブルクォート内状態
break;
case 3: // ダブルクォート内状態
if($dq_flg == 1){
$dq_flg = 0; // 連続ダブルクォート状態を解除
break;
}
// 次の文字はない
if($i == $len-1){
$state = 1; // 通常状態にする
break;
}
// 次の文字はダブルクォートか?
$next = $ary[$i + 1];
if($next == '"'){
$dq_flg = 1; // 連続ダブルクォート状態にする
break;
}
// 次以降に最初に現れる文字は「,」か?(スペースは飛ばす)
for($i2=$i+1; $i2<$len; $i2++){
$nnext = $ary[$i2];
if($nnext == ','){
$state = 1; // 通常状態にする
break;
}elseif($nnext == ' '){
continue;
}else{
break;
}
}
break;
}
}
// その他の文字である場合
else{
switch ($state){
case 0: // 初期状態
$state = 1; // 通常状態にする
break;
case 1: // 通常状態
break;
case 2: // ダブルクォート監視状態
$state = 1; // 通常状態にする
break;
case 3: // ダブルクォート内状態
break;
}
}
$prev_state = $state;
} // ループ終わり
$flg = false;
// ダブルクォート状態のまま担っている場合、「改行中」という判断を下す。
if($state == 3){
$flg = true;
}
return $flg;
}
出力
CSVの行 | 判定 |
---|---|
"98","沖縄に生息するイモリ","TEST" | OK |
99,abc | OK |
100,シリケンイモリ,"沖縄に生息するイモリ" | OK |
100,シリケンイモリ,"沖縄に生息する,イモリ" | OK |
101,シリケンイモリ,"沖縄に生息するイモリ | 改行中です |
101,シリケンイモリ,"沖縄に生息するイモリ, | 改行中です |
102,シリケンイモリ,"沖縄に生息する | 改行中です |
103,シリケンイモリ," | 改行中です |
104,シリケンイモリ, | OK |
104,シリケンイモリ,, | OK |
105,シリケンイモリ,"沖縄に""生息""するイモリ" | OK |
106,シリケンイモリ,"沖縄に""生息""する | 改行中です |
107,シリケンイモリ,"""沖縄""に生息する,""イモリ""" | OK |
107,シリケンイモリ, """沖縄""に生息する,""イモリ""" | OK |
"イモリ" | OK |
"イモ | 改行中です |
" | 改行中です |
"""" | OK |
""" | 改行中です |
"シリケン",""" | 改行中です |
107,シリケンイモリ,"沖縄 | 改行中です |
に""生息"" | OK |
するイモリ" | OK |
イモリ", | OK |
検証0
$str0 = "echo 'マンモス'; ";
eval($str0);
出力
マンモス
検証1
eval実行する文字列にPHPコードやHTMLコードが混在している場合。
$str = "動物名:<?php echo 'アフリカゾウ'; ?><hr>";
eval(' ?>'.$str.'<?php ');
出力
動物名:アフリカゾウ
検証2
evalの外で宣言している変数をeval内で実行する
$animal_name= 'インド象';
$str2 = "動物名:<?php echo ¥$animal_name; ?><br>";
eval(' ?>'.$str2.'<?php ');
出力
動物名:インド象
検証2.1
evalで実行する文字列を「"」で括った場合と、「'」で括った場合を検証する。
$animal_name= 'インド象';
$str2 = "動物名:<?php echo ¥$animal_name; ?><br>";
eval(' ?>'.$str2.'<?php ');
$str2 = '動物名:<?php echo $animal_name; ?><hr>';
eval(' ?>'.$str2.'<?php ');
出力
動物名:インド象 動物名:インド象
検証3
eval内で宣言されている変数を、eval外で参照してみる。
$str3 = "<?php ¥$nauman='ナウマンゾウ<hr>'; ?>";
eval(' ?>'.$str3.'<?php ');
echo $nauman;
出力
ナウマンゾウ
検証4
eval内でエラーが起きたときのエラー情報をキャッチする。
<?php
$str4 = "
<?php
¥$a='大きな';
¥$b='ゾウは';
¥$c= 10 / 0; // ワザとエラーにする。
¥$d='m あります。';
echo ¥$a . ¥$b . ¥$c . ¥$d;
?>
";
echo $str4;
$response = @eval(' ?>'.$str4.'<?php ');
if (error_get_last()){
echo '<div style="color:red">eval内のエラーです<br>';
print_r(error_get_last());
echo '</div>';
}
?>
出力
大きなゾウはm あります。 eval内のエラーです Array ( [type] => 2 [message] => Division by zero [file] => C:\xampp\htdocs\sample\php\a020\eval_demo\eval_demo.php(133) : eval()'d code [line] => 5 )
$outErr = error_get_last(); // 外部エラーをあらかじめ取得しておく
$str4 = "
<?php
\$a='大きな';
\$b='ゾウは';
\$c= 10 / 0; // ワザとエラーにする。
\$d='m あります。';
echo \$a . \$b . \$c . \$d;
?>
";
echo $str4;
$response = @eval(' ?>'.$str4.'<?php ');
$err = error_get_last();
if ($err){
if(empty($outErr)){
echo '<div style="color:red">eval内のエラーです<br>';
print_r(error_get_last());
echo '</div>';
}else{
// 外部エラーと現在のエラーが一致する場合、現在のエラーは外部エラーである。そのためエラー出力は行わない。
if($outErr['type'] == $err['type'] && $outErr['line'] == $err['line']){
}else{
echo '<div style="color:red">eval内のエラーです<br>';
print_r(error_get_last());
echo '</div>';
}
}
}
検証1
// 正常なパターン:グローバル変数が表示される
$a = 'オオムラサキ';
test1();
function test1(){
global $a;
echo $a; // → オオムラサキ
}
検証2
// globalを使わないとエラーになる。
$a = 'オオムラサキ';
test1();
function test1(){
echo $a; // → エラー
}
検証3
// 関数内の変数をglobalすると空になる。
test1();
function test1(){
$a = 'オオムラサキ';
global $a;
echo $a; // → 空値になる
}
検証4
// 関数内の変数からglobalを除去すると空にならない。
test1();
function test1(){
$a = 'オオムラサキ';
$a;
echo $a; // → オオムラサキ
}
パスの末尾にスラッシュがなければ追加
/**
* パスの末尾にスラッシュがなければ追加。
*
* @param string $path パス
* @param $sep セパレータ: デフォルトは「/」である。「¥」を指定することも可能。
* @return 末尾にスラッシュを付加したパス
*
*/
private function addSlashToPathEnd($path,$sep='/'){
if(empty($path)){
return $path;
}
$end_str = mb_substr($path,-1);
if($end_str== $sep){
return $path;
}
$path .= $sep;
return $path;
}
パスの末尾にスラッシュがあれば削除
/**
* パスの末尾にスラッシュがあれば削除
*
* @param string $path パス
* @param $sep セパレータ: デフォルトは「/」である。「¥」を指定することも可能。
* @return 末尾からスラッシュを削除したパス
*
*/
private function removeSlashToPathEnd($path,$sep='/'){
if(empty($path)){
return $path;
}
$end_str = mb_substr($path,-1);
if($end_str != $sep){
return $path;
}
$path = mb_substr($path,0,mb_strlen($path)-1);// 末尾の一文字を削る
return $path;
}
/**
* ファイルアップロード情報からXMLパース形式のデータを取得する
*
* @param string $xmlFp XMLファイルパス
* @return array XMLパース形式のデータ
*/
private function getDataFromXml($xmlFp){
$res = array(
'err_msg' => '',
'data' => $data
);
$xmlData = simplexml_load_file($xmlFp);
if(!empty($xmlData)){
$res['data'] = json_decode(json_encode($xmlData), true);
}else{
$res['res_msg'] = 'XMLデータの読込に失敗、もしくはXMLが空です。';
}
return $res;
}
require_once 'JAX.php';
// 配列データのサンプル
$data = array(
'id' => 99,
'name' => '赤猫',
'option' => array(
'age'=>0,
'date'=>'2017-5-1'
)
);
var_dump($data);
// 配列データからXMLテキストに変換する
$jax = new JAX();
$xml_fp = 'test1.xml';
$xml_text = $jax->array2xml('cat',$data);
var_dump($xml_text);
// XMLテキストから配列データに変換する。
$data2 = @$jax->xml2array($xml_text);
var_dump($data2);
出力
array (size=3) 'id' => int 99 'name' => string '赤猫' (length=6) 'option' => array (size=2) 'age' => int 0 'date' => string '2017-5-1' (length=8)
string '<?xml version="1.0"?>
<cat><id>99</id><name>赤猫</name><option><age>0</age><date>2017-5-1</date></option></cat>
' (length=124)
array (size=3) 'id' => string '99' (length=2) 'name' => string '赤猫' (length=6) 'option' => array (size=2) 'age' => string '0' (length=1) 'date' => string '2017-5-1' (length=8)