Quite The Pickle... Wordpress Menu Items from Yii

Ok. I have my Yii app running "inside" of WordPress, as described here: http://www.yiiframework.com/wiki/213/integrating-wordpress-and-yii-yet-another-approach/

It’s a bit of a hack, but it works for my needs.

Now, my issue is that I want to have some items added to the WordPress menu depending on if the user is logged in or not. BUT, I want these items to be there even on WordPress pages, not just on the Yii application pages.

For example, the app I have lives at /yiiapp/ WordPress is installed at document root (/).

Obviously only within yiiapp/ are the pages going to have access to Yii. Adding items to the menu from there is trivial. The issue is when the user switches to, say, the home page, which is just the WordPress index page. Now, I have no way to add those Yii menu items.

Inside the WP theme that generates the menu I tried doing something like this:




$yii=dirname(__FILE__).'/../../../../yii-1.1.10.r3566/framework/yii.php';

$config=dirname(__FILE__).'/../../../yiiapp/protected/config/main.php';

require_once($yii);

Yii::createWebApplication($config);

$yiiMenu = new WpMenu;

$yiiMenuItems = $yiiMenu->getMenu();



WpMenu is my class to generate the additions to the menu. It works, EXCEPT that this is being called by the server, not by the user - so I don’t have the user’s session information, so I have no way to know if the user is logged in, thus I have no way to know what menu items to show them!

Any ideas on how else I could get this working?

I was doing some thinking / research on this this morning. Am planning on writing up some better documentation / wiki articles on it, but let me outline my approach really briefly.

Instead of running Yii / Wordpress as separate apps, you can run them combined with Yii running as the controller / router over top of Wordpress. In addition, load in the Wordpress settings/functions (sorry, don’t have the code handy at the moment) in your entry script. What you then need to do is have a Wordpress controller that acts as your fall back / default route if another URL rule doesn’t match. In your Wordpress controller, disable display of your layout ($this->layout = false) and launch Wordpress I think the code to do so was wp()

Because you load Wordpress function info in your entry script, you can then add Wordpress get_header() / get_footer() functions to your layout files and load Wordpress theming around your Yii pages.

Finally, to answer your question, you can easily hook into Wordpress’ menu system from within Wordpress and (ready for this?) run Yii code inside of Wordpress to set visibility of menu items. You have full access to Yii models, view rendering, etc because you’ve loaded Wordpress within Yii.

Things to look out for

Session stuff might get a bit tricky if both Wordpress and Yii are trying to do sessions (although I wasn’t having issues this morning with Wordpress, I ran into some snags with Drupal and accessRules, which apparently uses session). Once I disabled the access rules for my DrupalController, I stopped having session errors.

Sorry that’s so brief. Let me know if you want me to explain more and I’ll see if I can write it up more clearly tomorrow. Have some taxes to work on too (blech) …

Ok, more detail. Edit: posted a wiki article with more detail on this subject.

The easiest way to handle things is to have Wordpress in a separate folder within your webroot folder, as you don’t have to worry about Wordpress upgrades overwriting your stuff. You’ll then want to configure it so that Wordpress sets its links to your webroot path, but knows that its files are actually in webroot/wordpress (see attached file).

Add the below code to your entry script:




define('WP_USE_THEMES', true);

$wp_did_header = true;

require_once('wordpress/wp-load.php');



Create a Wordpress fallback controller (note the layout being turned off)




<?php


class WpFallbackController extends Controller

{

	public function actionIndex()

	{

		$this->layout = false;

		$this->render('index');

	}

}



Add the below rule as the last url rule that you have:




'urlManager'=>array(

	'rules'=>array(

		'*'=>'wpFallback/index',

	),

),



I also found that having Wordpress handle errors meant that I didn’t have to map every URL to Wordpress, but this could be improved:




// Error handler

'errorHandler'=>array(

	// use 'site/error' action to display errors

	'errorAction'=>'wpFallback/index',

),



Create a view/wpFallback/index.php file for your wpFallback controller:




<?php

wp();

require_once( ABSPATH . WPINC . '/template-loader.php' );



And adjust your main layout to spit out your Wordpress header/footer:




<?php

get_header(); ?>


	<?php

		// echos Yii content

	     echo $content;

	?>


<?php get_footer(); ?>



At this point, you can use Yii content inside of Wordpress functions, plugins, page templates, etc. I’ll see about posting a wiki article on this as well.

Thanks a lot for the detailed reply. I’m sure a lot of people will find this useful. I had a deadline to meet when I posted so I ended up hacking it a bit using jquery to add the items to the menu with an ajax call to get the additional menu items for the user. Once our current event is over I’ll your method a try, it’s much cleaner. Thanks again!

Sure, love to hear what you think. I was tickled when I figured it out :slight_smile:

Hey there. It’s been a while but I wanted to come back to say thanks again. I am getting our site up for this years event and took some time and switched over to this method. It is MUCH cleaner once it’s all working, great work.

It’s getting a bit late so maybe I’ll figure this out once I get a little sleep, but just in case…

Going back to my original problem, in my WP theme’s functions.php file I’ve added:




function yii_menu_extras($menu, $args) {

	$extras = WpController::actionMenu();

	return $menu . $extras;

}

add_filter('wp_nav_menu_items','yii_menu_extras', 10, 2);



This will call the actionMenu method of the WpController class to find items to add to the menu. It works great on WordPress pages, but as soon as I try to go to a Yii page I get an error:

Any idea what’s going on here?

Did you get this figured out? It looks like the WpController isn’t being auto-loaded. If you’re running things per my setup, you might also try this:




$this->actionMenu



As theoretically, you’re running Wordpress inside of the WpController, so should have access to the entire controller from within it. Does that work?

I did set it up as the Wiki specified, and everything is working great. I have the WpController class with just an actionIndex (and my actionMenu). $this is not available when I try to call it from the WordPress template’s functions.php file. It actually failed for both WordPress and Yii pages, whereas calling WpController::actionMenu() only fails for Yii pages.

What about doing this?




global $this;

$this->actionMenu();



Does $this work in your templates even if it isn’t working in your functions.php file? It may be a matter of scope that you run into there …

Does anything work with your WpController work in your template files?

I am also trying to get yii code to work in Wordpress theme. I need to call up the menu items from yii into Wordpress theme, but any partialRender calls do not work. I have followed the integration steps and have Wordpress theming the yii application (Lightspeed Webstore), I just can’t get anything yii to load on the Wordpress side.