最初にやっておきたいfunctions.phpの基本設定

セキュリティの観点や諸々から、Wordpress（以下WP）のカスタム設定ファイルの`functions.php`に標準設定として入れておいた方が良いコード。
基本は、日々利用されるお客様が運用しやすいようにすることが大事なので、標準設定として自作テーマの時は必ず入れるようにしておくと良いかと思います。

以前書いた、`functions.php`にhead情報を入れる記事はこちら

https://qiita.com/makkie/items/34a608ca3dc8a0b8d66b

# 事前準備
テーマを自作する場合、他ファイルと同様に`functions.php`をテーマフォルダ配下に作成します。
既にある場合は、既存のコードの下や上に追記していきますが、コードの競合等がない様に注意してください。
以下は私がテーマを自作する際に用意するファイルとフォルダの構成です。
```
../themes/original/
        ├─images/（画像用）
        ├─inc/（パーツ用）
        ├─fnc/（functionsのパーツ用）
        ├─js/（jsファイル用）
        ├─css/（cssファイル用）
        ├─index.php    
        ├─home.php
        ├─header.php
        ├─footer.php
        ├─sidebar.php
        ├─archive.php
        ├─singular.php
        ├─search.php
        ├─style.css
        └─functions.php
```
ファイルとフォルダの構成の詳細は以下の記事で書いてます。

https://qiita.com/makkie/items/dc764c2845492079c0af

`functions.php`の中身はとりあえずこんな感じです。
`PHP`コードを書くので、先頭と末尾は`<?php`と`?>`としています。
これを2重に書いたり抜けたりしてると、WP画面が真っ白になったりエラーが出たりするので、忘れない様に。
コードの都度`<?php` `?>`しても良いと思いますが、私は忘れやすいので、基本先頭と末尾にしか書かないようにしてます。

```functions.php
<?php
//この中に必要なコードを書きます。
?>
```
## ログイン画面のカスタマイズ
これは特に動作とかには関係ないのですが、標準のWPロゴマークだとなんとなく安っぽい。できればお客様専用のサイトだよ感を出したい時に。
テーマフォルダの`images`内に`logo.png`を入れるのを忘れずに（別ファイル名でもOKです。その際は、下記コードの該当箇所を修正してください）
画像サイズはMAXで`83x83px`ですが、`h1 a`の`100% 100%`を表示したい画像のサイズにすればその大きさで表示されます。
あとコーポレートカラーとかがあれば、背景色`body.login`を合わせると良い感じになります（恋色の場合は薄い色に調整した方が良いかも）
```diff_php
////////////////////////////////////////////////
//ログイン画面カスタマイズ
////////////////////////////////////////////////
//83x83px
function custom_login_logo() {
  echo '<style type="text/css">';
  echo 'h1 a { background: url('.get_bloginfo('template_directory').'/images/logo.png) 100% 100% no-repeat !important; }';
  echo 'body.login { background: #ecf7f8; }';
  echo '</style>';
 }
add_action('login_head', 'custom_login_logo');
```
## ダッシュボードのカスタマイズ
### バージョン情報の非表示
Chromeのデベロッパーツール等でWPのバージョンが見えてしまい、最新のバージョンを使ていないことが知れてしまうと、攻撃を受けやすくなるため、必ず非表示にします。
プラグインでもできますが、この一行書くだけでいいので、`functions.php`に書くことをおすすめします。
```diff_php
//WPのバージョン情報非表示
remove_action( 'wp_head', 'wp_generator');
```
### お問い合わせ先のリンク修正
`<a href="***">`に自社WEBサイトのURLを入れたり、問い合わせフォームのURLを入れたり。
`お問い合わせ`の文言も変更してもいいかも。社名とか`株式会社＊＊＊お問い合わせはこちら`とか。
```diff_php
// フッターWordPressリンクを非表示に
function custom_admin_footer() {
   echo '<a href="***">お問い合わせ</a>';
}
```
### サイドバーの「コメント」は非表示
コーポレートサイトの場合は、基本的にコメントは受け付けないので、管理画面のサイドメニューからも非表示にします。
スパムコメントも多いので、交流を目的としているサイトでなければ基本非表示で良いかも。

:::note alert
ここで非表示にしても、設定から`コメントを受け付けない`設定をしないとスパムコメントが書き込まれてしまいます。
（`設定`－`ディスカッション`の中の`コメントの投稿者の名前とメールアドレスの入力を必須にする` `自分宛のメール通知`のチェックをONにして、他はOFF）
またテーマファイルでも、デフォルトのテーマを流用している場合、コメント用のファイルがあり、スパムコメントが入ってしまうので削除しましょう。
:::
```diff_php
//サイドバーに表示する項目はコメントアウト
add_action( 'admin_menu', 'remove_menus' );
function remove_menus(){
    //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' ); //コメントメニュー
    //remove_menu_page( 'themes.php' ); //外観メニュー
    //remove_menu_page( 'plugins.php' ); //プラグインメニュー
    //remove_menu_page( 'tools.php' ); //ツールメニュー
    //remove_menu_page( 'options-general.php' ); //設定メニュー
}
```
:::note warn
ここで非表示にした場合、管理者権限があっても非表示になるので、ユーザー権限によってサイドバーの表示内容を変えたい時は、ユーザーの権限を変更するか、独自のユーザー権限を付与するプラグインを利用してください。
:::

## カスタム機能をON
サイト制作をしていると当たり前に使う機能でもWPだと標準になっていないと言う機能があるので、それをONにします。

### カスタムナビゲーション
下記コードは、ヘッダー用とフッター用の2種類用意しています。
よくあるナビゲーションで、ヘッダーは最小のナビだけにして、フッターは全部のコンテンツのナビを表示と言う場合等、ヘッダーとフッターの表示する内容を変える場合に分けます。さらにサイドバー用が欲しいよって方は、`'nav-foot' => 'フッターナビ',`の下に追加してください。
```diff_php
//++++++++++++++++++++++++++++++++++++++++++
//　　カスタムナビゲーション
//++++++++++++++++++++++++++++++++++++++++++
function register_my_menus() {
  register_nav_menus( array(
    'nav-head' => 'ヘッダーナビ',
    'nav-foot' => 'フッターナビ',
  ));
}
add_action( 'after_setup_theme', 'register_my_menus' );
```
テーマファイル（`header.php`等）での出力は↓
```diff_php
<nav>
<?php
//カスタムメニュー表示
wp_nav_menu( array(
    'theme_location' => 'nav-head',
    'container' => false,
    'items_wrap' => '<ul class="head-nav-area">%3$s</ul>'
));
?>
</nav>
```
ナビゲーションなので、`<nav>`で囲んでいます。
特にWPが自動で吐き出すclass等そのままでいい場合は
```diff_php
<?php wp_nav_menu('nav-head'); ?>
```
で出力できます。
細かいパラメータの指定はCodexを見てください。

https://wpdocs.osdn.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/wp_nav_menu

#### 自動で挿入されるタグを消す
自動で挿入されるタグを消したい場合は、以下のコードを`functions.php`に追加します。
（2023/1/6　下記コードではWP6.1.1でうまく動いていませんでしたので、修正版を追記しました。）
```
function my_nav_menu_id($menu_id){
	$id = NULL;
    return $id;
}
add_filter('nav_menu_item_id', 'my_nav_menu_id');

function remove_menu_aria_current( $atts, $item, $args ){
	unset ( $atts['aria-current'] );
	return $atts;
}
add_filter('nav_menu_link_attributes', 'remove_menu_aria_current', 11, 5);
```
```diff_php
//カスタムメニューで自動挿入されるタグ（id + class）を削除
//開いてるページにcurrent-menu-item付与
add_filter('nav_menu_css_class', 'my_css_attributes_filter', 100, 1);
add_filter('nav_menu_item_id', 'my_css_attributes_filter', 100, 1);
add_filter('page_css_class', 'my_css_attributes_filter', 100, 1);
function my_css_attributes_filter($var) {
  return is_array($var) ? array_intersect($var, array('current-menu-item')) : '';
}
```
### サムネイル（アイキャッチ）
だいたい記事ごとにサムネイルを表示したい、サムネイルは記事中の写真（画像）とは違うのにしたいと言った時に使用します。
文字だけよりも画像があった方が見た目も良いのでこれはぜひONにしておきたい機能です。（なんで標準じゃOFFなんでしょう？）
```diff_php
//++++++++++++++++++++++++++++++++++++++++++
//　　アイキャッチ画像
//++++++++++++++++++++++++++++++++++++++++++
add_theme_support('post-thumbnails');
```
### 投稿一覧に機能を追加
投稿一覧にあると日々の投稿を行う際に便利な機能を追加します。

#### スラッグ表示
スラッグは日本語にしているとエンコードされたURLになりSEO的によろしくないので、英語もしくはアルファベット表記にした方がいいのですが、うっかり変更し忘れてしまう事があるので表示する様にしています。
```diff_php
//スラッグ表示--------------------------------------------
function add_posts_column_title($colomun) {
  $colomun['slug'] = 'スラッグ';
  echo '<style>
  .fixed .column-slug {width: 15%;}
  </style>';
  return $colomun;
}
function add_posts_column($column_name, $post_id) {
  if($column_name == 'slug') {
    $post = get_post($post_id);
    $slug = $post -> post_name;
    echo esc_attr($slug);
  }
}
add_filter('manage_posts_columns', 'add_posts_column_title');
add_action('manage_posts_custom_column', 'add_posts_column', 10, 2);

//固定ページの投稿一覧に
function add_page_column_title($colomun) {
  $colomun['slug'] = 'スラッグ';
  echo '<style>
  .fixed .column-slug {width: 15%;}
  </style>';
  return $colomun;
}
function add_page_column($column_name, $post_id) {
  if($column_name == 'slug') {
    $post = get_post($post_id);
    $slug = $post -> post_name;
    echo esc_attr($slug);
  }
}
add_filter('manage_pages_columns', 'add_page_column_title');
add_action('manage_pages_custom_column', 'add_page_column', 10, 2);
```
#### アイキャッチ画像を表示
せっかくアイキャッチ画像をONにしたので、投稿一覧に表示する設定も。
下記コードだと、投稿、カスタム投稿、固定ページの一覧の右側にアイキャッチが表示されるようになります。
```diff_php
//アイキャッチ画像表示---------------------------
//各投稿一覧ページにアイキャッチ画像用の列を追加
add_filter( 'manage_posts_columns', 'add_custom_post_columns');    //投稿 & カスタム投稿
add_filter( 'manage_pages_columns', 'add_custom_post_columns' );   //固定ページ
if ( !function_exists( 'add_custom_post_columns' ) ) {
    function add_custom_post_columns( $columns ) {
        global $post_type;
        if( in_array( $post_type, array('post', 'page', 'blog') ) ) { //列を追加するタイプをここで指定
            $columns['thumbnail'] = 'アイキャッチ画像';    //カラム表示名
        }
        return $columns;
    }
}
//サムネイル画像を表示
add_action( 'manage_posts_custom_column', 'output_custom_post_columns', 10, 2 );  //投稿 & カスタム投稿(階層構造が無効)
add_action( 'manage_pages_custom_column', 'output_custom_post_columns', 10, 2 );  //固定ページ & カスタム投稿(階層構造が有効)
if ( !function_exists( 'output_custom_post_columns' ) ) {
    function output_custom_post_columns( $column_name, $post_id ) {
        if ( 'thumbnail' === $column_name ) {
            $thumb_id  = get_post_thumbnail_id( $post_id );
            if ( $thumb_id ) {
                $thumb_img = wp_get_attachment_image_src( $thumb_id, 'medium' );  //サイズはご自由に
                echo '<img src="',$thumb_img[0],'" width="160px">';
            } else {
                echo 'アイキャッチ画像が<br>設定されていません';
            }
        }
    }
}
```

## 必要な場合はONにする機能
### ウィジェットを使いたい
以下のコードは、3種類（サイドバー、フッター、コンテンツ）のウィジェットを追加します。
ひとつでいい場合は`register_sidebar`から`));`を削除してください。
3つ以上欲しい場合は、`));`の下に`register_sidebar`を必要分追加してください。
```diff_php
//++++++++++++++++++++++++++++++++++++++++++
//ウィジェット
//++++++++++++++++++++++++++++++++++++++++++
function theme_slug_widgets_init() {
  register_sidebar( array(
      'name' => 'サイドバー', //ウィジェットの名前を入力
      'id' => 'sidebar', //ウィジェットに付けるid名を入力
  ));
  register_sidebar( array(
    'name' => 'フッター',
    'id' => 'footbar',
  ));
  register_sidebar( array(
    'name' => 'コンテンツ',
    'id' => 'contentbar',
  ));
}
add_action( 'widgets_init', 'theme_slug_widgets_init' );
```
テーマファイルでの出力は以下のコード（例は`フッター`）
`li`で出力されるので`ul`で囲んでください。
```diff_php
<ul id="foot-widget-area">
    <?php dynamic_sidebar('footbar');?>
</ul>
```

### WPで自動生成される画像をSTOP
WPを利用していると自動生成される画像でサーバ容量を圧迫することが多々あります。細かく画像サイズを用意することで、WEBサイトの表示速度を速める効果を期待してのことなのですが、不要なサイズまで生成されるのはサーバ容量的に困ります。
`設定`－`メディア`でアップロードした画像のサイズを指定できますが、ここで設定した他にも勝手に生成されるサイズがあるので、`functions.php`でも設定します。
下記コード内のコメントに`option-media.phpの設定にプラス`と入れていますが、これは`設定`－`メディア`のことです。
設定画面で数値を指定した上で、さらに下記コードで ***生成したくないサイズを表示*** に、 ***生成したいサイズを`//`（コメントアウト）*** にします。
```diff_php
//++++++++++++++++++++++++++++++++++++++++++
// 画像の自動生成STOP
// option-media.phpの設定にプラス
// 有効にするサイズはコメントアウト
//++++++++++++++++++++++++++++++++++++++++++
add_image_size('thumbnail', 0, 0);
add_image_size('medium', 0, 0);
add_image_size('medium_large', 0, 0);
//add_image_size('large', 0, 0);
add_image_size('1536x1536', 0, 0);
add_image_size('2048x2048', 0, 0);
add_filter( 'big_image_size_threshold', '__return_false' );

function not_create_image($sizes) {
    unset($sizes['thumbnail']);
    unset($sizes['medium']);
    unset($sizes['medium_large']);
    //unset($sizes['large']);
    unset($sizes['post-thumbnail']); # 1200x800
    unset($sizes['1536x1536']);
    unset($sizes['twentytwenty-fullscreen']); # 1980x1320
    unset($sizes['2048x2048']);
    return $sizes;
}
add_filter('intermediate_image_sizes_advanced', 'not_create_image');
```

## テーマロゴを指定
テーマカスタマイザーからユーザー側でロゴマークが設定出来るようにします。
会社やお店を立ち上げたばかりでロゴマークがまだないというお客様向け。
```diff_php
//++++++++++++++++++++++++++++++++++++++++++
//カスタムロゴ
//外観-カスタマイズで画像指定
//画像がない時はサイトタイトル表示
//++++++++++++++++++++++++++++++++++++++++++
add_theme_support('custom-logo');
function mycustom_logo(){
  if( has_custom_logo() ){
   $custom_logo_id = get_theme_mod( 'custom_logo' );
   $image = wp_get_attachment_image_src( $custom_logo_id , 'full' );
     $mylogo = $image[0];
   $mylogo = '<img src="'. $mylogo .'" class="custom-logo" alt="'. get_bloginfo( 'name' ) .'" />';
  } else {
    $mylogo = get_bloginfo( 'name' );
  }
  if( is_front_page() && is_home()){
   echo '<h1 class="site-logo">'. $mylogo .'</h1>';
  } else {
   echo '<span class="site-logo"><a href="'. home_url() .'" rel="home">'. $mylogo .'</a></span>';
  }
}
```

# まとめ
大体の機能がプラグインで実現できてしまうのですが、プラグインは余計な機能が多くサーバの容量を圧迫する、こまめに更新してもらわないとセキュリティホールになる、いちいちインストールして有効化するのが面倒といった問題がありますが、`functions.php`に書き込めば、テーマを読み込ませるだけで機能が有効化され、サーバ容量もさほど圧迫しません。また、コードが古くなったとしても、プラグインの様に更新を待たなくてもすぐに修正できるという利点があります。
書き方を間違えたりするとすぐにサイトが真っ白になったりするので、初心者の方には敷居が高そうに見えますが、WPのテーマを自作したいと考えているのであれば、必ず越えなくてはいけないところではないかと思っています。


独学で得た知識なので、専門的に学ばれた方から見ると不足や解釈間違い等あるかと思います。
おかしな点などありましたらご指摘いただけると幸いです。