pas-polのサイトを模写コーディングしてみよう!
こちらも有名なサイト「🔗PAS-POL」を模写コーディングしてみましょう!
模写コーディングでWordPressの基本的な実装方法を知りましょう。
実際の案件で丁寧に「ここはこれを使って実装してね」と言われることはほとんどないので、
色んな実装方法を知ることで、自分の好みの実装や、案件によって実装方法を使い分けたりできるかと思います。
※他人が作ったコードも読みやすくなるでしょう。
(注意)ここではコピペで作れないように制作の流れしか紹介しません。コードは自分で実装しましょう!
課題を通して、実務で使う以下の機能を覚えましょう
- 自作テーマを作成できるようになる
- WordPressのテンプレート階層を学び、適切なファイルを選択・作成する
- functions.phpで「外部ファイルの読み込み」「機能の拡張」を経験する
- WordPressでよく使うタグを学ぶ
- ヘッダーやフッターなど、共通パーツを分割する方法を学ぶ
- カスタム投稿の実装方法、「アーカイブページ(記事一覧ページ)」「投稿ページ」を学ぶ
- プラグインを使ってカスタムフィールドを学ぶ
- Contact Form 7を使って、「お問い合わせページ」「確認画面ページ」「サンクスページ」を作る
- 404ページ
- Basic認証
- reCAPTCHA
WordPressの開発環境がまだの方は下記のページを参考に構築してしまいましょう
https://www.moncoure.com/web/local
どんなサイト?
あくまで作りについてです。
・TOPページやお問い合わせページがあります。
・NewsとProductの投稿が2つありますね。それぞれに、一覧ページと詳細ページがあります。
ファイル構成
実装方法の好みもありますが、WordPressのテンプレート階層を参考に、下記のような構成などが考えられます。
.
├── archive-news.php //Newsの一覧ページ
├── archive-products.php //productの一覧ページ
├── assets
│ ├── css
│ │ ├── reset.css //共通のCSS
│ │ ├── common.css //共通のCSS
│ │ ├── front.css //topページ用
│ │ ├── news.css //ニュース用
│ │ └── product.css //プロダクトページ用
│ ├── images
│ ├── js
│ │ └── product.js
│ │ └── news.js
│ └── scss
├── front-page.php // TOPページ用
├── functions.php // CSS,JSの読み込み、カスタム投稿の追加
├── index.php
├── header.php
├── footer.php
├── single-news.php // News用のページ
├── single-product.php // プロダクト用のページ
├── page-contact.php // プロダクト用のページ
├── page-confirm.php // プロダクト用のページ
├── page-thanks.php // プロダクト用のページ
├── screenshot.png
└── style.css
SCSSなどは、好みでファイルを分けても良いですね。
・TOPページ:front-page.php
・一覧ページ:archive.php
・詳細ページ:single.php
・お問い合わせページ:固定ページ
で作ってみましょう。
メインビジュアルのスライドショー
実装方法が、ライブラリを使う方法とjQueryでの実装、WordPressのプラグインを使う方法がありますね。
選択肢を増やすために、できれば、使ったことないライブラリは一度使ってみて欲しいです👍
pas-polは「🔗Flexslider」というjQueryのプラグインを使っているようです。
私は慣れている、こちらもjQueryのプラグイン「🔗Slick」で実装しました。
他にも「🔗Swiper」などあるので使ってみましょう!
ヘッダーやフッターを作ろう
header.phpやfooter.phpファイルを作りましょう。
呼び出すときは、
<?php get_header(); ?>
<?php get_footer(); ?>
のコードで呼び出せましたね。
header.phpには</header>まで入れてOKです。
<?php wp_head(); ?>を忘れずに入れましょう!
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SAMPLE</title>
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<header class="header">
<h1 class="header__logo">
<a href="/" class="header__logo-link">LOGO</a>
</h1>
<nav class="header__navigation">
<ul class="navigation__list">
<li class="navigation__item"><a href="<?php echo home_url('/'); ?>" class="navigation__link">TOP</a></li>
<li class="navigation__item"><a href="/" class="navigation__link">PRODUCT</a></li>
<li class="navigation__item"><a href="/" class="navigation__link">ABOUT</a></li>
<li class="navigation__item"><a href="/" class="navigation__link">NEWS</a></li>
<li class="navigation__item"><a href="/" class="navigation__link">CONTACT</a></li>
</ul>
<div class="navigation__toggle">MENU</div>
</nav>
</header>
footer.phpには、footerタグまで入れますね。
<?php wp_footer(); ?>は忘れずに入れましょう。
<footer class="footer">
</footer>
<?php wp_footer(); ?>
</body>
</html>
functions.phpでスタイルシートやスクリプトファイルを読み込もう
<?php
/**
* Enqueue scripts and styles.
*/
function theme_enqueue_assets()
{
// WPデフォルトのjQueryを読み込む
wp_enqueue_script('jquery');
// slickのスタイルシートを読み込む
wp_enqueue_style(
'slick-css', // ハンドル名
get_template_directory_uri() . '/assets/js/slick-1.8.1/slick/slick.css', // slick.cssのパス
array(), // 依存関係なし
'1.8.1' // バージョン
);
wp_enqueue_style(
'slick-theme-css', // ハンドル名
get_template_directory_uri() . '/assets/js/slick-1.8.1/slick/slick-theme.css', // slick-theme.cssのパス
array('slick-css'), // slick.cssに依存
'1.8.1' // バージョン
);
// slickのJavaScriptファイルを読み込む
wp_enqueue_script(
'slick-js', // ハンドル名
get_template_directory_uri() . '/assets/js/slick-1.8.1/slick/slick.min.js', // slick.min.jsのパス
array('jquery'), // jQueryに依存
'1.8.1', // バージョン
true // フッターで読み込む
);
// JavaScriptファイルを読み込む
wp_enqueue_script(
'custom-index-js',
get_template_directory_uri() . '/assets/js/index.js',
array('slick-js'), // slickに依存
'1.0.0',
true
);
// 共通のCSSファイルとJavaScriptファイルを読み込む
wp_enqueue_style('reset-style', $theme_directory . '/assets/css/reset.css');
wp_enqueue_style('common-style', $theme_directory . '/assets/css/common.css', array('reset-style'), null);
wp_enqueue_script('common-script', $theme_directory . '/assets/js/common.js', array('jquery'), null, true);
// front-page.php のみで読み込むCSSとJavaScript
if (is_front_page()) {
wp_enqueue_style('front-style', $theme_directory . '/assets/css/front.css', array('common-style'));
wp_enqueue_script('front-script', $theme_directory . '/assets/js/front.js', array('jquery'), null, true);
}
// news 投稿タイプ用のCSSとJavaScript
if (is_singular('news') || is_post_type_archive('news')) {
wp_enqueue_style('news-style', $theme_directory . '/assets/css/news.css', array('common-style'));
wp_enqueue_script('news-script', $theme_directory . '/assets/js/news.js', array('jquery'), null, true);
}
// product 投稿タイプ用のCSSとJavaScript
if (is_singular('product') || is_post_type_archive('product')) {
wp_enqueue_style('product-style', $theme_directory . '/assets/css/product.css', array('common-style'));
wp_enqueue_script('product-script', $theme_directory . '/assets/js/product.js', array('jquery'), null, true);
}
}
add_action('wp_enqueue_scripts', 'theme_enqueue_assets');
TOPページをつくろう
頑張って作ります。
NewsとProductはこの時点ではSkipしてOKです。
カスタム投稿タイプ News、Productを実装
カスタム投稿タイプ(CPT)は、WordPressに標準で用意されている「投稿」や「固定ページ」などのデフォルト投稿タイプに加えて、独自の投稿タイプを作成できる機能です。通常の「投稿」ではなく、特定のコンテンツタイプに適した管理が可能になります。
今回はデフォルトの投稿は使わずに、カスタム投稿を使って実装してみます。
functions.phpに下記を追加。
function theme_setup() {
// アイキャッチ画像のサポートを有効にする
add_theme_support('post-thumbnails');
// タイトルタグを動的に出力する
add_theme_support('title-tag');
// カスタム投稿タイプ 'product' を登録
register_post_type('product',
array(
'labels' => array(
'name' => __('Products'),
'singular_name' => __('Product')
),
'public' => true,
'show_in_rest' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'products'),
'supports' => array('title', 'editor', 'thumbnail', 'excerpt')
)
);
// カスタム投稿タイプ 'news' を登録
register_post_type('news',
array(
'labels' => array(
'name' => __('News'),
'singular_name' => __('News Item')
),
'public' => true,
'show_in_rest' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'news'),
'supports' => array('title', 'editor', 'thumbnail', 'excerpt')
)
);
}
// テーマのセットアップが完了した後に 'theme_setup' 関数を実行
add_action('after_setup_theme', 'theme_setup');
register_post_type('news', ...);
この部分で新しいカスタム投稿タイプ News を登録しています。labels には投稿タイプの名前や単数形を設定しています。
public
投稿タイプが公開されるかどうかを設定します。true でフロントエンドや管理画面に表示されます。
show_in_rest
ブロックエディタ(Gutenberg)やREST APIを有効にする設定です。
has_archive
投稿のアーカイブページを作成するかどうかを設定します。true で /news/ というアーカイブページが生成されます。
rewrite
投稿タイプのURLスラッグを設定します。'slug' => 'news' によって、/news/という形のURLが作成されます。
WP管理画面の左側に投稿ボタンが増えました。
News、Productにサンプルの記事を投稿しよう
WP管理画面に投稿ボタンが出てきたら、サンプルデータを投稿しよう。
いくつも投稿するのは大変なので、WPプラグイン「🔗Copy & Delete Posts(Duplicate Post)」などで、コピーするのもおすすめです。
投稿した記事をTOPページに表示しよう
(例)
<section class="l-section">
<h2>PRODUCT</h2>
<a href="<?php echo get_post_type_archive_link('product'); ?>">More Products</a>
<?php
// WP_Query を使ってカスタム投稿タイプ 'product' の最新6件の投稿を取得
$product_query = new WP_Query(array(
'post_type' => 'product', // 取得する投稿タイプを 'product' に指定
'posts_per_page' => 6, // 取得する投稿の数を 6 に指定
));
// 投稿が存在するか確認
if ($product_query->have_posts()) :
// 投稿が存在する場合、ループを開始
while ($product_query->have_posts()) : $product_query->the_post(); // 投稿が存在するか確認 : まだ投稿が残っているかチェック
?>
<div class="product-post">
<h3><?php the_title(); ?></h3> <!-- 投稿のタイトルを表示 -->
<?php if (has_post_thumbnail()) : ?>
<div class="post-thumbnail">
<?php the_post_thumbnail('medium'); // サムネイル画像を 'medium' サイズで表示 ?>
</div>
<?php endif; ?>
<a href="<?php the_permalink(); ?>">Read more</a> <!-- 投稿の詳細ページへのリンクを表示 -->
</div>
<?php
endwhile;
// クエリ後のグローバルな投稿データをリセット
wp_reset_postdata();
else :
// 投稿が見つからない場合のメッセージを表示
echo '<p>No products found.</p>';
endif;
?>
</section>
get_post_type_archive_link('product')
get_post_type_archive_link('product') は、カスタム投稿タイプ「Product」のアーカイブページへのリンクを生成します。このリンクをクリックすると、productの全投稿一覧ページ(アーカイブページ)に遷移します。
WP_Queryでカスタム投稿を取得
$product_query = new WP_Query(array(
'post_type' => 'product',
'posts_per_page' => 6,
));
WP_Query クラスを使って、カスタム投稿タイプ「Product」の最新の6件の投稿を取得しています。
'post_type' => 'product' で取得する投稿タイプを指定しています。この場合、product というカスタム投稿タイプの投稿のみを取得します。
'posts_per_page' => 6 で、一度に取得する投稿の数を6件に指定しています。
投稿が存在するか確認
if ($product_query->have_posts()) :
have_posts()
は、指定したクエリで投稿が存在するかを確認する関数です。投稿が存在する場合に次の処理を進めます。
投稿のループ処理
while ($product_query->have_posts()) : $product_query->the_post();
while ループで、投稿がある限り繰り返し処理を行います。
$product_query->the_post() は、次の投稿データを取得し、グローバル変数 $post に設定します。これにより、the_title() や the_permalink() などのテンプレートタグが使えるようになります。
投稿のタイトル、サムネイル、リンク、抜粋の表示
the_title() は投稿のタイトルを表示します。このコードでは、各投稿のタイトルが <h3> タグ内に表示されます。
has_post_thumbnail() は、その投稿にアイキャッチ画像が設定されているかを確認する関数です。
設定されている場合、the_post_thumbnail() でサムネイル画像を表示します。
'medium' サイズで画像を表示するように指定しています。
WordPressにはあらかじめ登録されたサイズ(thumbnail, medium, large など)があり、必要に応じて適切なサイズを指定できます。
the_permalink() は、その投稿の詳細ページへのリンクを生成します。
このリンクをクリックすると、個別の投稿ページに移動します。
wp_reset_postdata() は、クエリによって変更されたグローバルな投稿データを元に戻す関数です。これを実行することで、以降のテンプレートで使用される投稿データが正しく戻ります。
ここにはないですが、Newsは、投稿記事の抜粋が使えますね。
<?php echo get_the_excerpt(); ?>
ページネーションの実装
<?php
// グローバル変数を使って現在のページ番号を取得
global $paged;
if (empty($paged)) $paged = 1;
// WP_Query を使ってカスタム投稿タイプ 'product' の最新6件の投稿を取得
$product_query = new WP_Query(array(
'post_type' => 'product', // 取得する投稿タイプを 'product' に指定
'posts_per_page' => 6, // 取得する投稿の数を 6 に指定
'paged' => $paged // 現在のページ番号を指定
));
?>
<div class="pagination">
<?php
// ページネーションリンクを表示
echo paginate_links(array(
'total' => $product_query->max_num_pages,
'current' => $paged,
'prev_text' => __('<', 'textdomain'),
'next_text' => __('>', 'textdomain'),
));
?>
</div>
<?php
// クエリ後のグローバルな投稿データをリセット
wp_reset_postdata();
?>
ページネーションの3ページ目以降がリンク切れになる場合
2ページ目まではきちんと表示されるのに、3ページ以降が表示されないことがあります。
そのときは、「WP管理画面 → 設定 → 表示設定 → 1ページに表示する最大投稿数を1」にしてみましょう。