今日は、Stinger3仕様の際に導入していた、CTA部分のカスタマイズを行ってました。
こんなヤツです。
参照:Stinger3カスタマイズ;Call To Actionをウィジェット形式で記事下に追加してみた。
子テーマを使ってのカスタマイズを進めていくと、必ずと言って良いほど壁として立ちはだかるのがfunctions.phpの問題ですよね。
他のファイルは上書きしてくれるのに、このfunctions.phpだけは、上書きはしてくれないわ、すぐにエラーを吐くわwww
今日は、そんなfunctions.phpのカスタマイズを子テーマ側でやる方法についてです。
functions.phpが上書きされない仕組み
まずはfunctions.phpが上書きされない仕組みについて。
最初の問題は、関数の重複
そもそも親テーマの内容(関数;function~の部分)を、そのまま子テーマに持ってくると、エラーになってサイトが見られなくなります。
これは、関数の重複を許可しないというPHPの仕様なので、どうしようもない。
なので、子テーマ側で別名の関数を準備し、親テーマの実行結果を、子テーマの関数で更に操作してあげる必要があります。
ところが、もう一つの問題が、、、
読込順序
WordPressは、なぜか下記の順序で読込みやがりますwww
子テーマのfunctions.php
↓
親テーマのfunctions.php
この様に、子テーマのfunctions.phpが読み込まれた後、追加で親テーマのfunctions.phpが読み込まれるため、通常では、子テーマのfunctions.phpが実行されてしまい、子テーマ側から親テーマの関数の動作を制御する事ができません。
面倒ですねw
functions.phpを上書きする方法は無いの?
じゃあ、親テーマの動作を子テーマから制御できないの?という事になりますが、どうにかする方法が2つあります。
1.親テーマにfunction_exists()があればラッキー
親テーマのfunctions.php側で、カスタマイズしたい関数にfunction_exists()の判定が設定されていれば、子テーマで再定義(同じ関数名が使える)できます。
(というより、該当の関数が既に読み込まれていれば、それ以上読み込まないという条件判定ですが)
子テーマ側でのカスタマイズを想定されているテーマであれば、カスタマイズされそうな部分に、この判定が設定されています。
Stinger5だと、下記の部分が該当しますね。
//function_exists()の判定あり //ウイジェット追加 if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar(4) )
なので、Stinger5ではdynamic_sidebar関数は子テーマでオーバーライド(上書き)できる。
という事になります。
2.親テーマにfunction_exists()が無い時は?
親テーマのfunctions.phpにfunction_exists()の判定が設定されていない場合は、残念ながらどうしようも有りません。。。
というのは冗談ですw
問題となるのは、読込順序なので、最後に動作するように、ちょっとした、おまじないを書いてあげればOK。
例えば、
//おまじない function after_all() { <処理> } // 親テーマの後に実行 add_action( 'after_setup_theme', 'after_all' );
と書いてあげれば、after_all()という関数は、全テーマの読み込み完了後に、実行されます。
※after_allの部分は任意。
なので、この関数の中に、親テーマの動作を書きかえる処理を入れてあげればOKという事になります。
この辺りの仕組みを、もう少し詳しく知りたい場合は、下記サイトの説明が解りやすいかも。
参考:WordPressをカスタマイズするなら覚えておきたいアクションフックとフィルターフック
実際にやってみよう
以上を踏まえて、子テーマ側でウィジェットを追加してみましょう。
そのまま追加
まずは、読込み順序を気にせず、そのまま追加してみます。
すると、管理画面上の表示順が見事に崩れますwww
しかも、
中身も、トップに来ているハズのサイドバーウィジェットの内容に置き換わってしまっています。
これでは管理上、具合が悪いので、「おまじない」を追記してみましょう。
おまじない有り
おまじないを追記すると、こうなります。
実際に追加したコード
以下、実際に記述したコードを記載しておきますので、導入してみたいという場合は参考にして下さい。
- functions.php(子テーマ)
functions.phpのコードは下記の通りです。なお、親テーマ側には何も手を入れていません。
//functions.php <?php if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar(5) ) if ( !function_exists('after_all') ): function after_all() { register_sidebars(1, array( 'name'=>'CTA-記事下', 'before_widget' => '', 'after_widget' => '', 'before_title' => '<h4>', 'after_title' => '</h4>', )); } endif; // 親テーマの後に実行 add_action( 'after_setup_theme', 'after_all' ); ?>
- single.php(親テーマ)
single.phpについては、親テーマ側に下記のコードを挿入しました。
//single.php <!-- CTA ここから--> <div class="call-to-action"> <?php if ( function_exists('dynamic_sidebar') && dynamic_sidebar(5) ) : else : ?> <p>CTA</p> <?php endif; ?> </div> <div class="clear"></div> <!-- CTA ここまで-->
なお、挿入位置は下記コード(ソーシャルボタンの読込み)の後にしましたが、お好きな位置で大丈夫かと思います。
//ソーシャルボタン読み込み <?php get_template_part('sns'); //ソーシャルボタン読み込み ?>
- ウィジェット
通常、ウィジェットにはテキストを配置して、画像リンクを並べてあげれば良いだけですが、今回は少し工夫が必要でした。
というのも、Stinger5ではウィジェット中に画像を並べて記載すると縦並びとなってしまうため。
これを解消するために、<div>タグで囲み、スタイルシートで並びを設定してあげる事に。
//ウィジェット <div class="sns_icons"> <ul> <li> <画像リンク> </li> </ul> </div>
※<画像リンク>の部分は、ご自身のブログに合せて下さい。
- style.css(子テーマ)
style.cssには、ウィジェットのデザインと、アイコンを横並びにする処理を追加しています。
ウィジェットのデザイン用コード
//ウィジェットのスタイル /*----------------------------------- call-to-actionウィジェットのスタイル ------------------------------------*/ .call-to-action { color: #dddddd; overflow: hidden; background: #666; border-top: solid 1px #dddddd; border-bottom: solid 1px #dddddd; margin: 20px -40px; padding: 50px 50px; } .call-to-action span { background-color: #666; font-size: 150% }
アイコンを横並びにする処理
//アイコンの横並び /*----------------------------------- アイコンの横並び ------------------------------------*/ .sns_icons ul{ list-style: none; overflow: hidden; } .sns_icons ul li{ display: inline; float: left; position:relative; }
ポイントは
- [list-style: none;]の部分でリストの中点を消す。
- [overflow: hidden;]で、この要素内だけの周り込みとする。
- [float: left;]でアイコンを回り込ませて横並びにする。
の3点ですね。
以上、
ざっと見ていきましたが、ポイントはいかに子テーマ側のfunctions.phpで親テーマ側の制御をしてあげるかです。
仕組みが解ってしまえば、それほど困難という訳でも有りませんので、頑張って子テーマ側のfunctions.phpでのカスタマイズにトライしてみてはいかがでしょう?