【WordPress】カスタム投稿タイプを自作プラグインで追加してみよう!

WordPressプラグイン作成してみた記事の第一弾です。Reoです。

今回は、お知らせ用の投稿を追加するプラグインを紹介したいと思います。

 

通常の投稿とは違う投稿タイプのことを「カスタム投稿タイプ」と言います。調べる時は「カスタム投稿タイプ」で調べると追加方法がわさわさヒットします。

カスタム投稿タイプを追加すると管理画面で上記画像のようにメニューに追加されます。

 

カスタム投稿タイプを追加する方法

カスタム投稿タイプを追加する方法はいくつかあります。

  1. テーマのfunctions.phpに追加する
  2. プラグインを使って追加する
  3. 自分でプラグインを作成して追加する

1番のテーマ内のfunctions.php に書く方法が一番主流だと思います。自分も今までその方法をとってきていました。

2番のプラグインを使って追加する場合はコードをいじらなくていいので、コードが読めない人でも利用することができます。

そして今回は3番の、自分でプラグインを作成して追加する方法について書いていきます。

 

プラグインで追加するメリット

さて、テーマ内のfunctions.php に書く方法が主流と言いましたが、では何故今回プラグインとして追加するのかという話です。

プラグインとして追加するメリットはひとつ。テーマに依存しない!ということです。

 

テーマ内のfunctions.php に書く方法では、テーマを変更してしまうと、また別のテーマのfunctions.php に書き加えなければいけません。

また、テーマを変更した際に、実際はDBに記事の中身は残っていますが、一見投稿が消えてしまったように見えてしまいます。

テーマを変えること自体あまり多くないことかもしれませんが、プラグインとして分けておくことで実際に管理も楽になりますし、別のブログへの流用も簡単になります。

 

それに実はコード自体はほとんど同じで、functions.php に書くコードをプラグイン用に少し書き直すだけでプラグインとして導入することができます。

 

プラグインを作ろう!

それでは実際にプラグインを作成していきます。

テーマを作成する時はwp-contentフォルダ内のthemeフォルダ内に配置しますが、プラグインの場合は、wp-contentフォルダ内のpluginフォルダに配置します。

wp-content > plugin に news-posts-pluginという名前のフォルダを作成します。

プラグイン名は他と被らないユニークな名前をつけてください。

 

作成したフォルダ内に、news-posts-plugin.phpというファイルを作成します。

news-posts-plugin.phpの中に、まずはこれだけ書いときましょう!

<?php
/*
Plugin Name: News Posts Plugin
Description: ニュース用の投稿を追加する
Version: 1.0
Author: Reo
*/
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

 

プラグインのヘッダーについてはこちらのWordPress Codexを参照してください。

配布しない自分用なので、色々端折っています。適当で大丈夫です。

 

ABSPATHとは・・・?

コメントアウト後の

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

この部分は、ABSPATHというグローバル定数がない場合はプラグインは読み込まないというものです。

ABSPATHは、「ABSPATHとはなんぞや。WordPressのインストールされたパスが定義されたグローバル定数らしい。」です。

 

自分はプラグイン作成を始めた時にAkismitのファイルを見ながら作っていて、その時にこの部分が書かれていたので真似して書いていたんですが、今見てみると書いてないですね。

なのでまぁいらないのかなーと思います。っていうかいらないですね。ABSPATH使ってないし(´・ω・`)

 

さて、この状態で管理画面のプラグインを見てみるとヘッダーに書いた情報が表示されているはずです。

 

カスタム投稿タイプを追加しよう

まだプラグインを有効化しても何も起きません。

【WordPress】カスタム投稿タイプの追加方法のコードが簡潔でわかりやすいので、そちらをお借りしてざっくりと説明させていただきます。

add_action( 'init', 'create_post_type' );
function create_post_type() {
    register_post_type( 'news', [ // 投稿タイプ名の定義
        'labels' => [
            'name'          => 'ニュース', // 管理画面上で表示する投稿タイプ名
            'singular_name' => 'news',    // カスタム投稿の識別名
        ],
        'public'        => true,  // 投稿タイプをpublicにするか
        'has_archive'   => false, // アーカイブ機能ON/OFF
        'menu_position' => 5,     // 管理画面上での配置場所
    ]);
}

リンク先ではこれをテーマ内のfunctions.phpに書いています。

 

これをプラグイン化するには、先ほど作ったnews-posts-plugin.phpにこのままコピペしちゃいましょう。

<?php
/*
Plugin Name: News Posts Plugin
Description: ニュース用の投稿を追加する
Version: 1.0
Author: Reo
*/

add_action( 'init', 'create_post_type' );
function create_post_type() {
    register_post_type( 'news', [ // 投稿タイプ名の定義
        'labels' => [
            'name'          => 'ニュース', // 管理画面上で表示する投稿タイプ名
            'singular_name' => 'news',    // カスタム投稿の識別名
        ],
        'public'        => true,  // 投稿タイプをpublicにするか
        'has_archive'   => false, // アーカイブ機能ON/OFF
        'menu_position' => 5,     // 管理画面上での配置場所
    ]);
}

ABSPATHのくだりはいらない気がしたので消しました。

これでプラグインを有効化してみましょう!はい!簡単!

これでも全然オッケーなのですが、この書き方だとcreate_post_type()という関数が他のプラグインにあると競合してエラーを起こしてしまいます

この書き方をする場合は、必ず他のプラグインと被らない名前をつけないといけません。

 

クラス化しよう!

先ほど書いた部分をクラスにしちゃいます。

class.news-posts-plugin.phpを追加します。クラスは別ファイルにすると良い派です。

先ほどのnews-posts-plugin.phpでこのクラスを読み込んでおきます。

<?php
/*
Plugin Name: News Posts Plugin
Description: ニュース用の投稿を追加する
Version: 1.0
Author: Reo
*/

define( 'NSPP_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );

// //ファイルの読み込み
require_once( NSPP_PLUGIN_DIR . '/class.news-posts-plugin.php' );

 

プラグインフォルダまでのパスを示す定数を作っておくと便利です。(この名前も他のプラグインと被ったらダメなので、適当に被らない添字的なのをつけておきます)

このファイルに書くことはこれだけです。

 

class.news-posts-plugin.phpを開きます。

<?php
/**
 * 
 * News_Posts_Plugin Common Settings .
 * 
 */

if ( !class_exists('News_Posts') ) {
    exit;
}

$NewsPosts = new News_Posts;

class News_Posts { 
    // ここに処理を書いていく
}

基本的にグローバル変数とクラス名は他と被らないものにする必要があります。

クラスが存在するかどうか判定して、存在する場合はここでインスタンス化しておきます。

 

クラス内に、

class News_Posts {

    // クラスがインスタンス化された時に呼ばれる
    function __construct() {
        add_action( 'init', array($this, 'create_post_type') );
    }

    function create_post_type() {
        register_post_type( 'news', [ // 投稿タイプ名の定義
            'labels' => [
                'name'          => 'ニュース', // 管理画面上で表示する投稿タイプ名
                'singular_name' => 'news',    // カスタム投稿の識別名
            ],
            'public'        => true,  // 投稿タイプをpublicにするか
            'has_archive'   => false, // アーカイブ機能ON/OFF
            'menu_position' => 5,     // 管理画面上での配置場所
        ]);
    }
}

先ほどのcreate_post_type()を貼り付けて、__construct内でアクションフックを書きます。

このadd_actionが結構肝。っていうか最初クラス化する時に地味にハマりました。

// クラス化しない場合
add_action( 'init', 'create_post_type' );

// クラス化する場合
add_action( 'init', array($this, 'create_post_type') );

クラス化する場合は配列にして関数の場所$thisを指定してあげないといけません。

 

あとはcreate_post_type()はそのままコピペするだけ!

これで先ほどクラス化しなかった場合と同じものができました。

 

作ったプラグインを使ってみよう!

最後に、作ったプラグインを使ってみましょう。

まずは、ダッシュボードからテスト投稿してみましょう。

テーマ内にsingle.phpがあれば、そのテンプレートを使用して表示してくれます。

記事一覧のページもarchive.phpがあれば・・・と思いましたが、ちょっとプラグイン側で変更しないとです。

class.news-posts-plugin.phpのcreate_posts_typeを変更します。

function create_post_type() {
    register_post_type( 'news', [ // 投稿タイプ名の定義
        'labels' => [
            'name'          => 'ニュース', // 管理画面上で表示する投稿タイプ名
            'singular_name' => 'news',    // カスタム投稿の識別名
        ],
        'public'        => true,  // 投稿タイプをpublicにするか
        'has_archive'   => true, // アーカイブ機能ON/OFF
        'menu_position' => 5,     // 管理画面上での配置場所
    ]);
}

10行目のhas_archiveをtrueにすればおkです。

そうすると、テーマにarchive.phpがあれば記事一覧ページを見ることができます。

テンプレートをカスタマイズしたい場合は、テーマ内にsingle-news.phpやarchive-news.phpを追加してください。

 

フロントページで使ってみよう!

実際にお知らせを表示する場所はおそらくフロントページになると思います。

フロントページにお知らせを表示する場合は、

front-page.phpに

<section class="top-content news" id="news">
    <div class="section-header">
        <h2>News</h2>
    </div>

    <?php get_template_part('content','front-news');?>

</section><!-- end .news -->

こんな感じのを書いておき、content-front-news.phpというファイルを追加します。(get_template_partで読み込み)

content-front-news.phpに

<?php 
$args = array(
    'posts_per_page' => 5,
    'post_type' => 'news'
);
$the_query = new WP_Query( $args );
if($the_query): 
?>
    <ul class="news-list">
        <?php
        while ( $the_query->have_posts() ) : $the_query->the_post();?>
            <li id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
                <a href="<?php the_permalink();?>">
                    <!-- date -->
                    <span class="news-date"><?php echo the_time('Y.n.j');?></span>
                    <?php the_title();?>
                </a>
            </li>
        <?php endwhile;?>
    </ul>
<?php else: ?>
    <p class="content-excerpt">お知らせはありません。</p>
<?php endif;?>
<?php wp_reset_postdata(); ?>

post_typeを指定してWP_Queryを使って表示させます。

これで表示されるはずです。

 

全体コード

基本的にfunctions.php に書いていたものは、このような手順で書きなおしてやるだけでプラグイン化することができます。

クラス化してフックは__construct内に書いとけば大体はええやろって感じです。

今回の全体コードはこんな感じです。

front-page.phpとcontent-front-news.phpはプラグインではなくテーマ内です!

 

最近になって仕事でWordPressプラグインを作って!と言われて、初めてWordPressプラグインを作り始めました。(今年5月くらい)

今までプラグインを作るなんて発想がなかったのですが、いざやってみるとこっちの方がいいじゃんと思い、これまでfunctions.php に書いていた処理でプラグイン化できるものはプラグイン化するようになりました。

 

実際に自分が作って利用しているものもGitHubにあげておきました。

uruly/News-Posts-Plugin: WordPress Plugin. Custom Post Type.

 

今回便宜上「【WordPress】カスタム投稿タイプの追加方法」のコードを勝手に利用させていただきました。すみません。(急に規約とかが気になってきた((((;´・ω・`)))

実際に利用している方との違いは、タクソノミーとかを加えているかどうかです。

 

それではでは〜。

Comments...

コメントは認証制です。詳しくは下記の注意をお読みください。お気軽にコメントお願いします!

Write a Comment

コメント時の注意

「Twitter」「Facebook」「Google+」「WordPress」のいずれかのアカウントをお持ちの方は各アカウントと連携することでコメントできます。 コメントしたことはSNSに流れませんので、アカウントをお持ちの方はこちらの方法でコメントを投稿して下さると嬉しいです。 アカウントをお持ちでない方はメールアドレスで投稿することができます。 初回コメント時は承認後に表示されます。

Related Memo...

【WordPress】メディアライブラリ の画像IDを取得する

WordPressのメディアライブラリ にアップロードされた画像IDを取得する方法です。

例えば6件取得してギャラリーで表示するとき。

$ids = get_posts( 
    array(
        'post_type'      => 'attachment', 
        'post_mime_type' => 'image', 
        'post_status'    => 'inherit', 
        'posts_per_page' => 6,
        'fields'         => 'ids',
    ) 
);

$ids_str = '';
foreach ( $ids as $id ) {
    $ids_str .= $id . ',';
}

$ids_str = rtrim($ids_str, ',');

// ショートコードでギャラリーを表示
echo do_shortcode( '[gallery ids="' . $ids .'"]' );

意外と便利なのでは!

 

WordPress

【WordPress】プラグイン化したカスタム投稿をテーマ内で使うとき

通常テーマ内でカスタム投稿を表示させる時に

$args = array( "posts_per_page" => 5,
        "post_type" => 'news'
    );
$the_query = new WP_Query( $args );
if($posts):

と書けば表示されるのに、プラグイン化していたので表示されなかった話。

 

functions.phpでカスタム投稿を追加している場合は必要ないが、newsというカスタム投稿をプラグイン化していたので、以下の記述が必要でした。

    public function __construct() {
        add_action( 'pre_get_posts', array($this, 'add_my_post_types_to_query') );
    }

    // queryにnewsをセットする
    function add_my_post_types_to_query( $query ) {
        if ( is_home() && $query->is_main_query() )
            $query->set( 'post_type', array( 'post', 'page', 'news' ) );
        return $query;
    }

WordPressプラグインの作り方は、また後日ちゃんとした記事にしたいと思ってます。今回はとりあえず忘れそうなのでメモだけで失礼。

WordPress

WordPressで現在のカテゴリから親カテゴリ/祖先カテゴリのスラッグを取得

//現在のカテゴリを取得
$categories = get_the_category($post->ID);
$category_slugs = array();
foreach($categories as $category){
    $cat = $category;
    array_push($category_slugs,$cat->slug);
    //親のカテゴリがなくなるまで回す
    while ($cat->parent) {
        $cat_parent_id = $cat->parent;
        $cat = get_category($cat_parent_id);
        array_push($category_slugs,$cat->slug);
    }
}

わりと頑張ってPHP書いてる。

WordPress
more