PHP

【PHP】SJISからUTF8に文字コード変換する際の文字化けを防ぐ。

Excelで生成したCSVファイルをPHPで取り込む際、下記のようにSJISからUTF8の文字コード変換を行うが、その際「チルダ」や「全角ハイフン」が正しく認識されない事がある。

$str = mb_convert_encoding($str, mb_internal_encoding(), 'SJIS');

そのため、mb_convert_encoding()第3引数のfrom_encodingを下記のように指定してやる必要がある。

$str = mb_convert_encoding($str, mb_internal_encoding(), 'SJIS-WIN');

上記の通り文字コードを指定した結果、文字化けは綺麗に解消された。

nbsp;

【CakePHP2.4】find()で複数のOR条件をANDで結合したいときの書き方。

めも。

$conditions = array(
	$this->alias.'.col1' => 'value_1',
	$this->alias.'.col2' => 'value_2',
	
	'OR' => array(
		array($this->alias.'.col3 LIKE' => '%value_3%'),
		array($this->alias.'.col3 LIKE' => '%value_4%'),
	),
	'AND' => array(
		'OR' => array(
			array($this->alias.'.col4' => 'value5'),
			array($this->alias.'.col5' => 'value6')
		)
	)
);

 

【PHP】XMLの指定したノードの子ノードを見付ける。

めも。

例えばRSSファイルの下記のような要素にアクセスしたい場合。

<dc:date></dc:date>
<dc:subject></dc:subject>

SimpleXMLElement::children()メソッドを用いることで取得可能。

下記例。

foreach($xmlObj->item as $item) {
    $date = $item->children('dc', true)->date;
    $subject = $item->children('dc', true)->subject;
}

第2引数のtrueは第1引数をプレフィックスとして扱うか否かのフラグ。

 

【PHP】in_array()での重複チェックと添字直アクセスのスピード比較。

例えばループ処理中重複した値を弾きたい場合、下記2つのアプローチではどちらが高速なのだろうか。

1, キャッシュ配列に値を詰め込みその後、in_array()を用いて重複値をチェックする
2, 値を配列のキーに持たせ、isset()にて添字の存在チェックい重複を弾く

結果は以下のとおり。

$cache = array();
$start = microtime(true);
for($i = 0; $i < 10000; $i++) {
	$md5 = md5($i);
	if(!in_array($md5, $cache)) {
		$cache[] = $md5;
	}
}
$end = microtime(true);

echo $end - $start."\n";


$cache = array();
$start = microtime(true);
for($i = 0; $i < 10000; $i++) {
	$md5 = md5($i);
	if(!isset($cache[$md5])) {
		$cache[$md5] = true;
	}
}
$end = microtime(true);

echo $end - $start."\n";

上はin_array()、下はisset()

5.5056478977203
0.020223140716553

その差は272倍。
圧倒的に添字アクセスの方が速い。

 

【PHP】file_get_contents()関数でコンテンツ取得時のHTTP レスポンスヘッダを取得する。

メモ。

file_get_contents()関数を実行した直後に$http_response_header変数をダンプするとHTTPレスポンスヘッダを取得することが出来る。

file_get_contents('http://example.com');
var_dump($http_response_header);

↓

array(9) {
  [0]=>
  string(15) "HTTP/1.1 200 OK"
  [1]=>
  string(35) "Date: Sat, 18 Jan 2014 08:34:35 GMT"
  [2]=>
  string(31) "Server: Plack::Handler::Starlet"
  [3]=>
  string(37) "Content-Type: text/xml; charset=utf-8"
  [4]=>
  string(32) "Vary: User-Agent,Accept-Encoding"
  [5]=>
  string(20) "X-Framework: JP/4.01"
  [6]=>
  string(98) "Set-Cookie: ldblog_u=121.107.203.110.1390034075591149; path=/; expires=Fri, 18-Apr-14 08:34:35 GMT"
  [7]=>
  string(45) "P3P: CP="BUS OUR PHY STP ADM CUR DEV PSA PSD""
  [8]=>
  string(17) "Connection: close"
}

 

【PHP】SimpleXMLでCDATAを取得する。

通常であればCDATA内の情報は破棄されてしまうが、第2引数、第3引数を下記のようにしてやることで、情報を正しく取得することが出来る。

simplexml_load_file('http://example.com', 'SimpleXMLElement', LIBXML_NOCDATA);

 

【CakePHP2.4】saveAll()メソッドでINSERT文を分割させたくない場合。

AppModelに下記独自関数を定義する。


App::uses('Sanitize', 'Utility');

class AppModel extends Model {
	
	public function saveAllAtOnce($data) {
		if(count($data) > 0 && !empty($data[0])) {
			$data = Sanitize::clean($data);
			$value_array = array();
			$fields = array_keys($data[0][$this->name]);
			foreach ($data as $key => $value) {
				$value_array[] = "('" . implode('\',\'', $value[$this->name]) . "')";
			}
			$sql = "INSERT INTO " . $this->table . " (" . implode(', ', $fields) . ") VALUES " . implode(',', $value_array);
			$this->query($sql);
			return true;
		}
		return false;
	}
	
}

この関数に下記のような構造のデータを渡せば、一度のインサート文で複数レコードを一括登録してくれるのでsaveAll()メソッドを使うよりも処理が速くなる。

array(
	0 => array(
		'ModelName' => array(
			'Field1' => 'value',
			'Field2' => 'value',
			'Field3' => 'value',
			'Field4' => 'value',	
		)
	),
	1 => array(
		'ModelName' => array(
			'Field1' => 'value',
			'Field2' => 'value',
			'Field3' => 'value',
			'Field4' => 'value',
		)
	)	
)

これはかなり便利。

 

【PHP】現在のメモリ使用量を取得する。

めも。

// メモリの使用量をバイト単位で取得する
echo memory_get_usage();

// PHPに割り当てられたメモリの最大値を得る
echo memory_get_peak_usage();

メモリを気にする重たい処理を作ってるとよく使う。