かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

WordPress 投稿が0件でもpost_typeを取得したい。

WordPresspost_typeを取得する場合 通常 get_post_type() を使うのですが、投稿が無い時(0件の時) get_post_type()false を返すため今のページのpost_typeを取得できない場合があります。(カスタム投稿タイプを作って投稿が0件のアーカイブページとか)

Source File: wp-includes/post.php

<?php
function get_post_type( $post = null ) {
    if ( $post = get_post( $post ) )
        return $post->post_type;
    return false;
}

引用元: get_post_type() | Function | WordPress Developer Resources

これは投稿がないとglobal $postがNULLなためget_post( $post )が見つからないのでfalseが返る仕様になっているようです。

get_query_var() を使う

get_query_var( 'post_type' ) を使うと、投稿が0件で $post が NULL の時でも、そのページのpost_typeを取得することができます。

<?php
$post_type = get_query_var( 'post_type' );
echo  $post_type;

カスタム投稿タイプなど投稿が0件でもアーカイブページを表示したり、グローバルナビゲーションなどでpost_typeが必要になる場合はこちらを使うのが良いのではないかと思います。

投稿の一覧ページ( is_home() )の問題

WordPress管理画面の設定 表示設定 > フロントページの表示 で指定できる投稿の一覧ページでは、
投稿が1件以上ある場合でもglobal変数の$wp_queryにはpost_typeが設定されていないので get_query_var( 'post_type' )post_typeを取得することはできませんでした。
投稿がある場合は get_post_type() で取得することが出来るのですが、
投稿が0件の時はget_query_var( 'post_type' ) でも get_post_type() でも post_type を取得することができません。
投稿のpost_typeのデフォルトがpostなので、is_home() && !get_post_type() の時はデフォルト値としてpostをハードコーディングで当てるしかなさそうです。

追記
カテゴリー・タクソノミーのアーカイブでは投稿があっても、query_varにpost_typeはセットされていないようで、 get_query_var( 'post_type' ) は 常に NULL になっていました。

taxonomyオブジェクトを取得して taxonomy_obj-> object_type[0] とすれば、post_type が取得できるようです。
カテゴリーの場合は get_taxonomy('category') で、カスタムタクソノミーはget_query_var('taxonomy')でタクソノミー名を取得してget_taxonomy('タクソノミー名') とすれば taxonomyオブジェクト が取得できます。

EX: post_type を取得する関数

アーカイブページ・シングルページなどで分けてpost_typeを返す関数を作成してみました

<?php
function get_current_post_type() {
  $post_type = get_post_type();
  
 if( empty($post_type) ) {
    // 投稿が 0 件の時
    if( is_category() ) {
      $tax = get_taxonomy('category');
      $post_type = $tax->object_type[0];
    } else
    if( is_tax() ) {
      // category, taxonomy get_query_var( 'post_type' ) は常に null
      // 投稿が 1件 でもあれば get_post_type() で取得可能
      $term = get_query_var('taxonomy');
      $tax = get_taxonomy( $term );
      $post_type = $tax->object_type[0];
    } else
    if( is_archive() ) {
      // 投稿が 0 件の時 get_post_type() は false を返すので get_query_var() で取得する
      $post_type = get_query_var( 'post_type' );
    } else
    if( is_home() ) {
      // 投稿の一覧で投稿が0件の時は 'post' を設定
      $post_type = 'post';
    }
  }
  return $post_type;
}

 
はてなblogさん。。。
マークダウンで引用内にコードブロック出力するにはどうしたら良いのですか???エンジニア系のblogだと結構必要じゃない?


[参考]

PHP56 Macを再起動したらlibphp5.soが消えてapacheが起動できなくなった。

Macを再起動して普段通りapacheを起動しようとしたら次の様なエラーが表示されるようになってしまいました。先方の環境に合わせてPHP56です

$ sudo apachectl start
httpd: Syntax error on line 170 of /usr/local/etc/apache2/2.4/httpd.conf: Cannot load /usr/local/opt/php56/libexec/apache2/libphp5.so into server: dlopen(/usr/local/opt/php56/libexec/apache2/libphp5.so, 10): image not found

HomebrewでインストールしてあるPHP56のディレクトリ(/usr/local/opt/php56/)を見に行くと、libexec ディレクトリが無くlibphp5.soが存在していませんでした。※ Macシャットダウン・再起動で消えたのか定かではありません。Macの再起動前までは問題なくApacheは起動していたのですが...

PHP56を再インストールしたら解決

HomebrewでPHP56を一度アンインスールし、--without-ldap--with-httpd24 オプションを付けてPHP56を再インストールしたらlibphp5.soが作られ問題が解決しました。

$ brew uninstall php56
$ brew install php56 --without-ldap --with-httpd24

参考にしたGitHubのissueには--without-ldap だけでOKのような感じだったのですが、今回の場合、--with-httpd24オプションを指定しないとlibphp5.soが生成されることはありませんでした。
しかし、なぜ突然この問題が発生したのかが謎です...

追記
PHP56を再インストールしたらlocal環境のWordPressでデータベース接続エラーになってしまいました。どうやらlocalhostのDBに接続できなくなっていたようなのでで、php.inimysql.sock関連を指定してあげる必要があるようです。
php.iniは/usr/local/etc/php/5.6にあります。

mysql.default_socket =mysql.sock のパスが記されているので、下記の箇所もこのパスを指定します。

  • mysqli.default_socket =
  • pdo_mysql.default_socket =

参考: [php]mysqliでNo such file or directoryが出る


[参考]

↑ 今ならコレ解決できたかもしれない...

PHP Carbonを使って週表示のカレンダーを作りたい。

週だけ表示できる良い感じのカレンダーが見つからなかったのでPHPで作ってみました。
日付の処理はLaravelでも使用されているCarbonが便利らしいので、これを使うことにしました。

仕様

  • 簡易に曜日と日付が表示できればOK
  • 週の始めは月曜 / 日曜
  • 前後で月が変わる部分も表示する

CarbonをComposerでインストー

$ composer require nesbot/carbon

週カレンダーを作成するスクリプト

<?php
require 'vendor/autoload.php';
use Carbon\Carbon;

/**
 * 週カレンダーの配列を返す関数
 * @param: $startSun(:Boolean)
 *         true ... 日曜から始める
 *         false ... 月曜から始める
 * @param: $date(:String) ... 今日の日付
 */
function getWeekCalender($isStartSun = true, $date = "") {
  $today = new Carbon( $date );
  $todayDay = $today->day;
  $startDate = getStartDay( $today->toDateString("Y-m-d"), $isStartSun );
  $startDay = $startDate->day;
  // 週の最終日を取得
  // note. コピーを作成しないと元のインスタンスの値が変更される
  $lastDay = $startDate->copy()->addDay(7)->day;

  // 開始日のある月の最終日を取得
  $limitDay = $startDate->copy()->endOfMonth()->day;

  $month = $startDate->month;
  $offset = $limitDay - $startDay;
  $day = $startDay;
  $weekArr = [];
  $i = 0;
  while($i < 7) {
    $day = $startDay + $i;
    // 月を跨いだ時
    if( $day > $limitDay ) {
      $day = $i - $offset;
      if($day === 1) {
        $month += 1;
      }
      if($month > 12) {
        $month = 1;
      }
    }
    if($isStartSun) {
      $week = getWeekByIndex($i);
    } else {
      $week = getWeekByIndex($i+1);
    }
    $weekArr[] = [
      'month' => $month,
      'day'   => $day,
      'week'  => $week,
      'today' => $todayDay === $day? true : false,
    ];
    $i++;
  }

  return $weekArr;
}

/**
 * 週の最初の日を取得
 * @param $today(:String) "Y-m-d"
 */
function getStartDay($today, $isStartSun) {
  $dt = new Carbon( $today );

  // $today が週の内何日目か (Sun = 0)
  $w = $dt->dayOfWeek;

  // 月曜始まりのとき
  if( !$isStartSun ) {
    // 今日が日曜なら前の月曜
    if($w === 0) {
      $w = 7;
    }
    $w -= 1;
  }

  return $dt->subDay( $w );
}

function getWeekByIndex($i) {
  $arr = ['Sun.', 'Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.'];
  $len = count($arr);
  if($i >= $len) {
    $i -= $len;
  }
  return $arr[$i];
}

使い方

<?php
// 今日の日付を指定する場合は第ニ引数で指定
// ex: 月曜始まり 2017年3月3日 のある週カレンダー
$weekCalenderData = getWeekCalender(false, "2017-03-03");

// カレンダーを出力
foreach($weekCalenderData as $val) {
  $th .= "<th>{$val['week']}</th>\n";
  $td .= "<td>{$val['day']}</td>\n";
}
echo "<table><tr>${th}</tr><tr>{$td}</tr></table>";

↓ 出力

Mon. Tue. Wed. Thu. Fri. Sat. Sun.
27 28 1 2 3 4 5

感想とか

Carbon は月末日とか簡単に取得できて凄い便利なのですが、関数を使うと元のオブジェクトの日付が変更されてしまう破壊的メソッド(?)なので、元の日付から色々計算した日付を取得したい時はcopy()メソッドを噛ませてオブジェクトを複製しないとハマりそうだなって思いました。


Signalize!/カレンダーガール

Signalize!/カレンダーガール