初めてWordPressテーマを自作してみた。知識が無い素人でも、調べながらやってみる。#2【テーマ実装】

目次

実装を始める前の準備として、デザインの検討やWordPress動作の勉強については、#1の記事で紹介しています。今回は、そちらの記事の続きからになります。

PHPファイルを触りながら、テンプレートの仕組みを学ぶ

さて、ここまでの理解では、「https://localhost/テーマ名」のようにWordPressのWebサイトにアクセスすると、テーマフォルダにあるindex.phpにアクセスしているようでした。

その理解が正しいのか確かめるため、index.phpをほぼ白紙で作ってみて、アクセスの実験してみます。何も書かれていない真っ白な状態が表示されると予想されます。

結果・・・そもそもテーマ自体を読み込むことができませんでした。何故だ・・・?

壊れているテーマと表示されます。

ググってみると、どうやらテーマにはindex.phpだけでなく、style.cssも必須だそうです。

いやいや、cssフォルダにstyle.cssもちゃんと存在しているのですが・・・。

どうやらテーマフォルダ直下に存在する必要があるらしいです。直下にすると読み込めました。

次に、初めてWordpress関数を使ってみます。

get_header()という関数を書くだけで、header.phpを読み込んでくれるらしいです。

index.phpに記載してみます。現状はheader.phpを作成していないのでエラーになると予想

すると、エラーにならず、白紙にもならず、勝手にタイトルが表示されました。しかも知らないメタタグやスクリプトも記載されています。

どうやらheader.php ファイルがテーマに含まれていない場合は、デフォルトテーマの 「wp-includes/theme-compat/header.php 」を読み込む模様でした。

ということで、白紙のheader.phpを作ってみると、サイトも白紙になりました。特にソースも出力されていない。

ちゃんとテーマの方のheader.phpファイルが優先されて読み込まれているようです。

ここまでで、なんとなーくテンプレートファイルの使い方や動きの理解が深まったところで、本格的にテーマを作っていきます。

トップページを作ってみる

さて、トップページの作成取り掛かりますが、ファイル分割など細かいことは考えず、まずはindex.phpにすべて集約して記載していきます。

といっても、すでに見た目だけならHTMLで作成しているので、やることはHTMLで作ったソースをコピペして、cssやimgファイルへのパスをWordPressの関数で取得するように置き換えただけです。

ほぼHTMLのままなので、苦労することなく表示できました。静的な画面であればこれで完成です。

しかし、記事の内容や数は、もちろん変動するので、動的に表示できるように記事の一覧をWordPress関数を使って作ってみました。

ちなみに、記事の情報を取得するにはhave_posts()を使い、while文でループさせながら個々の記事情報を取得します。基本的なやり方らしいので、詳しいことは検索するとすぐに出てきます。

なんかエラー発生。エラー内容を見るに、タグ表示の処理でエラーが起きているっぽいです。

そういえばタグ設定をローカル環境では一つもしていなかったので、Nullで落ちていると予想します。Nullチェック処理を入れて、タグがなければスルーする処理に変更することで、エラー解消できました。

空白ができない謎

HTMLコピペ部分はタグの隙間があるのだが、PHPで動的に生成している部分は空白が詰められています。

開発者ツールで、空白が詰められている部分と空いている部分を見比べてみたが、まったく違いがない。マージンやパディングの問題ではなさそう・・・?

何故だーっとめっちゃ悩んだが、簡単な話でした。実は元のHTML構造では改行が入っているが、PHPでwordpress関数を使い、動的にHTMLを出力するときは、改行が出力され無かった。ここが直接的な原因。

HTMLの仕様として、空白、タブ、改行は空白として解釈されるらしいです。

なので、最初に作成したHTMLファイルのタグ表示では隙間があったが、PHPの動的出力では 改行が削除されたHTMLが作成されてしまったということですね。

対応としては、改行ではなく、タグにme-1クラス(Bootstrapのマージン設定ができるクラスです)を設定することでマージンを設定し、隙間を作りました。

投稿管理画面でサムネイルをする項目が無い

トップページの投稿記事一覧部分でサムネイルを動的に出したいので、投稿管理画面にてサムネイルを設定しようと思ったが、そもそも設定する項目が無いです・・・。普通のテーマではあるのに・・・。

調べてみたら、add_theme_support(‘post-thumbnails’);という設定が必要らしいです。function.phpに設定したら、サムネイル設定項目が出てきました。

また、サムネイル無の場合、画像を何も表示しないのではなく、黒背景でno thumbnailと記載されたSVGを出すように条件分岐させました。

ここまで作ったトップページのPHP

index.php

PHPCOPY
<?php
/**
 * WordPress Theme
 * @author: taishi
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 * @link https://surukoto.jp/
 * @package surukoto
 */

get_header();
?>
<!-- コンテンツ -->
<div class="container overflow-hidden" id="surukoto-content">
    <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 px-4">
    <?php if( have_posts() ): ?>
        <?php while( have_posts() ) : the_post(); ?>
           <div class="col">
            <div class="card">
               <a href="<?php esc_url(the_permalink()); ?>">
                   <?php if (has_post_thumbnail()):?>
                       <img src="<?php the_post_thumbnail_url(); ?>" class="card-img-top" alt="<?php get_the_title(); ?>" />
                   <?php else: ?>
                       <svg class="card-img-top" viewBox="0 0 256 144">
                            <rect width="100%" height="100%" fill="#55595c"/>
                           <text x="50%" y="50%" fill="#eceeef" text-anchor="middle" dominant-baseline="central">no thumbnail</text>
                       </svg>
                    <?php endif; ?>
               </a>
               <div class="card-body">
                    <a href="<?php esc_url(the_permalink()); ?>">
                       <p class="card-title surukoto-card-title"><?php the_title(); ?></p>
                    </a>
                    <div class="card-text surukoto-card-text">
                        <span class="me-2"><?php echo get_the_modified_date(); ?></span>
                       <?php
                            $tags = get_the_tags();
                           if ( $tags ) {
                                foreach( $tags as $tag) {
                                   echo '<a href="'. get_tag_link($tag->term_id) .'" class="me-1"><span class="badge bg-secondary">' . $tag->name . '</span></a>';
                                }
                           }  
                       ?>
                   </div>
               </div>
           </div>
        </div>
        <?php endwhile; ?>
    <?php endif; ?>
    </div>
</div>
<!-- フッター -->
        <footer class="footer py-3 mt-5 bg-dark text-light">
            <div class="container text-center">
                <ul class="nav justify-content-center mb-3">
                    <li class="nav-item">
                    </li>
                    <li class="nav-item">
                    </li>
                    <li class="nav-item">
                    </li>
                </ul>
           
            <p class="footer-copyrigtht"><small>Copyright &copy;2022 Surukoto LAB, AllRights Reserved.</small></p>
        </div>
        </footer>
  </body>
</html>

投稿記事の参照ページを作ってみる

トップページの投稿記事一覧部分にリンクを張り、個別の投稿ページに遷移する、という動きをするにはどうしたらいいのか?また、そもそも投稿ページが無いと話が始まらないので、投稿ページの用意を考えます。

調べてみたらsingle.phpという名前で投稿ページのテンプレートファイルを用意するらしいです。

single.phpが存在しない場合の遷移実験

とりあえず、single.phpファイルを用意する前に、一覧からリンクを張ってみます。

当然、リンク先は無いので、そのリンクから飛んだらどうなるのかの実験。普通に考えたらNullとかNotFoundのエラーがでるのではないでしょうか?

ちなみに、リンクは<?php esc_url(the_permalink()); ?>と記載すれば良いっぽい。画像とタイトルをaタグで挟んでみました。

結果、エラーにならず、index.phpに戻っているっぽい・・・?

おそらくテンプレファイルがなければindex.phpを呼び出していると思れます。記事数が1つなのは、リンクを押下したときに送信する情報が、そのリンク先予定の記事情報を送っているだけだと想定。

だから、取得できる情報として1つしか一覧に出てないのだろう。また、投稿ページのsingle.phpテンプレファイルを用意してみると、白紙に遷移しました。

あとは、作る前の疑問として、元ネタとなる投稿内容の情報はどうやって取得すればいいのか・・・?

調べてみると、トップページと同じようにhave_posts()とthe_postを使えば、the_title()なども使用できて、記事情報を表示するだけなら簡単な模様。

ここまでで動きは確認できたので、中身を作っていきます。

目次を毎回手で作るのではなくて、自動で作れるようにしたい!

Parse_blocksというものでコードを配列にして、分析しやすくして、見出し構造を作っていくという考えを見つけました。以下のサイトを参考にしました。

https://digipress.info/wordpress/tips/table-of-contents-with-parse_blocks/

ブロックエディタの場合は可能らしいが、クラシックの場合はダメらしい。自分はクラシックを使わなくても良いので、問題ない。採用です。

作成したのはこんな感じ。

2つ目次がありますが、上がHTMLファイルをコピペしたやつです。下がWordPress関数等を駆使して作成したやつです。動的に出力することができましたね。

ただ、一部、なぜか箇条書き形式になってポチが記載されてしまう。

これは見出しレベルが直前より高いときの処理が2重になっていた。不要な記述を削除することで解消。

また、上記サイトのままではH2が最初に来たときのみ正常に動く。いきなりH3やH4が来ても、バグらないようにします。

つまり、ほぼほぼ無いパターンだが、見出しの1番目が最高レベルじゃない場合も対応したということです。

function.php

PHPCOPY
//見出し作成機能
function generate_my_toc( $content ){
 
    // 投稿ページのメインループ内のときのみ
    if ( is_single() && in_the_loop() && is_main_query() ) {

        // 目次コード用
        $toc_code = '';

        // 番号あり : ol, 番号なし : ul
        $list_tag = 'ul';

        // 階層レベルチェック用
        $current_level = $previous_level = $max_level = 1;

        // カウンター
        $index = 0;

        // 見出しタグ抽出用
        $reg = "/(<h([1-6]).*?>)(.*?)(<\/h[1-6]>)/";

        // 本文テキストをブロックごとにパース
        $blocks = parse_blocks( $content );

        $count_current_level = 1;
        $count_index = 0;
        // 見出しの最大レベルをあらかじめ知っておく
        foreach ( $blocks as $key => $count_block ) {
            // 見出しブロックの場合
            if ( $count_block['blockName'] == 'core/heading' ) {
                // 見出しタグを解析
                if ( preg_match( $reg, $count_block['innerHTML'], $count1 ) ) {
                    // 現在のレベルを取得
                    $count_current_level = (int)$count1[2];
                    // 1番目の見出しレベルを保持
                    if ( $count_index == 0 ) {
                        $max_level = $count_current_level;
                    }
                    //最大レベルを更新
                    if($max_level > $count_current_level){
                        $max_level = $count_current_level;
                    }
                    ++$count_index;
                }
            }
        }

        // パースしたブロックを順番に処理
        foreach ( $blocks as $key => $block ) {
            // 見出しブロックの場合
            if ( $block['blockName'] == 'core/heading' ) {

                // 見出しタグを解析
                if ( preg_match( $reg, $block['innerHTML'], $m1 ) ) {
                    // 現在のレベルを取得
                    $current_level = (int)$m1[2];
                    // 本文内の見出しタグの置換
                    $content = preg_replace_callback( "/(<h[1-6].*?>)(" . preg_quote( $m1[3], '/' ) . ")(<\/h[1-6]>)/", function( $m2 ) use ( &$index ) {
                        // 見出しタグ内を span で括って ID を付けて入れ替える
                        return '<span id="i-' . $index . '">' . $m2[1] . $m2[2] . $m2[3] . '</span>';
                    }, $content );

                    // 1番目または現在の見出しレベルと直前の見出しレベルが同じとき
                    if ( $index == 0 || $current_level == $previous_level ) {
                        // 1番目以外は直前の見出しレベルに閉じタグ(</li>)を付ける
                        if ( $index > 0  ) {
                            $toc_code .= '</li>';
                        }
                        //最大レベルならば線を引くクラスを適用、それ以外ならスタイルなしを適用。1番目が最大レベルであることが前提
                        if($index == 0 || $current_level == $max_level){
                            $toc_code .= '<li class="surukoto-article-agenda-li py-2">'. str_repeat( '<' . $list_tag . ' class="list-unstyled"><li class="ps-3 pt-2">', $current_level - $max_level ) . '<a href="#i-' . $index . '">' . $m1[3] . '</a>';
                        }else{
                            $toc_code .= '<li class="ps-3 pt-2"><a href="#i-' . $index . '">' . $m1[3] . '</a>';
                        }
                       
                    // 現在の見出しレベルが直前よりも高いとき
                    } else if ( $current_level < $previous_level ) {
                        //最大レベルならば線を引くクラスを適用、それ以外ならスタイルなしを適用。1番目が最大レベルであることが前提
                        if($current_level == $max_level){
                            $toc_code .= '</li>'. str_repeat( '</' . $list_tag . '></li>', $previous_level - $current_level ) . '<li class="surukoto-article-agenda-li py-2"><a href="#i-' . $index . '">' . $m1[3] . '</a>';
                        }else{
                            $toc_code .= '</li>'. str_repeat( '</' . $list_tag . '></li>', $previous_level - $current_level ) . '<li class="ps-3 pt-2"><a href="#i-' . $index . '">' . $m1[3] . '</a>';
                        }

                    // 現在の見出しレベルが直前よりも低いとき
                    } else {
                        $toc_code .= '<' . $list_tag . ' class="list-unstyled"><li class="ps-3 pt-2"><a href="#i-' . $index . '">' . $m1[3] . '</a>';
                    }

                    // 現在の見出しレベルを保持
                    $previous_level = (int)$m1[2];
                    // インクリメント
                    ++$index;
                }
            }
        }

        if ( !empty( $toc_code ) ) {
            // 目次リストの整形
            $toc_code = '<div class="surukoto-article-agenda p-3 mb-5"><p class="surukoto-article-agenda-title">' . __( '目次' ) . '</p><' . $list_tag . ' class="surukoto-article-agenda-list list-unstyled">' . $toc_code . '</li>' . str_repeat( '</' . $list_tag . '></li>', ( $previous_level - $max_level ) ) . '</' . $list_tag . '></div>';
            // 本文の先頭に目次リストを追加
            return $toc_code . $content;
        }
    }
    return $content;
}
add_filter( 'the_content', 'generate_my_toc', 1 );

オリジナルの下線装飾を作りたい!

色々調べる前に・・・。そもそもエディタに下線を引くブロックがないんやが・・・

調べてみたら、ブロックエディタになってから下線ツールはなくなった模様。Ctrl+Uでつけれるとの噂。

確かにつけれた。が、標準の下線なので、CSSで指定しているオリジナルクラスを適用できない。

オリジナルのブロックツールを追加できないか?以下のサイトを参考に作成してみました。

https://www.vektor-inc.co.jp/post/gutenberg-blocks-development-without-build/

下線ブロックのスクリプトを作って、Function.phpでそれをactionに追加するように記載したら、動くには動きました。

ただし、これはあくまでブロック単位です。

やりたいことは、段落ブロックの中の文字に対して使えるツールとして追加したい。太文字と同じ感じで実装したいです。

以下のサイトを見る限りregisterFormatTypeがキーワードっぽい・・・?。

今の自分では、よく理解できなかったので、他に調べてみると以下のサイトにたどり着きました。

https://elearn.jp/wpman/column/c20211119_01.html

深くは理解していないが、とりあえず、できました。

function.php

PHPCOPY
add_action('enqueue_block_editor_assets', function ($hook_suffix) {
    // CSSディレクトリの設定
    $uri = get_template_directory_uri() . "/css/editor-style.css";
    // CSSファイルの読み込み
    wp_enqueue_style("editor-style-css", $uri, array(), wp_get_theme()->get('Version'));
    // JSディレクトリ
    $uri = get_template_directory_uri() . "/js/editor-style.js";
    // JSァイルの読み込み
    wp_enqueue_script('editor-style-script', $uri, array(), wp_get_theme()->get('Version'), true);
});

editor-style.js

PHPCOPY
( function ( wp ) {
    var paragraphUnderlineButton = function ( props ) {
        return wp.element.createElement(
            wp.blockEditor.RichTextToolbarButton,
            {
                icon: 'editor-underline',
                title: '下線',
                onClick: function () {
                    props.onChange(
                        wp.richText.toggleFormat(
                            props.value,
                            {
                                type: 'paragraph-ex/underline',
                            }
                        )
                    );
                    props.onFocus();
                },
            }
        );
    }

    wp.richText.registerFormatType(
        'paragraph-ex/underline',
        {
            title: '下線',
            tagName: 'span',
            className: 'surukoto-article-under',
            edit: paragraphUnderlineButton
        }
    );
} )( wp );

editor-style.css

CSSCOPY
/* オリジナル下線*/
.surukoto-article-under {
    background: linear-gradient(transparent 70%, #a8eaff 70%);
}

ヘッダー部分を共通部品にしたい

トップページや記事参照ページに、同じヘッダーが記載されています。今後もページが増えることを想定すると共通部品にしておきたいです。

最初にheader.phpを勉強がてら作っていたと思います。ヘッダー部分を切り取って、そちらへコピペするだけです。

ページによって異なる箇所はどう対応するのか?

例えば、トップの一覧ページと、記事参照のページで、読み込むCSSを変えたい場合などです。

以下のサイトを参考にしました。

headerにCSSやJavaScriptのリンクを記載するのではなく、function.phpに各リンクの読み込みを登録する方法を推奨しています。とくに反論はないし、だめなら変えればいいので、それでやってみた。

https://www.at-freak.jp/column/wordpress_css/

記載してみたが、読み込まれない。なぜか・・・?

wp_enqueue_scripts はwp_head()で実行されているアクションフックらしく、wp_head()を実行していないので、そのアクションフックも動かない模様。

header.phpの閉じタグ直前でwp_head()を呼び出すようにすると、解決しました。

BootstrapのCDNが読み込めない。

function.phpで、CSSと同じように登録したが、読み込めません。

どうやら、https:がいらない。//から記載するらしいです。

また、第3引数以降は不要っぽい。入れると読み込まれなかった。これで元通り表示されるようになりました。

function.php

HTMLCOPY
// bootstrap の読み込み
    wp_enqueue_style(
        'bootstrap',
        '//cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css'
    );

フッター部分を共通部品にしたい

ヘッダーと同じくですね。コピペしただけです。

こちらはfooter.phpがテンプレファイルのようです。

特にコンテンツがないので、コピーライトをそれっぽく適当に作ったぐらいです。

とりあえず、共通部品として用意しただけ。やること無い。

footer.php

PHPCOPY
<?php
/**
 * WordPress Theme
 * @author: taishi
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 * @link https://surukoto.jp/
 * @package surukoto
 */
?>
        <!-- フッター -->
        <footer class="footer py-3 mt-5 bg-dark text-light">
            <div class="container text-center">
//なんかリンクとか出しておくなら、と思って枠だけ用意。今は何もなし。
                <ul class="nav justify-content-center mb-3">
                    <li class="nav-item">
                    </li>
                    <li class="nav-item">
                    </li>
                    <li class="nav-item">
                    </li>
                </ul>
           
            <p class="footer-copyrigtht"><small>Copyright &copy;2022 Surukoto LAB, AllRights Reserved.</small></p>
        </div>
        </footer>
  </body>
</html>

タグページを作ってみる

タグをクリックしたときに、そのタグが付いている記事の一覧を見るためのタグページを作成します。

tag.phpがテンプレファイル名で、それを作っておけば、タグのリンク(get_tag_link())で遷移するときに自動で呼び出されるようです。

やることはindex.phpをコピペして、なんのタグの一覧かが分かるように、タグ名の表示処理を付けたぐらいです。タグ名を出す関数はsingle_cat_title()です。以下を参考。

http://webdesign.practice.jp/wordpress-theme13-category-php

tag.php

PHPCOPY
    <div class="row border-bottom mb-4 mx-4">
        <div class="col">
            <span class="surukoto-category-title me-2">tag : </span>
//ここでタグ名取得
            <span class="surukoto-category-name"><?php single_cat_title() ?></span>
        </div>
    </div>
    <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 p-4">
    <?php if( have_posts() ): ?>
        <?php while( have_posts() ) : the_post(); ?>
            //~~~記事一覧のロジック~~~
        <?php endwhile; ?>
    <?php endif; ?>
    </div>

全記事一覧ページを作ってみる

トップページに表示しきれない記事も含めて、過去全記事を参照するための一覧ページを作ります。

tag.phpのベースをざっと作る

tag.phpと基本的には同じです。違いは遷移の方法ぐらい。

まずは以下のサイトを参考にしました。

https://miya-system-works.com/blog/detail/159

一覧ページのテンプレファイルはarchive.phpらしいです。

先の参考サイトではよくわからなくなってきたので、次のサイトをさらに参考。

https://kbyt-programming.com/wordpress/parts_archive-page/

さらに以下を参考。

https://satoshimurata.com/wordpress-archive-another-url

function.php

PHPCOPY
/* ========================================================
アーカイブページ(archive.php):アーカイブを有効化
=========================================================*/
function post_has_archive($args, $post_type){
    if('post'== $post_type){
      $args['rewrite']=true;
      $args ["label"] = '投稿';
      $args['has_archive']='archive';
    }
    return $args;
  }
  add_filter('register_post_type_args', 'post_has_archive', 10, 2);

archive.php

PHPCOPY
<?php
/**
 * WordPress Theme
 * @author: taishi
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 * @link https://surukoto.jp/
 * @package surukoto
 */

get_header();
?>

<!-- コンテンツ -->
<div class="container overflow-hidden mb-5" id="surukoto-content">
    <div class="row border-bottom mb-4 mx-4">
        <div class="col">
            <span class="surukoto-category-title me-2">tag : </span>
            <span class="surukoto-category-name">全ての記事一覧</span>
        </div>
    </div>
    <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 p-4">
    <?php if( have_posts() ): ?>
        <?php while( have_posts() ) : the_post(); ?>
//記事一覧の部分は別ファイルにコピペして、共通部品にしている。
            <?php get_template_part( 'template-parts/content' ); ?>
        <?php endwhile; ?>
    <?php endif; ?>
    </div>
</div>
<!-- ここまでコンテンツ -->
<?php get_footer(); ?>

ページ送りをするためのページャーを作る

ページャーの用意もしないといけない。今は全記事表示されているので必要ないが、1ページの最大表示件数を設けて、それを超えるのであれば必要になります。

アーカイブを参考にしたサイトから、さらに以下の記載があった。以下参考です。

https://kbyt-programming.com/wordpress/parts-pagination/

<?php the_posts_pagination(); ?>だけでページャーは出せるらしい。

PHPCOPY
<?php
/**
 * WordPress Theme
 * @author: taishi
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 * @link https://surukoto.jp/
 * @package surukoto
 */

get_header();
?>

<!-- コンテンツ -->
<div class="container overflow-hidden mb-5" id="surukoto-content">
    <div class="row m-3">
        <?php the_posts_pagination($args); ?>
    </div>
    <div class="row border-bottom mb-4 mx-4">
        <div class="col">
            <span class="surukoto-category-title me-2">tag : </span>
            <span class="surukoto-category-name">全ての記事一覧</span>
        </div>
    </div>
    <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 p-4">
    <?php if( have_posts() ): ?>
        <?php while( have_posts() ) : the_post(); ?>
            <?php get_template_part( 'template-parts/content' ); ?>
        <?php endwhile; ?>
    <?php endif; ?>
    </div>
    <div class="row m-3">
        <?php the_posts_pagination($args); ?>
    </div>
</div>
<!-- ここまでコンテンツ -->
<?php get_footer(); ?>

ページャー出ないんだが・・・。

どうやら、ページを分ける必要がないときは表示されないらしいです。

1ページの最大表示件数を減らして、複数ページを出るようにして、ページャーを確認してみます。

ちなみに最大表示件数はposts_per_pageで設定できるようです。

でましたね。レイアウトもしょぼいので色々整えます。

function.php

PHPCOPY
/* 特定のページの1ページあたりの表示数を変更する */
function change_posts_per_page($query) {
    if ( is_admin() || ! $query->is_main_query() ) /* メインクエリでの表示数 */
        return;
    if ( $query->is_archive() ) { //アーカイブページの場合
        $query->set( 'posts_per_page', '2' ); /* 表示件数を指定する。-1で全件表示できる */
    }
}
add_action( 'pre_get_posts', 'change_posts_per_page' );

archive.php

PHPCOPY
<?php
/**
 * WordPress Theme
 * @author: taishi
 * @license: http://www.gnu.org/licenses/gpl-2.0.html GPL v2 or later
 * @link https://surukoto.jp/
 * @package surukoto
 */

get_header();
$args = array(
    'mid_size' => 2,
    'prev_text' => '&lt;&lt;前へ',
    'next_text' => '次へ&gt;&gt;',
    'screen_reader_text' => ' ',
);
?>

<!-- コンテンツ -->
<div class="container overflow-hidden mb-5" id="surukoto-content">
    <div class="row m-3">
        <?php the_posts_pagination($args); ?>
    </div>
    <div class="row border-bottom mb-4 mx-4">
        <div class="col">
            <span class="surukoto-category-title me-2">tag : </span>
            <span class="surukoto-category-name">全ての記事一覧</span>
        </div>
    </div>
    <div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 p-4">
    <?php if( have_posts() ): ?>
        <?php while( have_posts() ) : the_post(); ?>
            <?php get_template_part( 'template-parts/content' ); ?>
        <?php endwhile; ?>
    <?php endif; ?>
    </div>
    <div class="row m-3">
        <?php the_posts_pagination($args); ?>
    </div>
</div>
<!-- ここまでコンテンツ -->
<?php get_footer(); ?>

tag.css

CSSCOPY
/* -----------------------
    ページネーション
  ----------------------- */
  /* pagination */
  .pagination {
    justify-content: center;
  }

  /* リンクの枠 */
  .pagination .nav-links {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    justify-content: center;
    gap: 8px;
  }

  /* 数字のリンク */
  .pagination .nav-links .page-numbers {
    text-decoration: none;
    color: #333;
    border: 1px solid #aaa;
    display: inline-block;
    border-radius: 6px;
    padding: 0.5em 0.8em;
    -webkit-transition: .3s;
    transition: .3s;
  }

  /* 現在のページ */
  .pagination .nav-links .current {
    background-color: #333;
    color: #fff;
  }

  /* 現在のページとドット以外にホバーした時 */
  .pagination .nav-links a:hover {
    background-color: #333;
    color: #fff;
  }

記事一覧部分を共通部品にする

ここまでのソースコードの中に既に記載していますが、改めて紹介します。

tag.phpとindex.phpのコンテンツ部分が同じであり、共通化させたほうが手間が減ると思ったので、共通PHPを作っています。

template-partsと呼ばれるものを作ります。

記事一覧の処理をcontent.phpに移して、index.phpとtag.php、archive.phpで共通的に利用できるようにしました。各phpでのcontent.phpの呼び出し方は<?php get_template_part( ‘template-parts/content’ ); ?>を記載です。

参考サイトを見ていると、get_template_part()の第二引数にget_post_format( $id )を入れているサンプルが多数。使い道がいまいちわからないのと、今必要なさそうなので、使っていません。

content.php

PHPCOPY
<div class="col">
    <div class="card">
        <a href="<?php esc_url(the_permalink()); ?>">
            <?php if (has_post_thumbnail()):?>
                <img src="<?php the_post_thumbnail_url(); ?>" class="card-img-top" alt="<?php get_the_title(); ?>" />
            <?php else: ?>
                <svg class="card-img-top" viewBox="0 0 256 144">
                    <rect width="100%" height="100%" fill="#55595c"/>
                    <text x="50%" y="50%" fill="#eceeef" text-anchor="middle" dominant-baseline="central">no thumbnail</text>
                </svg>
            <?php endif; ?>
        </a>
        <div class="card-body">
            <a href="<?php esc_url(the_permalink()); ?>">
                <p class="card-title surukoto-card-title"><?php the_title(); ?></p>
            </a>
            <div class="card-text surukoto-card-text">
                <span class="me-2"><?php echo get_the_modified_date(); ?></span>
                <?php
                    $tags = get_the_tags();
                    if ( $tags ) {
                        foreach( $tags as $tag) {
                            echo '<a href="'. get_tag_link($tag->term_id) .'" class="me-1"><span class="badge bg-secondary">' . $tag->name . '</span></a>';
                        }
                    }  
                ?>
            </div>
        </div>
    </div>
</div>

ここまでで必要なページの作成ができました。

最後に細かい機能を実装していきます。機能の実装については#3で紹介します。

Weekly Most Popular
記事書いたりサイト運営してる人
シイタ / siita
シイタ / siita
現役サラリーマン/システムエンジニアです。 会社外でも、自分に自信を持って活躍できるようになりたい。金銭的にも安心できるようになりたい。という気持ちから技術向上や不労所得を得るために、日々活動することを記録し、共有していきます。