読者です 読者をやめる 読者になる 読者になる

ITの隊長のブログ

ITの隊長のブログです。いや、まだ隊長と呼べるほどには至っていないけど、日々がんばります。CakePHPとPlayFrameworkを使って仕事しています。最近はAngular2をさわりはじめたお(^ω^ = ^ω^)

最近Wordpressで学んだこと

WordPress PHP

スポンサードリンク

WordPress

先週デスマだったので、その時にやったことをメモ。

template関連

特定のページで読み込むstyleとかjavascriptを変更したいとき

よくheader.phpで条件を増やしたり、header.php自体を増やしたりしてしまいますが、修正する範囲が増えるのでナンセンス。

その悩みもこの関数を使えば解消されます。

関数リファレンス/wp enqueue style - WordPress Codex 日本語版

<?php
wp_enqueue_style('search-template', get_template_directory_uri() . '/assets/css/search.css', array(), '1.1');
get_header(); ?>

page.phpなどのget_header()前に記述すると、登録したcssget_header()時に一緒にロードしてくれます。なので、そもそもheader.phpに記述する必要なし。

CakePHPでよく使うHtmlヘルパーのfetch()みたいな関数と勝手に理解しています。

javascriptの場合はこちらの関数を使ってください。

関数リファレンス/wp enqueue script - WordPress Codex 日本語版

<?php
wp_enqueue_script('rwd-image', get_template_directory_uri() . '/js/jquery.rwd-image-maps.js', array(), '1.1', true);

個人的な注意点として、wp_head()のときに一緒に読み込むらしいので、その前に実行しなければなりませんので。なので、get_header()より前に記述しなければいけないので注意。

また、wp_enqueue_script()の引数5番目は$in_footerで、trueを渡すと、scriptのロードが、wp_footer()の時になるので、footerに書かないと動かないscriptはtrueにすべし。

投稿一覧ページの投稿リストのhtml&cssは、~/theme/template-parts/content-xxx.phpに任せる

投稿の一覧ページのリストのhtmlやstyleはどーせほとんど同じなので、コードは統一すべきです。

なので、大体のテーマの中にある~/theme/template-parts/content-xxx.phpを使って、統一にしましょう。

<?php

while(have_posts): the_post;
  get_template_part('template-parts/content', 'xxx');
endwhile;

一覧ページや検索一覧などは、こいつを呼べば完成するし、修正が楽ですねー。

レイアウト修正したい場合は、partsファイルをそのたび増やせばおkだと思います。なるべく共通化することがのぞましいですけども。

Custom Post Type UI

投稿タイプを追加、taxonomyを増やしたいなら

このプラグインを使う Custom Post Type UI

Taxonomyを階層にしたい

親、子、孫の関係を使いたい時に使う。

設定したいTaxonomyの設定画面にて、「Hierarchical(階層化)」をTrueに変更する

Advanced Custom Fields

投稿にフィールドを追加したい。追加するフィールドで条件分岐したい。

このプラグインを使う Advanced Custom Fields

すでに登録したtaxonomyを使って、フィールドに流すこともできるが 条件分岐とかでは使えず、またtaxonomyと重複になってしまう。

もしtaxonomyを流用できるなら、検索のパラメータが1つで絞ることができるので楽と思ったんですけどね〜。

そこだけは残念。

blog.s-giken.net

WordPressのadvanced custom fields使用時のGoogle Map入力が出来ない

全く同じ事象はこちら(ちなみに回答しました)

teratail.com

テーマのなかに置いてある、functions.phpにフックを追加してください。

<?php
...
add_filter('acf/fields/google_map/api', function () {
    return array(
        'libraries' => 'places',
        'key'        => 'GOOGLE_API_KEY', // Googleで発行したキーを用意する
        'client'     => ''
    );
});

GOOGLE_API_KEYの発行はこちらから

nendeb.com

検索の話

Taxonomyのお話

Taxonomyを取得する

get_categories()を使う

get_term()は非推奨らしい。

関数リファレンス/get categories - WordPress Codex 日本語版

<?php
$args = array(
  'type' => 'post ,      // post_type -> 投稿タイプ名を指定する
  'hide_empty' => false, // これをtrueにすると投稿からチェックされているtaxonomyしか取得できない。要は記事が無いカテゴリーは取得されない
);
$categories = get_categories($args);

親のみを取得する

引数にparent0で指定すればいける。

<?php
$args = array(
  'type' => 'post',
  'hide_empty' => false,
  'parent' => 0
);
$categories = get_categories($args);

子を取得する

スマートな方法がわからないけど、ループしたらいけた。

parentterm_idを渡すとその親の子を取得することができる。これを親分だけループすればすべての子のデータが取得できる。

<?php
$args = array(
  'type' => 'post',
  'hide_empty' => false,
  'parent' => 0
);
$categories = get_categories($args);

$childCategories = array();
foreach($categories as $parentCategory) {
  $childArgs = array(
    'type' => 'post',
    'hide_empty' => false,
    'parent' => $parentCategory->term_id
  );
  $childCategories = array_merge($childCategories, get_categories($childArgs));
}

それか、親、子の関係だけであれば、親以外を取得するってのもあり

<?php
$args = array(
  'type' => 'post',
  'hide_empty' => false,
);

$categories = get_categories($args);

$childCategories = array();
foreach($categories as $category) {
  if ($category->parent != 0) {
    $childCategories[] = $category;
  }
}

孫を取得する

ループループ。。。

<?php
$args = array(
  'type' => 'post',
  'hide_empty' => false,
  'parent' => 0
);
$categories = get_categories($args);

$childCategories = array();
foreach($categories as $parentCategory) {
  $childArgs = array(
    'type' => 'post',
    'hide_empty' => false,
    'parent' => $parentCategory->term_id
  );
  $childCategories = array_merge($childCategories, get_categories($childArgs));
}

$grantChildCategories = array();
foreach($childCategories as $childCategory) {
  $grandChildArgs = array(
    'type' => 'post',
    'hide_empty' => false,
    'parent' => $childCategory->term_id
  );
  $grantChildCategories = array_merge($grantChildCategories, get_categories($grandChildArgs));
}

ひ孫を取得する

いいかげんにしろ!!!! 要件を見直すんだ!!!!

(でも再帰とか使えばなんかいけそうな気がする)

taxonomyに紐付いてる、記事数をカウントする

SQLだぁーと思ったけど、すでに情報は付与されている。

<?php
...
$category->count;

以上。注意すべきはチェックが入っていないとカウントされない。当たり前か。。。

Taxonomyにslug、名前以外で情報を持たせたい

スマートじゃないけど、descriptionのフィールドを使う。複数持たせたい場合は、カンマ区切りとか独自のルールを用意してやらばいいと思う。あんまりおすすめしないけど。。。

<?php
...
$categories = get_categories($args);
foreach($categories as $category) {
  echo $category->term_id;     // タームのid
  echo $category->slug;        // スラック名
  echo $category->name;        // 登録の名前
  echo $category->parent;      // 親のid(親が居ないなら0)
  echo $category->description; // 説明。ここに独自ルールでデータを保存したりすればいける
}

Taxonomyで検索する

<?php
...
$args = array(
  'post_type' => 'post_type',
  'tax_query' => array( // 配列のなかに配列を作ることで検索できる。よく間違えるので注意
    array(
      'taxonomy'=>'category', // taxonomyの名前を指定
      'field' => 'slug',      // slug -> slug名, term_id -> term id, name -> termの名前
      'terms' => 'okinawa',   // 上で指定した値のvalueをいれる。配列でも良い -> array('south', 'north')
      'operator' => 'IN'      // 演算子。指定したい値を除外したいなら 'NOT IN'とか使う
    )
    /**
     * 2つ目の条件を用意したいなら、もうひとつ配列を追加
    array(
    ),
    'relation' => 'AND' // それぞれ指定した論理条件を指定します。値は'AND'、'OR'の2つです。
    */
  )
);

// 上のパラメータを query_posts() か、get_posts() に食わせる
// query_posts($args); // query_posts()の場合はその後のhave_posts()とwhile()を組み合わせて値を取得
$posts = get_posts($args); // get_posts()の場合は、条件にマッチした記事objectが返ってくるので、それを取得してforeach()とかでループすれば良い。

Custom fieldのお話

custom field で検索する

ほとんどはtaxonomyのときと同じ。

<?php
...
$args = array(
  'post_type' => 'post_type',
  'meta_query' => array(
    array(
      'key' => 'okinawa', // custom field の key名を指定
      'value' => 'south', // 検索したい条件の値を指定。配列でもおk
    ),
    /**
     * 料金とかの場合、0円 〜 1000円の商品とかの情報(記事)を検索したい場合もあるかも
     * その場合は、BETWEENを使えば良い
     * また、DBに検索を書けるため、必要な情報として、型もいれてあげること
     * NUMERIC => 数値 TIME => 時間 などなど

     array(
      'key' => 'price',
      'value' => array(0, 1000),
      'compare' => 'BETWEEN',
      'type' => 'NUMERIC'
     ),
     'relation' => 'AND'
     */
  )
);
// query_posts($args);
$posts = get_posts($args);

検索フォームと検索(処理)結果

1.templateファイルを作成 * 検索フォーム.phpを作成 - 今回はtest-searchform.php * 検索処理・結果.phpを作成 - 今回はsearch-test.php

2.固定ページを作成 検索フォーム.phpを指定する固定ページを用意

3.functions.phpに下記コードを追記する

<?php
...

/**
 * 検索時にtaxonomyのタイプを確認して検索テンプレートを選択
 * @param $template
 * @return string
 */
function customSearchTemplate($template)
{
  // 検索結果の時
  if (is_search()) {

    $taxonomy = $_GET['taxonomy'];

    $templates = [];
    if (! empty($taxonomy)) {
      $templates[] = "search-${taxonomy}.php";
    }
    $templates[] = 'search.php';

    $template = get_query_template('search', $templates);

  }
  return $template;
}
add_filter('template_include','customSearchTemplate');

template_includefilterにフックする。検索の時に、任意の処理でtemplateを指定されたら、そのtemplateを読み込み用に処理を追加した。

色々な指定の仕方があると思うが、今回自分はsearchform.phpで、getパラメータに<input type="hidden" name="taxonomy" value="test">と記述することで、searchform.phpsearch.phpを紐付けられるようにしました。

これで1つの検索フォームと検索結果ページでごちゃごちゃに処理を記述せずにすむんじゃないかな。

感想

2ヶ月前の案件では、「このクソCMSがぁ!!!」なんていっていましたが、わかってくると面白いですね。というか本当によくできているCMSかなと。

ソース読んでみるとよくまぁこんなにスピーディーに動くなぁと。コードの読みやすさは低いと思うけど。

引き続きWP案件続きそうなので、勉強します。オライリー読みたくなってきた。