ZipArchiveのextractToで日本語ファイルが解凍できない【PHP】

zip圧縮自体はうまくいってるのだけれど、ZipArchiveのextractToで解凍すると日本語部分が消えてしまう問題が発生しました。

たとえばファイル名が

サンプル-1.jpg

という場合、解凍すると

-1.jpg

となってしまいます。

調べたところ、ZipArchiveはPHPで設定されているlocaleに依存するとのこと。

ZipArchiveで日本語ファイル名を扱えない場合があって困った話 - Qiita

ということであれば、同じプログラム内で事前にlocaleの設定を変えればいいんじゃね?と思い、ZipArchiveをインスタンス化する前に、下記を追記しました。


if (setlocale(LC_ALL, 'ja_JP.UTF-8') === false) {
error_log('Locale not found: ja_JP.UTF-8');
exit(1);
}

参考:PHPのロケールに関するまとめ - hnwの日記

日本語ファイルでもうまく解凍できるようになりました!

nandani | 2014年12月19日 | コメント(0) | トラックバック(0) | PHP関連

WordPressの検索機能をカスタマイズ

WordPressの検索の欠点として

  • カスタムフィールドが対象外
  • カテゴリー・タグ(タクソノミー)が対象外

というものがあります。

最近は内容フィールドは使用せず、カスタムフィールドに中身を入れるといった場合もあるので、これでは大変不便です。

ということで、検索機能をカスタマイズし、これらからも引っ張ってくるようにします。(ついでに抜粋からも)

なお、検索処理のカスタマイズは「pre_get_posts」をフックした関数にて行います。

pre_get_postsについては、こちらをご覧ください(query_postsを捨てよ、pre_get_postsを使おう【追記あり】【報告あり】)。

functions.phpに下記を追加します。
※pre_get_postsをフックした関数がすでに存在していている場合は、うまく編集してください。

function my_pre_get_posts($query) {
	//管理画面には適応しない
	if ( is_admin() || ! $query->is_main_query() )
		return;
		
	//検索画面の場合
	if($query->is_search()){
		global $wpdb;
		
		$keywords = get_search_query();
		if($keywords){
			
			$keywords = str_replace(" ", " ", $keywords);
			$keyword_array = explode(" ", $keywords);
			$post_ids = array();
			$post_ids_exists = array();
			foreach($keyword_array as $keyword){
				$post_ids_meta = array();	//カスタムフィールド
				$post_ids_post = array();	//タイトル・内容
				$post_ids_term = array();	//カテゴリー
				
				if($keyword){
					$keyword = '%' . like_escape( $keyword ) . '%';
					
					//カスタムフィールド内を検索
					$post_ids_meta = $wpdb->get_col( $wpdb->prepare( "
						SELECT DISTINCT post_id FROM {$wpdb->postmeta}
						WHERE meta_value LIKE '%s'
					", $keyword ) );
					
					//タイトルと内容・抜粋から検索
					$post_ids_post = $wpdb->get_col( $wpdb->prepare( "
						SELECT DISTINCT ID FROM {$wpdb->posts}
						WHERE post_title LIKE '%s'
						OR post_content LIKE '%s'
						OR post_excerpt LIKE '%s'
					", $keyword, $keyword, $keyword ) );
					
					//カテゴリー名から検索
					$term_ids = $wpdb->get_col( $wpdb->prepare( "
						SELECT DISTINCT term_id FROM {$wpdb->terms}
						WHERE name LIKE '%s'
					", $keyword) );
					//ヒットしたカテゴリーが所属する投稿
					if($term_ids){
						$term_id = implode(",", $term_ids);
						$post_ids_term = $wpdb->get_col( $wpdb->prepare( "
							SELECT DISTINCT  object_id FROM {$wpdb->term_relationships}
							WHERE term_taxonomy_id IN (%s) 
						", $term_id) );
					}
					
					//各処理で取得した投稿IDをマージする。
					$post_ids_tmp = array();
					$post_ids_tmp = array_merge($post_ids_meta, $post_ids_post, $post_ids_term);
					
					//重複している投稿IDのみ抜き出す(AND検索のため)
					if($post_ids_tmp){
						//検索ワード1つ目の場合、$post_ids_existsのキーに投稿IDを入れていく(内容はtrue)
						if(empty($post_ids_exists)){
							foreach($post_ids_tmp as $post_id){
								$post_ids_exists[$post_id] = 1;
							}
						}
						//検索ワード2つ目以降の場合
						else{
							//○つ目の投稿IDを$post_ids_exists_tmpキーに入れていく(内容はtrue)
							$post_ids_exists_tmp = array();
							foreach($post_ids_tmp as $post_id){
								$post_ids_exists_tmp[$post_id] = 1;
							}
							
							//1つ目の$post_ids_existsと、○つ目の$post_ids_exists_tmpとを比較し、存在しない場合はunsetする。
							foreach($post_ids_exists as $post_id => $value){
								if($post_ids_exists_tmp[$post_id] != 1){
									unset($post_ids_exists[$post_id]);
								}
							}
						}
					}
				}
			}
			
			//まとめた$post_ids_existsのキー(投稿ID)を、内容に移す
			if($post_ids_exists){
				foreach($post_ids_exists as $post_id => $value){
					$post_ids[] = $post_id;
				}
			}
			if($post_ids){
				$query->set('post__in', $post_ids);
			}else{
				$query->set('post__in', array(0));
			}
			
			
		}else{
			$query->set('post__in', array(0));
		}
		$query->set('s', '');	//本来の検索は邪魔になるので削除しておく
	}
}
add_action( 'pre_get_posts', 'my_pre_get_posts' );

最後に、

$query->set('s', '');

を行っているため、検索結果ページで、$sやget_query_var('s')から検索ワードを取得できなくなっています。

そのため、search.phpのget_header()の前に

$wp_query->query_vars["s"] = $wp_query->query["s"];

を追記してください。
これで$sやget_query_var('s')を使って検索ワードを取得できるようになります。

しかし結構ごつい処理をしてるので重くなりそうな気も・・・大丈夫かな。

参考サイト

nandani | 2014年12月17日 | コメント(2) | トラックバック(0) | CMS関連

Firefoxは勝手にアクセスする

WordPressで、独自にページアクセス数をカウントする機能を作成していたのですが、1ページにアクセスしただけなのに、次のページまで加算されてしまう現象になってしまいました。

どうもwp_head()があると、別のページも加算されてしまう模様。

しかし怪しいところは無い。なぜだ・・・と思っていたら、こんな記事を見つけました。

Firefoxはlink relを先読みする模様

お、おう・・・マジか。

なんてありがた迷惑な機能・・・

とりあえずrel="next"を消す必要があるようなので、こちらのサイト(Firefoxはlink relを先読みする模様)を参考にfunctions.phpに下記を追記しました。

remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');

う~ん。

今回SEO対策を考慮しなくてよいサイトだったのでよかったのですが、rel="next" rel="prev"は本来必要な記述。

SEOを考慮しながら、独自でアクセス数をカウントする機能を追加しなくてはならない場合のことも考えておかねば。

ちなみに、アクセスごとにカウントを取る仕組みは、single.phpに


$pageview_prev = get_post_meta($post->ID, "pageview", "true");
$pageview = $pageview_prev + 1;
update_post_meta($post->ID, 'pageview', $pageview, $pageview_prev);

を追記するだけの簡単なものです。

Google Analyticsとかどうしてるんだろう?

まあ賢いGoogle先生だから何かしらのフィルタリングをしているのだろうけど。

nandani | 2014年12月15日 | コメント(0) | トラックバック(0) | CMS関連

カスタムフィールド並び替えが数字の場合の注意点【WordPress】

カスタムフィールド順に並び替える場合、query_postsを使うと、こんな感じになります。

query_posts(
array(
"orderby" => "meta_value",
"meta_key" => "(カスタムフィールドのキー)",
"order" => "ASC"
)
);

しかし各投稿のカスタムフィールドの中身が、1,2,3,4,5,6,7,8,9,10,11,12・・・

となっている場合、順番が

1,11,12,2,3,4,5,6,7,8,9・・・

となってしまいます。

このような場合、orderbyはmeta_valueではなく、meta_value_numとしなくてはなりません。

query_posts(
array(
"orderby" => "meta_value_num",
"meta_key" => "(カスタムフィールドのキー)",
"order" => "ASC"
)
);

これで、並び替えの内容が数字と判断され、数字の順番通りに並びます。

参考サイト

query_posts:WordPress私的マニュアル

テンプレートタグ/query posts - WordPress Codex 日本語版

 

 

nandani | 2014年12月15日 | コメント(0) | トラックバック(0) | CMS関連

管理画面の投稿やカテゴリー(カスタムタクソノミー)画面でも並び替えを反映させる【WordPress】

カテゴリーおよびカスタムタクソノミーの並び替えを簡単に行えるプラグイン「PS Taxonomy Expander

フロントエンドでは、get_termsやwp_list_categoriesの"orderby"を"order"にすることによって、並び替えた順に並んでくれます。

しかし管理画面の「新規投稿を追加」や「投稿を編集」のカテゴリー選択リスト、および「カテゴリー」画面のカテゴリーリストでは並び順が反映されていません。

Category Order and Taxonomy Terms Order」というプラグインもあって、これを使用すると管理画面内の並び順も反映されるんですけどね。

こっちを使ってもいいし、「PS Taxonomy Expander」のまま、functions.phpに下記を追加しても構いません。


function my_get_terms_orderby($orderby){
  if(is_admin()){
    return "t.term_order";
  }else{
    return $orderby;
  }
}
add_filter('get_terms_orderby', 'my_get_terms_orderby', 10);

これで管理画面内のカテゴリーの並び順は強制的に、Term Orderで設定した並び順に並びます。

※必ず一度は並び替えの保存を行ってください。未保存のままだとカテゴリーリストが表示されなくなります。

しかしフック機能の便利さには舌を巻きますね。何でもできる気分になりますw

nandani | 2014年12月02日 | コメント(0) | トラックバック(1) | CMS関連 | PHP関連

ページのスラッグからデータを引き出す方法【WordPress】

get_page_by_path("スラッグ名");

で、そのスラッグ名のページ(固定ページ)を取得できます。

第3引数をpostとすれば、「投稿」から取得できます。

get_page_by_path("スラッグ名", "OBJECT", "post");

なお、固定ページで、親ページが設定されている場合、親ページのスラッグも含める必要があります。

get_page_by_path("親ページのスラッグ名/スラッグ名");

だから、やっぱり正確にはスラッグ名ではないんですね。

 

参考サイト

get_page_by_path:WordPress私的マニュアル

nandani | 2014年11月24日 | コメント(0) | トラックバック(0) | CMS関連 | PHP関連

WordPressでTinyMCEの入力フィールドを作る場合

任意の場所に、Wordpressの内容入力フィールドと同じようにリッチテキストエディタ(TinyMCE)を設置する方法は、

wp_editor( "(内容)", '(ID)');

で、設置できます。

第3引数に細かい設定ができますが、(ID)をnameと同じにしていればこれだけでもOKです。

プラグインなしでカスタムフィールド作ってた際(functions.phpに直書き)どうやったらリッチテキストエディタになるのか、かなり苦戦したのでメモ。

参考サイト

wp_editor:WordPress私的マニュアル

 

nandani | 2014年11月12日 | コメント(0) | トラックバック(0) | CMS関連 | PHP関連

Postgresqlはテーブル名に注意

Postgresqlでテーブルを作った後、PHPにてSQL

SELECT * FROM (テーブル名)

と実行したのですが、存在するテーブルなのに、

ERROR:  relation "(テーブル名)" does not exist

というエラーが出てしまいました。

調べてみると、どうやらテーブル名はダブルクォートでくくらなければならないらしい。

SELECT * FROM "(テーブル名)"

ただし、これはテーブル名に大文字が含まれている場合のみで、小文字のみであればダブルクォートは不要とのこと。

たしかに、テーブル名は大文字で作成してました。

なんならSQLを実行した後、エラーで表示されるテーブル名が小文字になっているから、おかしいなとは思っていたのですが。

Postgresqlの場合は、実行時にテーブル名が小文字になってしまうのかな?

だから、大文字を含む際はダブルクォートが必要なのか。

 

参考サイト

PostgreSQLのテーブル名はダブルクォート有無で別名になった. - それマグで!

nandani | 2014年10月08日 | コメント(0) | トラックバック(0) | DB関連 | PHP関連

SuPHP使ってるときはphp.confいらないよ

手間取ったのでメモ。

PHPのバージョンをアップしたところ、PHPがモジュールモードになってしまい、実行権限がapacheになってしまいました。(もともとSuPHPを使っていたので、実行権限はユーザごとになっていた。SuPHPを使うためには、PHPをCGIモードにする必要がある。)

CGIモードにするには、ということでいろいろ調べてphp.confをいじりまくったのですが、全然CGIモードにならない!

効いていないわけではないっぽいけど、やっぱりモジュールモードのままで散々手こずったのですが、FTPで/etc/httpd/conf.d/フォルダを除いてみたところ、一発で解決しました。

そこにあったのは「mod_suphp.conf」

こいつだけでよかったのです。

「php.conf」なんていらなかったのです。

多分バージョンアップしたときに、勝手にできたのでしょう。

「php.conf」をリネームし、無効化してから、Apache再起動したところ、無事CGIモードに切り替えることができました。

あ~あ・・・・

ちなみに、PHPがモジュールモードかCGIモードかを見極める方法は、phpinfoの「Server API」を確認すればOKです。

ここが、「CGI/FastCGI」ならCGIモード、「Apache 2.0 Handler」ならモジュールモードです。

 

htmlspecialcharsに注意【PHP】

今更な話題ですが、詰まったのでメモ。

PHPが5.3から5.5に変わった途端、フォームにて日本語がPOSTされるとまるごと消えてしまう現象が発生しました。(ちなみにそのサイトはEUC-JPで作成されていました)

この現象はWordpressなどでもあったので、

default_charset
mbstring.internal_encoding

あたりの仕業だろうと思っていたのですが、これらはコメントアウトされている。(つまり特定の文字コードに設定されていない)

phpinfoを見てもおかしなところは全然見当たらない。

ということでいろいろ調べてみると、なんとhtmlspecialcharsが原因であることが判明しました。

このhtmlspecialcharsはもともとは、「ISO-8859-1」がデフォルト文字コードで変換がされていたのですが、PHP5.4から「UTF-8」がデフォルトになったとのこと。

しかも、php.iniで設定されている文字コードに準拠してくれればよいのですが、これはちゃんと設定してあげないと、強制的に「UTF-8」が使用されてしまうらしい。(第3引数をクォートなどで任意に空にしてあげれば準拠してくれるらしい。でも、第3引数をなにも設定してないとUTF-8となる。なんでやねん)

ということで、簡単な方法はないかを探していたけど、やっぱり引数をつけてあげるしかないみたい・・・

htmlspecialchars($hoge, ENT_COMPAT | ENT_HTML401, "ISO-8859-1");

参考サイト

htmlspecialchars()を使うと文字が消える? | PHP Archive

[PR]WAFの導入はHASHコンサルティング Sturts1 / Struts2 の脆弱性にも対応

nandani | 2014年09月23日 | コメント(0) | トラックバック(0) | PHP関連

Copyright(c) 2010 - 2024 ダリの雑記