0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WordPressでのサイト構築の備忘録

Last updated at Posted at 2019-06-28

クライアントから自社サイトを安く構築したいと相談を受けWordPressでやったのでメモしておく。

要件

  1. 無料テーマを改造して実装する。

環境

  1. Amazon Linux2
  2. Wordpress 5.2.2
  3. Visual Studio Code + SSHFS

環境構築

使いやすさでVisual Studio Codeを選択。SSHFSプラグインでLinuxサーバを直接いじる。これが快適でだいぶ生産性があがった。

Visual Studio Codeで拡張機能検索で「SSH FS」で検索してインストール。
Configurationを作成、入力するのは

  1. Host
  2. Port
  3. Root
  4. Username
  5. Private Key(AWSのpemファイルを指定)
    である。
    作成できたら右クリで接続。緑丸になれば接続成功。
    後はVSCで直接いじれる。

実装

機能を大別すると

  1. 表向きのページ(いわゆるHP)
  2. 管理者ページ(記事投稿用)
    がある。

Wordpressのインストールファイル

ツリー図
.
├── themes
│   └── bluestreet
├── wp-admin //管理者ページのルート
│   ├── css
│   ├── images
│   ├── includes
│   ├── js
│   ├── maint
│   ├── network
│   └── user
├── wp-content //HPページのルート
│   ├── languages
│   ├── plugins★ プラグイン
│   ├── themes
│   │   ├── bluestreet★ 親テーマのルート
│   │   └── wallstreet★ 子テーマのルート
│   ├── upgrade
│   └── uploads★ 記事投稿リソース保存先
└── wp-includes //インクルードリソース
    ├── blocks
    ├── certificates
    ├── css
    ├── customize
    ├── fonts
    ├── ID3
    ├── images
    ├── IXR
    ├── js
    ├── pomo
    ├── random_compat
    ├── Requests
    ├── rest-api
    ├── SimplePie
    ├── Text
    ├── theme-compat
    └── widgets

★がついているところが主に手を入れたところ。
下記に要点を列挙する。

共通部品

グローバルヘッダー、グローバルフッター。
header.php、footer.phpをいじる。
ベースにしたテーマではSNSリンクがあったが使わないのでこれは外した。
コンタクト情報はDBのoptionから取る方式はそのままとした。

グローバルヘッダーはポップアップメニューとした。

header.php
<!-- PC版メニュー -->
<div class="navbar navbar-wrapper navbar-inverse navbar-static-top headerbar" role="navigation">
  <!-- Brand and toggle get grouped for better mobile display -->
  <div>
    <ul class="navbar-header global-header-menu">
      <li class="header_div_main">
        <a href="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>">
          <div class="header_div_sub1">
            <!--<span class="header_label1-1"><?php echo get_option('company_mainlogo'); ?></span>-->
            <span class="header_label1-2"><?php echo get_option('company_sublogo'); ?></span>
          </div>
          <div class="header_div_sub2">
            <span class="header_label2"><?php $l->g('company'); ?></span>
          </div>
        </a>
      </li>
      <li>
        <ul class="header-menu-table">
          <li class="header-menu-parent accodionArea">
            <a href="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>/company-introduction/">
              <div class="accodionBtn">
                <span class="header-menu-label1">会社案内</span>
              </div>
            </a>
            <ul class="header-menu-children sub-menu-close sub-menu-hidden"> ★ここ以下がポップアップする。
              <li>
                <a href="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>/company-introduction" class="sub-menu-label1">会社の理念</a>
              </li>
              <li>
css
@keyframes menu-fadeout {
  0% {
    opacity: 1;
    margin-top: 0;
    transform: translateY(0);
  }
  99% {
    opacity: 0;
    margin-top: 0;
    transform: translateY(-50px);
  }
  100% {
    opacity: 0;
    margin-top: -200px;
  }
}
.sub-menu-open {
  animation: menu-fadein 0.5s forwards;
  display: block !important;
}
.sub-menu-close {
  animation: menu-fadeout 0.5s forwards;
}
.sub-menu-hidden {
  display: none;
}
javascript
jQuery(function() {
  jQuery('.accodionBtn').on('mouseenter', function() {
    jQuery(this).parent().next(".header-menu-children").removeClass("sub-menu-close");
    jQuery(this).parent().next(".header-menu-children").addClass("sub-menu-open");
  });

  jQuery('.accodionArea').on('mouseleave', function() {
    jQuery(this).children(".header-menu-children").removeClass("sub-menu-open");
    jQuery(this).children(".header-menu-children").addClass("sub-menu-close");
  });
});

ページ内項目外出し化

基本的にDBのwp_optionに突っ込んでget_optionsで取得するようにする。

サブ機能の実装

ベースにしたテーマになかった「お知らせ」、「求人票」の投稿周りの機能をプラグインとして実装した。
functions.phpに実装してもできるとは思うが、プラグインだと有効かしたときにコンストラクタでDBテーブルを作成するなどの準備処理ができる。
規定のコメントヘッダーを入れることでWordpress管理画面のプラグイン一覧に載るようになる。

wp-content\plugins\information-function.php
<?php
/*
Plugin Name: information function
Plugin URI:
Description: お知らせコンテンツ関係機能プラグイン
Author: fantec
Version: 1.0
Author URI: 
*/

class informationFunction {
  //テーブル名
  var $table_name;

  //コンストラクタ
  public function __construct()
  {
    global $wpdb;

    //接頭辞(wp_)を付けてテーブル名を設定
    $this->table_name = $wpdb->prefix . 'informations';
    
    //プラグイン有効化したとき実行
    register_activation_hook (__FILE__, array($this, 'create_table'));
  }

  //初期化処理
  function create_table() {
    global $wpdb;

    //DBのバージョン
    $func_db_version = '1.0';

    //現在のバージョン取得
    $installed_ver = get_option( 'information_func_version' );
    
    //DBバージョンが違ったら作成
    if( $installed_ver != $func_db_version ) {
      $sql = "CREATE TABLE " . $this->table_name . " (
            info_id bigint(20) UNSIGNED DEFAULT '0' NOT NULL,
            info_title text,
            author_id int(10) DEFAULT NULL,
            content text,
            imgname text,
            regist_date datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
            update_date datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
            UNIQUE KEY info_id (info_id)
          )
          CHARACTER SET 'utf8';";
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);

        //オプションにDBバージョン保存
        update_option('information_func_version', $func_db_version);
    }
  }

  //全お知らせ取得
  public function get_all() {
    global $wpdb;

    return $wpdb->get_results("SELECT * FROM wp_informations ORDER BY update_date DESC");
  }

  //お知らせ先頭n件取得
  public function get_topn($n) {
    global $wpdb;

    return $wpdb->get_results("SELECT * FROM wp_informations ORDER BY update_date DESC LIMIT ".$n);
  }
  
  //一覧表示用お知らせ取得
  //
  public function get_page_list($page) {
    global $wpdb;
    $result = array();

    //一覧ページあたり掲載数
    $num_per_page = 5;

    $tmp = $wpdb->get_results("SELECT * FROM wp_informations ORDER BY update_date DESC");
    $result['data'] = array_slice($tmp, $num_per_page*($page-1), $num_per_page);
    $result['maxpage'] = (count($tmp) % $num_per_page == 0) ? floor(count($tmp) / $num_per_page) : (floor(count($tmp) / $num_per_page))+1;

    return $result;
  }

  //特定お知らせ取得
  public function get_by_infoid($info_id) {
    global $wpdb;

    $result = $wpdb->get_results("SELECT * FROM wp_informations WHERE info_id = ".$info_id." ORDER BY update_date DESC");
    return isset($result[0]) ? $result[0] : null;
  }

  //特定お知らせ新規登録
  public function insert($info_title, $author_id, $content, $imgname) {
    global $wpdb;

    $datetime = new DateTime();
    $datetime->setTimeZone( new DateTimeZone('Asia/Tokyo'));
    $date_formated = $datetime->format('Y-m-d H:i:s');
    
    $result = $wpdb->get_results("SELECT MAX(info_id) AS maxid FROM wp_informations");

    $wpdb->insert('wp_informations', 
      array( 
          'info_id' => $result[0]->maxid+1,
          'info_title' => $info_title,
          'author_id' => $author_id,
          'content' => $content,
          'imgname' => $imgname,
          'regist_date' => $date_formated,
          'update_date' => $date_formated
      ));

      return intval($result[0]->maxid+1);
  }

  //特定お知らせ更新(画像変更なし)
  public function update_noimg($info_id, $info_title, $author_id, $content) {
    global $wpdb;

    $datetime = new DateTime();
    $datetime->setTimeZone( new DateTimeZone('Asia/Tokyo'));
    $update_date_formated = $datetime->format('Y-m-d H:i:s');

    $wpdb->update('wp_informations', 
      array( 
          'info_title' => $info_title,
          'author_id' => $author_id,
          'content' => $content,
          'update_date' => $update_date_formated
      ), 
      array( 'info_id' => $info_id ));

    return intval($info_id);
  }

  //特定お知らせ更新
  public function update($info_id, $info_title, $author_id, $content, $imgname) {
    global $wpdb;

    $datetime = new DateTime();
    $datetime->setTimeZone( new DateTimeZone('Asia/Tokyo'));
    $update_date_formated = $datetime->format('Y-m-d H:i:s');

    $wpdb->update('wp_informations', 
      array( 
          'info_title' => $info_title,
          'author_id' => $author_id,
          'content' => $content,
          'imgname' => $imgname,
          'update_date' => $update_date_formated
      ), 
      array( 'info_id' => $info_id ));

    return intval($info_id);
  }

  //画像ルートURI取得
  public function get_img_root_uri() {
    return content_url()."/uploads/informations/img/";
  }
  
  //画像ルートディレクトリ取得
  public function get_img_root_dir() {
    $upload_dir = wp_upload_dir();
    return $upload_dir['basedir']."/informations/img/";
  }

  //未設定時画像パス取得
  public function get_notsetimg_uri() {
    return content_url()."/uploads/informations/img/noimage.jpg";
  }

  //文の省略加工
  public function get_omission_str($str, $len) {
    return mb_strlen($str) > $len ? mb_substr(esc_html($str), 0, $len)."..." : $str;
  }
}
$incetance = new informationFunction;

利用側

<!-- AddThis Button END -->
<?php $wallstreet_pro_options=theme_data_setup();
$current_options = wp_parse_args(  get_option( 'wallstreet_pro_options', array() ), $wallstreet_pro_options );
//お知らせ機能用
$infofunc = new informationFunction();
?>
<div class="information-section">
  <div>
    <div class="row">
      <div class="section_heading_title">
        <h1><?php echo esc_html(get_option('information_title')); ?></h1>
        <div class="pagetitle-separator">
          <div class="pagetitle-separator-border">
            <div class="pagetitle-separator-box"></div>
          </div>
        </div>
      </div>
    </div>
    <div class="row">
      <?php
        $infos = $infofunc->get_topn(3);
        foreach($infos as $info) {
          $info_id = isset($info->info_id) ? $info->info_id : null;
          $title = isset($info->info_title) ? $info->info_title : null;
          $content = isset($info->content) ? $info->content : null;
          $imgname = isset($info->imgname) ? $info->imgname : null;
          $update_date = isset($info->update_date) ? $info->update_date : null;
          $datetime = new DateTime($update_date);
          //$update_date_formated = $datetime->format('Y/m/d H:i:s');
          $update_date_formated = $datetime->format('Y/m/d');
      ?>
      <div class="information-outline">
        <div class="headerdiv">
          <span class="information-title"><?php echo esc_html($title); ?></span>
          <div class="information-datetime">
            <span>掲載日:<?php echo esc_html($update_date_formated); ?></span>
          </div>
        </div>
        <div class="contentdiv">
          <?php if ($imgname!=null) { ?>
          <img src="<?php echo $infofunc->get_img_root_uri().esc_html($imgname); ?>" alt="" />
          <?php } ?>
          <span class="information-content"><?php echo $infofunc->get_omission_str(nl2br(esc_html($content)), 50); ?></span>
        </div>
        <form method="post" name="information_form_<?php echo $info_id ?>" action="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>/information-detail/">
          <input type="hidden" name="info_id" value="<?php echo $info_id ?>">
          <div class="information-detail-button-div">
            <a href="javascript:information_form_<?php echo $info_id ?>.submit()">
              <div class="information-detail-button">
                  <span>詳細を見る</span>
              </div>
            </a>
          </div>
        </form>
      </div>
      <?php
        }
      ?>
    </div>
    <div class="information-more-button-div">
      <a href="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>/information-list/">
        <div class="information-more-button">
          <span>お知らせをもっと見る</span>
        </div>
      </a>
    </div>  
  </div>  
</div>
<!-- /wallstreet Portfolio Section -->

問合せをメール送信

PHPMailerで実装。メール本文はテンプレートをキーワード置換で作成するようにした。

<?php
  get_header();
  
/*
Template Name: 問い合わせ内容のメール送信ページ
*/

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

require 'PHPMailer/src/Exception.php';
require 'PHPMailer/src/PHPMailer.php';
require 'PHPMailer/src/SMTP.php';

$inquiry_no;
$mail = new PHPMailer(true);

$is_spam = spam_check();  // スパム判定
$error = null;

try {
  // サーバ設定
  //$mail->SMTPDebug = 2;     // デバッグモード。本番時はコメントアウトすること。
  $mail->isSMTP();
  $mail->Host = 'localhost';
  $mail->SMTPAuth = true;
  $mail->Username = 'xxx@bbb.cc';    // 送信アカウント
  $mail->Password = 'xxxxxxx';           // 送信アカウントのパスワード
  $mail->SMTPSecure = false;              // TLSなどの暗号化非対応のサーバならfalseを設定。使えるなら'tls'か'ssl'を設定。
  $mail->SMTPAutoTLS = false;             // SMTPSecureをfalseにする場合はfalseにする。それ以外なら未設定で。
  $mail->Port = 587;

  // 送り先情報
  $mail->setFrom('xxxx@bbb.ccc');              // 送信元アドレス
//    $mail->addCC();                           // CC
//    $mail->addBCC();                          // BCC
  $mail->addAddress('aaa@xxx.cc');          // 送信先アドレス
  $mail->addReplyTo('aaa@xxx.cc');          // 返信先アドレス

  // 本文
  $mail->isHTML(false);
  $mail->CharSet = 'UTF-8';

  $inquiry_type = $_POST['inquiry_type'];    // 問合せ種別(joboffer:派遣求人票問合せ tradingcompany:派遣取引企業向け問合せ recruitment:自社採用情報問合せ)

  // 置換対象を順に指定
  $search = array('$$inquiry_no$$', '$$simei$$', '$$furi$$', '$$inquiry_ages$$', '$$inquiry_sex$$', '$$tel1$$', '$$tel2$$', '$$tel3$$',
      '$$email$$', '$$offer_no$$', '$$inquiry_subject$$', '$$inquiry_content$$');
  // 置き換える文字列を順に指定
  $inquiry_no = make_inquiry_no("JO");
  $replace = array($inquiry_no, $_POST['simei'], $_POST['furi'], $age, $sex, $_POST['tel1'], $_POST['tel2'], $_POST['tel3'],
                $_POST['email'], $_POST['offer_no'], $subject, $_POST['inquiry_content']);
  $mail->Body = str_replace($search, $replace, $template);    // 本文
  $mail->Subject = mb_encode_mimeheader($subject." 問い合わせ番号「".$inquiry_no."」");                   // 件名
  $mail->send();

} catch (Exception $e) {
  echo $mail->ErrorInfo;
}
差出人: HP 「派遣のお取引企業」お問い合わせ自動送信フォーム

お問い合わせ番号:「$$inquiry_no$$」

【貴社名】:
$$company$$

【部署名】:
$$section$$

【ご担当者様のお名前】:
$$simei$$

【フリガナ】:
$$furi$$

【お電話番号】:
$$tel1$$ - $$tel2$$ - $$tel3$$

【FAX番号】:
$$fax1$$ - $$fax2$$ - $$fax3$$

【メールアドレス】:
$$email$$
  
【お問い合わせ件名】:
$$inquiry_subject$$
  
【お問い合わせ内容】:
$$inquiry_content$$

-- 
このメールは 株式会社xxxx (yyyyyy) の「派遣お取引企業様向けお問い合わせフォーム」から送信されました

管理者画面のメニュー操作

1. wp_enqueue_styleでリソースのインクルード。
2. remove_menu_pageで余計なmニューを削除。
3. add_menu_pageとadd_submenu_pageで独自なメニューを追加。

\wp-content\themes\bluestreet\functions.php

function bluestreet_custmizer_style()
{
    wp_enqueue_style('bluestreet-customizer-css',get_stylesheet_directory_uri() .'/css/cust-style.css');
}
add_action('customize_controls_print_styles','bluestreet_custmizer_style');


/* 管理画面メニューのカスタマイズ */
define('MAX_FILE_SIZE', 1 * 1024 * 1024); //アップロード画像のサイズ制限(1MB)
define('JTAG_ON', 'on');                   //求人タグの選択時データ
define('JTAG_OFF', 'off');                 //求人タグの未選択時データ
if (is_user_logged_in()) {
  function remove_admin_menu() {
    remove_menu_page( 'index.php' );                // ダッシュボード
    remove_menu_page( 'edit.php' );                 // 投稿
    remove_menu_page( 'upload.php' );               // メディア
    remove_menu_page( 'edit.php?post_type=page' );  // 固定ページ
    remove_menu_page( 'edit-comments.php' );        // コメントs
    remove_menu_page( 'themes.php' );               // 外観
    remove_menu_page( 'plugins.php' );              // プラグイン
    remove_menu_page( 'users.php' );                // ユーザー
    remove_menu_page( 'tools.php' );                // ツール
    remove_menu_page( 'options-general.php' );      // 設定
  }
  $user = wp_get_current_user();
  if($user->roles[0]!="administrator") {
    /* 管理者以外なら不要な管理画面メニューを非表示にする */
    add_action( 'admin_menu', 'remove_admin_menu', 999 );
  }

  //各カスタムページを出力するコールバック定義外部ファイル読み込み
  require( get_template_directory().'/functions/my-admin/admin-info-list.php');          //お知らせ一覧
  require( get_template_directory().'/functions/my-admin/admin-info-post.php');          //お知らせ編集
  require( get_template_directory().'/functions/my-admin/admin-joffer-list.php');        //求人一覧
  require( get_template_directory().'/functions/my-admin/admin-joffer-post.php');        //求人編集
  require( get_template_directory().'/functions/my-admin/admin-joffertags-edit.php');    //求人タグ編集
  require( get_template_directory().'/functions/my-admin/admin-joffertypes-edit.php');  //求人職種編集
  require( get_template_directory().'/functions/my-admin/admin-jofferareas-edit.php');  //求人勤務地編集
  require( get_template_directory().'/functions/my-admin/admin-recruitment-list.php');  //採用情報一覧
  require( get_template_directory().'/functions/my-admin/admin-recruitment-post.php');  //求人編集

  /* 独自メニューを追加 */
  function add_admin_menu() {
    //お知らせ機能
    add_menu_page( 'お知らせ一覧', 'お知らせ', 'publish_posts', 'informations', 'admin_info_list', '', 0 );
    add_submenu_page( 'informations', 'お知らせ編集', '新規登録', 'publish_posts', 'admin_info_post', 'admin_info_post');
    //求人機能
    add_menu_page( '求人一覧', '求人', 'publish_posts', 'joboffers', 'admin_joffer_list', '', 1 );
    add_submenu_page( 'joboffers', '求人編集', '新規登録', 'publish_posts', 'admin_joffer_post', 'admin_joffer_post');
    add_submenu_page( 'joboffers', 'タグ編集', 'タグ編集', 'publish_posts', 'admin_joffertags_edit', 'admin_joffertags_edit');
    add_submenu_page( 'joboffers', '職種編集', '職種編集', 'publish_posts', 'admin_joffertypes_edit', 'admin_joffertypes_edit');
    add_submenu_page( 'joboffers', '勤務地編集', '勤務地編集', 'publish_posts', 'admin_jofferareas_edit', 'admin_jofferareas_edit');
    //採用情報機能
    add_menu_page( '採用情報一覧', '採用情報', 'publish_posts', 'recruitment', 'admin_recruitment_list', '', 1 );
    add_submenu_page( 'recruitment', '採用情報編集', '新規登録', 'publish_posts', 'admin_recruitment_post', 'admin_recruitment_post');
    
    $user = wp_get_current_user();
    if($user->roles[0]!="administrator") {
      /* 管理者以外なら余計な部品は非表示にする */
      wp_enqueue_style( 'hidden-parts-style', get_theme_root_uri()."/wallstreet/css/my-admin-hidden-parts.css" );
    }
  }
  add_action('admin_menu', 'add_admin_menu');
}

画面遷移

普通に。

<div class="information-more-button-div">
  <a href="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>/information-list/">
    <div class="information-more-button">
      <span>お知らせをもっと見る</span>
    </div>
  </a>
</div>

POSTパラメータつき。

<form method="post" name="information_form_<?php echo $info_id ?>" action="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>/information-detail/">
  <input type="hidden" name="info_id" value="<?php echo $info_id ?>">
  <div class="information-detail-button-div">
    <a href="javascript:information_form_<?php echo $info_id ?>.submit()">
      <div class="information-detail-button">
          <span>詳細を見る</span>
      </div>
    </a>
  </div>
</form>

一覧ページング

同一ページへの同期型POSTリクエスト方式

<div class="joboffer-paging-area">
  <div class="row">
    <form method="post" name="joboffer_list_form_prev" action="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>/joboffer-list/">
      <input type="hidden" name="page" value="<?php echo $page-1 ?>">
      <input type="hidden" name="filter" value="<?php echo $filter ?>">
      <a class="<?php echo $page>1 ? '':'vs-hidden'; ?>" href="javascript:joboffer_list_form_prev.submit()">
        <div class="page-prev-button">
          <span>前へ</span>
        </div>
      </a>
    </form>
    <?php for($i=1; $i<=$offers['maxpage']; $i++) { ?>
    <form method="post" name="joboffer_list_form_<?php echo $i ?>" action="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>/joboffer-list/">
      <input type="hidden" name="page" value="<?php echo $i ?>">
      <input type="hidden" name="filter" value="<?php echo $filter ?>">
      <?php if($i!=$page) { ?>
      <a href="javascript:joboffer_list_form_<?php echo $i ?>.submit()">
        <div class="page-no-button">
          <span><?php echo $i ?></span>
        </div>
      </a>
      <?php } else { ?>
        <div class="page-no-button page-this">
          <span><?php echo $i ?></span>
        </div>
      <?php } ?>
    </form>
    <?php } ?>
    <form method="post" name="joboffer_list_form_next" action="<?php echo esc_url( get_option( 'ssl_url' ) ); ?>/joboffer-list/">
      <input type="hidden" name="page" value="<?php echo $page+1 ?>">
      <input type="hidden" name="filter" value="<?php echo $filter ?>">
      <a class="<?php echo $page<$offers['maxpage'] ? '':'vs-hidden'; ?>" href="javascript:joboffer_list_form_next.submit()">
        <div class="page-next-button">
          <span>次へ</span>
        </div>
      </a>
    </form>
  </div>
</div>
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?