kjmtsh
フォーラムへの返信
-
フォーラム: 使い方全般
返信が含まれるトピック: カスタムフィールドの価格の合計get_field() って、よくわからないのですが…
foreach (リンゴA~リンゴCの条件) { $price_data[] = get_field('cfprice'); } $sum = array_sum($price_data);
それとも、データベースに保存するんでしょうか?
フォーラム: 使い方全般
返信が含まれるトピック: 投稿を【ユーザーメタデータ】で検索したいSearch Everything を使っていないので、推測で書きます。内容が少し難しいようなら、最後の結論だけを読んでいただくだけでもかまいません。
WordPress デフォルトの検索は、query string が投稿のタイトルと本文のどちらかに含まれるものを検索します。だから、使うテーブルは、
- wp_posts
だけです。検索文字列は外部からの入力なので、SQL インジェクションを回避するための処理をしたり、stop word を削除したり、文を語の単位に分解をしたりして、最終的に生成されるクエリステートメントの where 句は、
($wpdb->posts.post_title LIKE '%{$term}%') OR ($wpdb->posts.post_content LIKE '%{$term}%')
のようになります。これを検索語句の数だけループで回して、AND 結合します。ここで理解していただきたいのは、ユーザが入力した検索文字列を投稿やページに含まれる文字列と照合する SQL 文がこの段階で作成されてしまっているということです。
Search Everything は、Plugin Directory の記述を読む限り、これに加えて、カスタムタクソノミーやカテゴリやその他も含めて検索できる機能を提供するプラグインです。このため、利用するテーブルがさらに増えて、
- wp_postmeta
- wp_comments
- wp_term
- wp_term_taxonomy
- wp_term_relationships
- wp_users
が含まれるようです。これらは必要に応じて、JOIN で結合されるのではないかと思いますが(WordPress にフィルタが用意されています)、wp_usermeta テーブルはありません。temina さんがお示しのような、
$search .= "{$searchand}(u.display_name LIKE '{$n}{$term}{$n}')";
は、wp_users を JOIN で結合して始めて利用できる WHERE 句ですから、wp_usermeta を利用する meta_key や meta_value は使えないということになります。一方、description や aim は、wp_users に含まれるので、動作します。また、上の例と比べてみるとわかるように、これは WordPress が検索クエリを作るときとそっくり同じ、変数名まで同じものです。たぶん、この前には、
SELECT * FROM wp_posts AS p LEFT JOIN wp_users AS u ON u.user_id=p.ID
のような主文があるはずです。コメントを検索するには同じく、wp_comments を JOIN して、検索語句の数だけループを回して上のような WHERE 句を AND で結合するわけです。
細部は違うかもしれませんが、現象から考えて、大筋はこのようになっていると思います。そうすると、以下のような結論になります。
ユーザが入力した検索語句は、temina さんが functions.php に書き加えたコード、
$users = $wpdb->get_results(" SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'aim' AND meta_value LIKE '%$s%'");
で使われるだけでなく、実は他の部分でもすでに使われてしまっていて、それを制御する手段はありません。他の全ての設定を外しても、デフォルトの検索クエリだけは残るでしょうから、最低でも1か所で使われてしまいます。つまり、temina さんが入力した「関東」という語は、ユーザ ID を探すために使われると同時に、「関東」が含まれる投稿とタイトルを検索するためにも使われているということです。
さて、それでは、どうすればよいでしょうか?
「ユーザメタデータを検索のキーとして、該当ユーザのIDを含む投稿を列挙する」
という temina さんのやりたいことを実現するには、Search Everything のデフォルトの動作を停止する必要があります。また、WordPress デフォルトの検索クエリも作動しないようにしなければなりません。とすると、もう自分でメインクエリを書き換えるしかありません。しかも、WP_Query のインスタンスが作成されるところにまでさかのぼる必要があるので、pre_get_posts のようなフックも使えません。Hic Rhodus, hic salta.
そもそも本件可能なのでしょうか?
「可能です」が答えになると思いますが、何行ものコードを書く必要があります。思いつく方法は三つあります。
- Search Everything を改造すること。wp_usermeta を JOIN できるように追加のコードを書き、これを使って検索するときには、WHERE 句に投稿やタイトルを検索する部分が含まれないようすればよいはずです。
- 新たな、検索用 WP_Query のインスタンスを作り、post_join フィルタで wp_usermeta を追加して、必要なパラメータを指定すること。このとき、is_search() が true になると、WordPress の検索クエリが先にできてしまうので、search.php でメインクエリを置き換える操作が必要になります。
- $wpdb クラスを使って、生のクエリを自作し、search.php で自前の整形をする。
1 は大幅なコード追加になると予想できます。2 は、実質 Search Everything を捨てることを意味します。3 が一番お手軽だとは思いますが、WordPress で用意されている テンプレートタグが使えません。また、Search Everything の機能も使えません。これを使った暫定解です。functions.php に以下を書いて、
function search_with_usermeta() { global $wp_query, $wpdb; if (!(is_search() || isset($wp_query->query_vars['s']))) return; $query_string = stripslashes($wp_query->query_vars['s']); $query_string = str_replace(array("\r", "\n""), '', $query_string); $where = ''; if (preg_match_all('/".*?("|$)|((?<=[\t ",+])|^)[^\t ",+]+/', $query_string, $matches)) { $search_terms = $matches[0]; if (empty($search_terms)) { $search_terms = array($query_string); } } else { $search_terms = array($query_string); } foreach ($search_terms as $term) { $term = like_escape(esc_sql($term)); $where .= " AND (um.meta_key = 'メタキー' AND um.meta_value LIKE '%{$term}%')"; } $where .= " AND (p.post_type = 'ポストタイプ' AND p.post_status = 'publish')" $results = $wpdb->get_results(" SELECT * from $wpdb->posts AS p LEFT JOIN $wpdb->usermeta AS um ON p.post_author = um.user_id WHERE 1=1 $where ORDERBY p.post_date DESC "); return $results; }
search.php で下のように使ってください。
$my_posts = search_with_usermeta(); foreach ($my_posts as $post) { 出力整形 }
ページ送りなどは考慮していません。当然ですが、無保証です。
フォーラム: 使い方全般
返信が含まれるトピック: 管理画面の文言置換(カスタム投稿別)ishihara takashi さんの書き換えでいいと思いますが、switch で指定するのが、翻訳前の文字列となります。パラメータで受けた $untraslated_text は書き変わらないからです。case 以下を下のようにするとどうでしょう?
case 'Save Draft': $translated_text = '保存して内容を確認する'; break; case 'Save as Pending': $translated_text = 'レビュー待ちとして送信'; break;
この場合、日本語じか打ちになってしまう(gettext が必要ない)のと、ここで text_domain を指定してもテーマのものになるので、上のようにかえました。
フォーラム: 使い方全般
返信が含まれるトピック: jsが作動していないかもしれません。上で書いたコードは、yuga.js の該当部分を整理したものなので、もう削除してかまいません。yuga.js を読み込めば、同様に動作するはずです。親子についてのスイッチも機能するはずです。
ただし、thickbox.js は完全にエラーなので、上の対策が必要だと思います。yuga.js の deprecated というのは、「古い方法なので、使わない方がいいよ」という警告なので、そのまま使っても問題ありません。セキュリティが脅かされることもありません。
全て最後にスラッシュついてました
こういうことが起こるので、本当は、自分で打ち込むよりも、WordPress の関数を使ってメニューを作ってもらうのがよいのですが、管理画面でも画像を使うメニューは作れます。今後、少しずつ勉強されるとよいと思います。私も勉強になりました、ありがとうごうざいました。
/* やっと WordPress に戻ってきた */
フォーラム: 使い方全般
返信が含まれるトピック: jsが作動していないかもしれません。フォーラム: 使い方全般
返信が含まれるトピック: jsが作動していないかもしれません。ちゃんと動作しますね。aboutページは正常動作です。今度は、flowページを表示したときにどうなっているか、教えてください。flow ページの行だけでかまいません。
このとき、ブラウザのアドレスバーにどんなアドレスが表示されているかも知りたいです。
フォーラム: 使い方全般
返信が含まれるトピック: jsが作動していないかもしれません。本当はブラウザの「ソースを表示」で見られるものがほしかったのですが、とりあえず、アンカーがあって、その内側に
<img>
タグがあることはわかりました。何が動作していないのか、実験してみましょうか。yuga.js も thickbox.js も外して、jquery だけ読み込み、下のコードをテンプレートファイルのbodyに書き込んでみてください。現在表示されているページのメニュー項目の画像が変わったら成功、そうでなければ、失敗です。
<script type="text/javascript"> jQuery(document).ready(function($) { $('nav a[href]').each(function() { permalink = this.getAttribute('href'); slug = location.href; if (permalink == slug) { $(this).addClass('current'); $(this).find('img').each(function() { newSource = $(this).attr('src').replace(new RegExp('(_cr)?(\.gif|\.jpg|\.png)$'), '_cr'+'$2'); $(this).attr('src', newSource); }); } }); }); </script>
フォーラム: 使い方全般
返信が含まれるトピック: jsが作動していないかもしれません。ああ… これって、about ページが表示されているときですよね?
<li id="about"><a href="現在のスラッグ">
となるはずのところに、href 以下がないのですが、何か細工してますか? スクリプトは、href を探すようになっていますから、これがないのは致命的です。まずは、ここに正しいスラッグが表示されるようにしましょう。
フォーラム: 使い方全般
返信が含まれるトピック: jsが作動していないかもしれません。@yuga.js の作者さん(もし、読んでいたら)
すいません、間違いを書いちゃいました、お許しを。以下、訂正です。@h-pine-h さん
ちょっとテストしてみました。現行のWordPressに付属の jQuery (1.10.2)を使うと、- 付属の thickbox.js がエラーで止まる。
- event.returnValue が depricated だから、event.preventDefault() を使えと言われる。
となりますが、yuga.js そのものの動作は作者の意図した通りになっているようです。セレクタ判定が jQuery のバージョンの影響を受けている可能性があるので、範囲を限定する必要がありますが…
1. はもうどうにもなりませんので、thickbox.js 本体をラップするしかないと思います。
jQuery.noConflict(); (function($) { ここに本体 })(jQuery);
一番はじめのaboutのページを開くと、メニュー部分にclass=”current”とつく
これが正しい動作ですが、
他のメニューは、ハイライトされていてもcurrentとなりません
親でも current でもないのに、ハイライト用画像が表示されているなら、異常です。
一つ確認ですが、メニューのタグはこのようになっていますか?
<li id="about"><a href="http://example.com/about/"><img src="......">about</a></li>
画像の書き換え条件は、
<a>
要素の href が現在のスラッグと同じであること(完全一致)- または、現在のスラッグの一つ上のディレクトリに見える(上の例だと、’about/’ をなくしたもの)
<img>
要素が<a>
の内側にある
つまり、
<li id="about"><img src="..."><a href="http://example.com/about/">about</a></li>
のようになっていると、正常動作しません。
selfLinkAreaSelector:'body'
を、
selfLinkAreaSelector: 'nav'
と変更して試してみてください。なお、
changeImgParents:false
は、ちゃんと動作するようです。
フォーラム: 使い方全般
返信が含まれるトピック: jsが作動していないかもしれません。ドキュメントを見ていないので、違うかもしれませんが、
changeImgParents: false
にすると、親ディレクトリが存在する限り、
if (setImgFlg)
が常に false となって、画像の書き換えが全てオフになってしまうのではないでしょうか? ドキュメントと実装がずれているかもしれません。each(function(){}) の中の if …. else if … が親と子、それぞれで真になっちゃうんですよね…
単純に、親ディレクトリの画像入れ替えは必要ない、ということなら、
setImgFlg = c.changeImgParents;
をコメントアウトすれば、お望みの動作になるかもしれません。最後のところのアルゴリズムをちょっと変更する必要があるかもしれませんが、未検証です。
/* WordPress から遠く離れて… */
フォーラム: 使い方全般
返信が含まれるトピック: 特定カテゴリ記事一覧を表示させたいforeach ($posts as $post) :
を
foreach ($posts as $post) : setup_postdata($post);
とすると、どうでしょう? 生の $post->post_content をテンプレートタグで使えるようにするための関数です。
フォーラム: その他
返信が含まれるトピック: 投稿がスパム判定されていますフォーラム: 使い方全般
返信が含まれるトピック: 検索結果をテンプレート別に作りたい固定ページが数十あるので…
ページが増えるごとにしこしこ配列に追記する姿を想像して、ちょっと申し訳なく思ってしまいました。動いても、仕事を増やすコードはよくないです。ということで、アイディアだけの別解です。
英語日本語のページはheader.phpとfooter.phpを二つ用意して…
とあるので、日本語ページの header.php にグローバル変数か定数を1つ追加できませんか? $lang=’ja’ みたいな感じです。これを flag として、検索フォームの hidden フィールドから飛ばし、関数でそれを受けて、場合わけをするというのはどうでしょう? 流れは次のようになります。
header.php で、
$lang = 'ja';
search_form で、
<input type="hidden" name="lang" value="$lang" />
function で、
if (is_search() && isset($_GET['lang']) && $_GET['lang'] == 'ja') 日本語処理 リターン else デフォルト リターン
フォーラム: 使い方全般
返信が含まれるトピック: wp-config.phpを一つ上の階層に移動する際の疑問各WPのwp-config.phpを一つ上の階層に移動するとなると、ファイル名が被ってしまうと思うのですが、複数WordPressをインストールしている場合この方法はできないということでしょうか?
はい、できません。そもそも、このインストール形態では、
wp-config.php を1つ上の階層(非公開ディレクトリ)へ移動
ができません。
config.php を非公開ディレクトリに置く、というのは、たとえば、次のようなことをいいます。Codex の想定に従うと、
+--www--+--wp-admin | +--wp-content | +--wp-includes | +-index.php | +-wp-config.php
この状態で、
+--www--+--wp-admin | | | +--wp-content | | | +--wp-includes | | | +-index.php | +--wp-config.php
のようにするわけです。WordPress は www 直下にインストールしてあって、wp-config.php は www ディレクトリと同じ階層にあるということですね。ここにあるファイルは、php なら読めるけれども、ウェブサーバ(たとえば、Apache)はアクセスできません。
これがより安全であるという理由は、「ウェブサービスを通して、wp-config.php が閲覧されたり、ダウンロードされたりする心配がない」ということです。当然、いろいろな議論があって、Codex にもリンクがありますから、ご覧になるといいと思います。
一方、kitaguni_ht さんのインストール状態では下のようになっています(WP3は省略しました)。
www--+--WP1--+--index.php | | | +--wp-config.php | +--WP2--+--index.php | | | +--wp-config.php | +--.htaccess
これを、
www--+--WP1--+--index.php | +--wp-config.php | +--WP2--+--index.php | | | +--wp-config.php | +--.htaccess
のようにすることができます。WP1 または WP2 ディレクトリの1つ上なので、Codex の例ように www と同じ階層には移せません。このとき、ウェブサーバがアクセスできる、できないということだけを考えると、どちらもアクセスできる場所なので、安全性が増すということはありません。また、kitaguni_ht さんがおっしゃるように、ファイル名が同じなので、一つしか置けません。理由は簡単で、WordPress でそのようにコーディングされているからです。
WordPress は index.php にアクセスがあると、次の順序でファイルを読みます。
index.php -> wp-blog-header.php -> wp-load.php -> wp-config.php
wp-load.php の冒頭近くにこんな部分があります。
if ( file_exists( ABSPATH . 'wp-cofing.php') ) { require_once( ABSPATH . 'wp-config.php' ); } elseif ( file_exists( dirname(ABSPATH) . '/wp-config.php' ) && !file_exists( driname(ABSPATH) . 'wp-settings.php' ) ) { require_once( dirname(ABSPATH) . '/wp-config.php' ); } else { インストールプロセスに入る }
コードにはコメントつけられていて、下のようなことが書いてあります。
- もし、WordPress がインストールされたディレクトリに wp-config.php があれば、それを読み込む。
- それがなくて、一つ上のディレクトリに wp-config.php があり、wp-settings.php がなければ、その wp-config.php を読み込む。
- どちらもなければ、インストールを開始する。
この部分を変えればどこからでもファイルを読み込めますが、コアファイルをいじると後のメンテナンスが面倒なので、お勧めしません。wp-config.phpはアップグレードの時でも書き換えられないことが保証されているので、これを2段階にして、別の場所からパスワードなどを読み込むという手段もありますが、気分の問題のような気がします。
ということで、Codexのお勧めは、
- wp-config.php のパーミッションを 0400 にする(ファイルの所有者以外はアクセス禁止)。
- .htaccess で全てのアクセスを禁止する。(kigaguni_ht さんの書かれた通りです)
となります。1はウェブサーバではなくて、サーバにある全てのプログラム、root を除く全てのユーザが禁止対象になります。共用サーバで、たとえ隣からシンボリックリンクを張られても、読まれる可能性は少ないと言えます。2は、勿論、Apache だけにしか作用しません。それぞれ別のことをやっているので、できればどちらも設定するのがよいと思います。
フォーラム: 使い方全般
返信が含まれるトピック: 別ページからのアンカーリンクがずれる