連続するスペースを一つにする

	$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エンコード


	/**
	 * 拡張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用データに変換


	 * 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ファイルを読み込み配列データに格納する


	/**
	 * 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


	/**
	 * 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;
	}
	

CSVの行が改行中であるか判定する


$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,abcOK
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

evalの使い方

検証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 )
	



Eval実行する際、外部エラーが表示されることがあるので注意


	$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>';
			}
		}
	}
	


globalの検証

検証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ファイルを読み込んでパースする | simplexml_load_file


	/**
	 * ファイルアップロード情報から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;

	}
	


JAX.phpでXMLと配列データを相互変換する

公式サイト

デモ


		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>&#x8D64;&#x732B;</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)