この質問への続き:
私はWordPressを使って作業することはめったにないので(phpBB、myBB、Concrete5、およびカスタムPHPスクリプトを使って多くの作業を行ってきましたが、私のWordPressの経験は1つか2つの単純なサイトに限られます)私はここで3時間かけてドキュメントを読むよりも早く答えが出るかもしれません。
WordPressのメニューを自分のものに置き換えるためのプラグインを作成しています。これまでのところ、このプラグインのコードです(すべて1つのPHPファイルに含まれています)。
add_action('init', 'DEMenu::init');
class DEMenu {
public static function init() {
$DEMenu = new DEMenu();
load_plugin_textdomain ('de-menu', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/');
/* Load CSS with wp_enqueue_style() */
// If in admin page, then load admin page stuff
if (is_admin()) {
add_action('admin_menu', 'DEMenu::admin');
}
// If not on admin page ...
else {
// Load plugin core - doesn't require a hook
$DEMenu->core();
}
}
public static function admin() {
add_options_page('DE Menu Options', 'DE Menu', 'manage_options', 'de-menu', 'DEMenu::options');
// add_option('de_menu_maintenance', 'off');
}
public static function options() {
if (!current_user_can('manage_options')) {
wp_die( __('You do not have sufficient permissions to access this page.') );
}
echo '<div class="wrap">';
echo '<p>Here is where the form would go if I actually had options.</p>';
echo '</div>';
}
public static function core() {
/* Add support for various themes */
add_filter('wp_nav_menu', 'DEMenu::display');
/* If I need to add more actions/filters they will go here... I may enqueue CSS here, too */
}
public static function display() {
print "Let's see if this displays. I'll add some text to ctrl+F for later";
}
}
これは主にWordPressのドキュメント、プラグイン開発のチュートリアル、そして基本的なOOPプラクティスからのさまざまなアドバイスの集大成です。
今、私はDashboard> Appearance> Menusエリアからメニューを描画することを任務としています。このメニューオブジェクトを(配列またはその他のアクセス可能なデータ型として)アクセスして、作業できるようにするにはどうすればよいですか。
私が同じメニューを使用しようとしているのであれば、wp_nav_menu()
の出力を完全に上書きするのはばかげているように思えますが、他の方法で自分が望むことを達成することはできません。
編集 -
wp_nav_menu()
がメニュー項目のリストをどのように取得するのか、そしてそれがどのように表示されるのかを学ぶためにwp-includes/nav-menu-template.php
を読んできました。私は基本的に、この関数で使用される方法を、多列構造に追加するためのわずかな変更を加えてのみエミュレートすることを試みてきました。これが私がこれまでに持っているものです:
public static function core() {
/* Add support for varoius themes */
add_filter('wp_nav_menu', 'DEMenu::display', 1);
/* If I need to add more actions/filters they will go here... I may enqueue CSS here, too */
}
public static function display( $args ) {
/* The following is blatantly ripped from nav-menu-template.php */
// *****************************************************************
/* Excluded for ease of reading - this is an exact copy of nav-menu-template.php */
// *****************************************************************
// Here we can invoke our custom walker without editing the theme
$args->walker = 'DEMenu_Walker';
$items .= walk_nav_menu_tree( $sorted_menu_items, $args->depth, $args );
unset($sorted_menu_items);
// *****************************************************************
/* Excluded for ease of reading - this is an exact copy of nav-menu-template.php */
// *****************************************************************
// $nav_menu = apply_filters( 'wp_nav_menu', $nav_menu, $args );
//
// if ( $args->echo )
// echo $nav_menu;
// else
// return $nav_menu;
// Rather than checking if we should echo the output, just return it.
// This is a filter, so the output will be echo'd by the calling function
return $nav_menu;
}
それから後で(DEMenuクラスの外で):
class DEMenu_Walker Extends Walker_Nav_Menu {
function __construct() {
die("We made it to the constructor!");
}
}
ただし、次のようなエラーが表示されます。
Warning: Attempt to assign property of non-object in /home/coupon/public_html/wp-content/plugins/DE-menu/index.php on line 146
この行番号は以下を参照しています。
$args->walker = 'DEMenu_Walker';
おそらく私が見過ごしてきたはるかに合理的な解決策がありますが、私が言うことができるものから私はカスタムウォーカークラス(表示されたアイテムの数と表示されるべきアイテムの数を追跡するプライベート変数と一緒に)を必要としますこれはテーマを編集せずにカスタムウォーカークラスを使用する唯一の方法です。しかし、私が現在取り組んでいる解決策を使用するのであれば、wp_nav_menu()
が関数の最初のほうに次のコード行を明確に含んでいるのに、なぜ$args
変数が非オブジェクトであるのかを理解する必要があります。
$args = (object) $args;
他の編集 -
私は非オブジェクト問題を解決しました。 wp_nav_menu()
がフィルタを呼び出すとき、それは次のようにそれを呼び出しています:
$nav_menu = apply_filters( 'wp_nav_menu', $nav_menu, $args );
私はこれが2つの議論を通過させることを意味していることに気づかなかった。表示機能を次のように修正しました。
public static function display( $nav_menu, $args ){
そしてもちろんadd_filter()
呼び出しを以下のように修正しました:
add_filter( 'wp_nav_menu', 'DEMenu::display', 1, 2 );
今では私はあらゆる種類の楽しい新しいエラーを得ています。
Fatal error: Using $this when not in object context in /home/coupon/public_html/wp-includes/class-wp-walker.php on line 185
念のために言っておくが、私はWordPressコアにまったく変更を加えていないので、class-wp-walker.php
..にエラーがある理由を理解できません。なぜこのエラーが発生したのかもわかりません。何か案は?
最終編集 -
https://stackoverflow.com/questions/6862887/replacing-wordpress-core-functionality-with-a-plugin から助けを借りて私はついに実現しましたwp_nav_menu()
関数全体をコピーせずに、wp_nav_menu_args
フィルターを使用して自分のwalkerクラスを渡すことができます。私はこの解決策を使用します(この問題を解決する)、上で述べたように - 私は私のwalkerクラスがその親クラスに致命的なエラーを投げさせるという新しい問題を抱えています。これはWalkerクラスの問題であり、メニュー項目へのアクセスやカスタムのWalkerの通過に関する問題ではないので、私はそのために新しい質問をします。
タスク:各サブメニュー(第2レベル以下)を5列に分割する必要があります(5つの別々の<ul>
要素または<div>
要素を特定の<li>
要素で囲む)。
最初:options()
には設定APIを使います( チュートリアル )。
2番目:コア関数 と利用可能なフィルタを見てください。それから利用可能なフィルタを見てください。
$sorted_menu_items = apply_filters( 'wp_nav_menu_objects', $sorted_menu_items, $args );
$items = apply_filters( 'wp_nav_menu_items', $items, $args );
$items = apply_filters( "wp_nav_menu_{$menu->slug}_items", $items, $args );