Wordpress and Yii

Has anyone an experience with intergrating Yii into Wordpress? I just want to features which wordpress delivers with data selection and display features of Yii.

Need any help and/or suggestions.

Thanks, Tomek vel Aztech

really no one?

You ever have any luck with this?

I’m wanting to use WordPress for the CMS on a project but have some custom application pieces I’d prefer to be built with Yii. Trying to find a way to integrate the two.

You can use Yii as a Content Construction Kit, generating posts with yii.

Any luck with this at all?

not really. no… if somebody was adept at wordpress and Yii crossing this would have been answered a million years ago. [figure of speech. pun intended.]

anyway, i posted something like this back then, concerning dynamic page generations and all, but… yeah you guessed it. no luck whatsoever.

it would be very helpful if someone so knowledgeable in regards to this matter would shed a light into this issue.

I’m studying this for few weeks.

In this stage Yii can’t be integrated in Wordpress, mainly because Wordpress builds it’s page from top to bottom, linear, header, content, footer, and Yii from deep to front, in depth, controller first and at the end renders the layout.

Wordpress get use of the activated plugins and register the scripts using init functions where the scripts are clearly defined.

Yii builds an array of scripts and renders at the end.

Even a plugin for wordpress it’s somehow hard to make, for the same reason.

I don’t know if it’s a good explanation or I explained in an obvious way.

The good news is that Wordpress can be integrated in Yii, with some issues because of the scripts (again). The chances to double some scripts are big, but if you take care that can be avoided.

Regards,

Paul

Could it not be achieved by simply bypassing the layout?

I was able to create dynamic XML pages so I’m guessing a similar approach can be used. The thing is to bypass the apps menu and url management and manually call the apps based on wordpress hooks.

develop wordpress hooks using controller classes and render using partial rendering?

I am new to yii so I don’t know much about its inner workings. But isn’t there a way to bypass the psuedo Yii::app()->run() and use a Yii::app()->get_controller()? or just run controllers by instantiating them?

Hi,

Like almost all modern frameworks, Yii doesn’t provide an external access to it’s resources by design, even there are requests for that. There are some libraries that offers such access, I studied one, I don’t remember the name, but you can find it searching the forum. It’s pretty complex, anyway.

It’s possible to call Yii methods as you said but as I said previously there will be some issues with JS and CSS.

An idea is to make a plugin that through the short codes or something like that (a widget where to set the requested module/controller/method?) to call the methods you need.

For small plugins is really not need to use a powerful framework as Yii. In my research I discovered that real complex sites based on WP are developed in the theme, mainly because WP doesn’t offer all the hooks you need. As an example I didn’t discovered a hook to display something in the home page just before the first post, or just after the posts are displayed.

It’s not a problem to bypass the layout, also you can use the layout to output only the content. What you are doing with the assets? That’s the question. To load again and again the same files is not desired.

If we bypass the url management the result, I think, is only to display something, which I think is not the only thing that I want. For example, if is a form, how can I recover the posted data, where is submitted and where I’ll go after?

That why I’m thinking that WP have to be used (called) in the layout of Yii. You can’t have access to recorded JSs and CSSs from YII but you can access those from WP.

I’m makeing a new component that is derived from CController that acts as a Widget from WP, let’s call it Block. There are few implementations of blocks and layout regions around, but not what I need (from Widget).

This architecture impose to make a separate admin for what is made in Yii, but I have to see if can be integrated in WP admin.

I didn’t wanted to say more about what I think it should be done because is too early and I didn’t tested all.

A. Change the root index.php

  1. override the autoloader and register the new one. there will be problems with WP classes

  2. load a bootstrap that initialize (and only that) WP. Usually the scripts are prepared here.

  3. run

B. Add the blocks you need in the theme. For tests you can use $content variable and the widgets you want.

(C. Recover the WP scripts, remove them from WP and add them to Yii)

D. Start WP in the layout

For URL management I couldn’t found yet a solution to automatically add a parameter for ‘get’ mode. Looks that is possible to add something like that for ‘path’ mode. Advanced themes usually require that.

Please, give me a feedback.

Paul

Hi Paul, I have no experience at all with WP, but I integrated Yii with sucess in Joomla.

You can see here how I did, maybe you can take some idea from it.

Hope it helps.

Hi,

It’s a very good idea. I was thinking on it but I didn’t studied too much because I was not very sure that is what I want.

The tutorial you gave for Joomla is very good to and I’ll try to see if works for WP.

Thanks,

Paul

imasia,

The issue of js and css and url management shouldn’t be…I think I would like WP handle that…My reason for trying to use Yii in WP would be its easy building model code to handle process and data…something that WP doesn’t make as simplified( Drupal has it). I would leave the layout and assets up to WP and focus in simply using yii to handle data output and data processing using its logic.

zaccaria,

I’m glad you mentioned this…if yii was able to integrate into drupal ( in my opinion its more complex than WP) then WP should be a lot easier. I just need the time to explore it…

If you can explain WP to use a script for fill a div, you are done.

Then you have to understand a bit how to save the autoinclude function of wp (if it has one) and the trick is done.

I’m looking forward for your news!

Hi,

After I’ve spent two nights on this research I came out with this conclusion: You can develop an entire Yii app inside a page area of WP, with widgets, but without AJAX. There is a problem when you have the language in the URL, that I didn’t solve it, yet, that I don’t know how to add the lang segment, main check will be scriptUrl.

The key is URLRewrite. You have to be really good to make something working (I’m not so good, that’s why I’ve lost so much time :))

To prepare wordpress for integration:

  • install any plugin that can include a script and activate it

  • activate permalinks

  • make a page where you can include the Yii’s index.php (I named it ‘yiitest’). Find it’s ID. Mine is 5.

  • make inside WP folder a new folder (I named it ‘yii’) and add there a new Yii app

I think that’s all. Next step is the preparation of Yii app:

  • in main config add/modify these (components)



'assetManager'=>array(

	'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..\..\assets',

	'baseUrl'=>'yii/assets',

),

'request'=>array(

	'baseUrl'=>'yii',

	'scriptUrl'=>'test/wordpress/yiitest/',

),

'clientScript'=>array(

	'class'=>'WPClientScript',

),

'urlManager'=>array(

	'routeVar'=>'yiiPath',

	'urlFormat'=>'path',

),



  • override autoload to check some hardcoded WP classes and to skip the autoloader for them. You’ll find the name of the classes when the application screams that the autoloader doesn’t find them.

  • add a component named WPClientScript.php




class WPClientScript extends CClientScript

{

   public function registerCssFile($url, $media='')

   {

	  wp_enqueue_style( 'stylesheet', $url, array(), '', $media );

   }

 

   public function registerScriptFile($url, $media='')

   {

	  wp_enqueue_script( 'script', $url );

   }

}



In the end, config the url rewriter. I know, you’ll hate it because is for IIS7. So, here it is the ‘Web.config’ file




<?xml version="1.0" encoding="UTF-8"?>

<configuration>

  <system.webServer>

    <rewrite>

      <rules><clear />

<rule name="alfa01" stopProcessing="true">

			<match url="yii/([A-z_0-9/.]+)\.(css|js|gif|jpg|png)$" ignoreCase="true" negate="false" />

			<action type="Rewrite" url="{R:0}" appendQueryString="false" />

		</rule>

		

		<rule name="Main Rule" stopProcessing="true">

            <match url="yiitest" negate="true" />

            <conditions logicalGrouping="MatchAll">

                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />

                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />

            </conditions>

            <action type="Rewrite" url="index.php" />

        </rule>

		

		<rule name="Imported Rule 2" stopProcessing="true">

			<match url="yiitest$" ignoreCase="true" negate="false" />

			<action type="Rewrite" url="index.php?page_id=5" appendQueryString="false" />

		</rule> 

		

		<rule name="Imported Rule 1" stopProcessing="true">

			<match url="yiitest/([A-z_0-9/]+)$" ignoreCase="true" negate="false" />

			<action type="Rewrite" url="index.php?page_id=5&amp;yiiPath={R:1}" appendQueryString="false" />

		</rule> 

		</rules>

    </rewrite>

  </system.webServer>

</configuration>



Be careful, the order does matter.

In my opinion this is the most sensitive part of the artwork. I hope you’ll find better ideas and share them with us.

Paul

PS: I’m very tired and I apologize if I’ve missed something or if the regex is not well formed. Everything van be improved and, maybe, we will add later this description to wiki.

Another night spent, :( .

Lang in URL solved, and few other things:




'request'=>array(

	'class'=>'WPHttpRequest',

	'baseUrl'=>'http://localhost/test/wordpress/yiitest',

	'scriptUrl'=>'yiitest',

),

'clientScript'=>array(

	'class'=>'WPClientScript',

),

'urlManager'=>array(

	'urlFormat'=>'path',

	'showScriptName'=>false,

),



And a rule changed




<rule name="alfa01" stopProcessing="true">

	<match url="yiitest/(css|assets)/([A-z_0-9/.]+)\.(css|js|gif|jpg|png)$" ignoreCase="true" negate="false" />

	<action type="Rewrite" url="yii/{R:1}/{R:2}.{R:3}" appendQueryString="false" />

</rule>



WPHttpRequest.php




class WPHttpRequest extends CHttpRequest

{

    public function getPathInfo()

    {

        return $_GET['yiiPath'];

    }

}



Have a nice sleep,

Paul

imasia,

Very good work man…I’m sure your efforts won’t go in vain. Your saying the key to everything would be to re-write rules huh?

This is interesting. The url part of it i found very confusing in Yii. I was really hoping to take that right out of there…

I saw this the other day Zend + WP and I’m thinking how does Zend compare to Yii. Using the same philosophies can we achieve a similar approach…

Hi Imasia!!

Looks like that the wp inclusion looks very similar to joomla one, the phylosophy is to pass all the query string in a variable and let yii to do his magic.

Would be very kind if you can organize a bit more your work and publish a wiki like mine, so that future readers can enjoy our solutions.

If you need an help for it, pm me!

@zaccaria

the wiki article is done:

Wiki article

Maybe it will help you in future developments ;)

@all

What I don’t like is that you are stuck in a content area of a page, no other pages possible but with another Yii apps. The sidebars are only the ones provided by WP.

I’ll continue researching WP in Yii, could be a much flexible result.

please feedback

Paul

Hey Guys,

Well I finally had some time and tinkered a bit with the notion of integrating wordpress and Yii. Now for me I wanted to use Yii as a framework to develop wordpress plugins. Using some tips from imasia Article I was able to do a simple integration of yii as a wordpress plugin. The integration was very basic and i just used yii with its default installation site. I don;t know how it will really react with CRUD application as yet but it was fairly easy to integrate after reading the article…

So here is what I did

  1. first intall yii into the plugins directory

  2. in the config file I did this


<?php


// uncomment the following to define a path alias

//Yii::setPathOfAlias('wp-includes', ABSPATH . 'wp-includes');


// This is the main Web application configuration. Any writable

// CWebApplication properties can be configured here.

$plugins = parse_url(WP_PLUGIN_URL);

return array(

	'basePath'=>dirname(__FILE__) . DIRECTORY_SEPARATOR.'..',

	//'baseUrl'=> WP_PLUGIN_URL,

	'name'=>'My Web Application',

	//'aliases'=>array(

         //  'wp-plugins'=> ABSPATH . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins',

   // ),

	// preloading 'log' component

	'preload'=>array('log'),


	// autoloading model and component classes

	'import'=>array(

		'application.models.*',

		'application.components.*',

		//'wordpress.*',

	),

	'defaultController'=>'site', 

	'modules'=>array(

		// uncomment the following to enable the Gii tool

		/*

		'gii'=>array(

			'class'=>'system.gii.GiiModule',

			'password'=>'Enter Your Password Here',

		),

		*/

	),


	// application components

	'components'=>array(

		'user'=>array(

			// enable cookie-based authentication

			'allowAutoLogin'=>true,

		),

		'request'=>array(

			//'class'=>'WPHttpRequest',

			'baseUrl'=> WP_PLUGIN_URL . '/yiiplugin',

			'scriptUrl'=>  $plugins['path']  . '/yiiplugin/yii.php',

		),

		// uncomment the following to enable URLs in path-format

		'assetManager'=>array(

    		'basePath'=>dirname(__FILE__) . DIRECTORY_SEPARATOR.'..\..\assets',

   			'baseUrl'=>$plugins['path'] . '/yiiplugins/assets',

			),

		'urlManager'=>array(

			//'urlFormat'=>'path',

			'routeVar'=>'page',

			

			/*'rules'=>array(

				'<controller:\w+>/<id:\d+>'=>'<controller>/view',

				'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

				'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',

			),*/

		),

		/*

		'db'=>array(

			'connectionString' => 'sqlite:'.dirname(__FILE__).'/../data/testdrive.db',

		),*/

		// uncomment the following to use a MySQL database

		/*

		'db'=>array(

			'connectionString' => 'mysql:host=localhost;dbname=testdrive',

			'emulatePrepare' => true,

			'username' => 'root',

			'password' => '',

			'charset' => 'utf8',

		),

		*/

		'errorHandler'=>array(

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

            'errorAction'=>'site/error',

        ),

		'log'=>array(

			'class'=>'CLogRouter',

			'routes'=>array(

				array(

					'class'=>'CFileLogRoute',

					'levels'=>'error, warning',

				),

				// uncomment the following to show log messages on web pages

				/*

				array(

					'class'=>'CWebLogRoute',

				),

				*/

			),

		),

	),


	// application-level parameters that can be accessed

	// using Yii::app()->params['paramName']

	'params'=>array(

		// this is used in contact page

		'adminEmail'=>'webmaster@example.com',

	),

);

It was tricky at first…I had to make sure the “baseUrl” and path related variables were correct (using relative in instances really help) and I had to change the route variable name… wordpress in admin starts off like wp-admin/admin.php?page=site/contact Yii is more /index.php?r=site/contact. I thought changing the path format would have helped but didn’t…no need to anyway. setting the aliases and stuff is not necessary either ( i need to take it out so as to not misguide anyone)

  1. with the index.php file I did the following

<?php

/**

 * @package Yii Test Plugin

 */

/*

Plugin Name: Yii Test Plugin

*/

// change the following paths if necessary


function yiiapp_init(){

	global $yii_app;

	

	

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

	$yii_app = Yii::createWebApplication($config);	

	//$yii_app = Yii::createApplication('SiteController',$config);

	//Yii::setApplication($yii_app);

	

}


function yiiapp_admin_actions()

{

   	global  $yii_app;

	add_menu_page("Yii", "Home", 1, 'site/', array(&$yii_app,"run"));

	add_submenu_page('site/', 'Yii', 'About', 1, 'site/page/view/about', array(&$yii_app,"run"));

	add_submenu_page('site/', 'Yii', 'Contact', 1, 'site/contact', array(&$yii_app,"run"));

	//add_submenu_page(basename(__FILE__), "Yii", "Contact", 3, __FILE__, array(&$yii_app,"run"));

	

}


global $yii_app;

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

// remove the following lines when in production mode

defined('YII_DEBUG') or define('YII_DEBUG',true);

// specify how many levels of call stack should be shown in each log message

defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',6);

require_once($yii);


if ( !defined( 'WP_AUTOLOAD_CLASSES' ) ) {

    define(

        'WP_AUTOLOAD_CLASSES',

        function_exists( 'spl_autoload_register' )

    );

}


if ( WP_AUTOLOAD_CLASSES ) {


	function wp_autoload( $class, $path = null ) {

		$classes = array('SimplePie' => ABSPATH . 'wp-includes/class-simplepie.php', 'WP_User_Search' => ABSPATH . 'wp-admin/includes/user.php');


		// Being called by PHP's autoloader

		if ( is_null( $path ) ) {

			

			if ( isset( $classes[$class] ) && !class_exists($class,false)) {

				include_once( $classes[$class] );

			} else {

			   


			}

			return;

		}


		// Being called by us

	   	// $classes[$class] = $path;

		// spl_autoload_unregister( 'wp_autoload' );

	}


    // Register it

   spl_autoload_register( 'wp_autoload' );

} else {

	function wp_autoload( $class, $path ) {

		require_once( $path );

	}

}


class YiiAutoLoad extends YiiBase {

	

	 public static function autoload($className)

	 {

	 	if(!class_exists($className,false))

			parent::autoload($className);

	 }

}


Yii::registerAutoloader(wp_autoload);


add_action('admin_init', 'yiiapp_init');

add_action('admin_menu', 'yiiapp_admin_actions');

//add_action('');

spl_autoload_unregister(array('YiiBase', 'autoload'));

spl_autoload_register(array('YiiAutoLoad','autoload'));

The above is code to generate initialize yii as a plugin and add the respective wordpress admin menus. The really obscure thing here is that yii’s autoload was enabling even WP external classes. WP doesn’t really have classes and the file names do not follow the same scheme. I had a simplepie on a wordpress 3.1. Yii kept trying to autoload it so you have to make your own custom autoload for WP and Yii to cater for wordpress classes and check for class_exists() in Yii. This would vary based on wp plugins and the use of OOP. Then use Yii registerAutoloader to load the custom autloaded when needed.

Adding menus that lead to yii urls paths was tricky also… but thanks to routeVar the patterns would be the same. use WP action functions to run instances of Yii and let yii sort out the url paths. didn’t have to “rewrite” any htaccess and any url manager rules.

I had to create a yii.php which contains the "original" markup code for yii applications


<?php

/**

 * @package Yii Test Plugin

 */

/*

Plugin Name: Yii Test Plugin

*/

// change the following paths if necessary

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

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


// remove the following line when in production mode

defined('YII_DEBUG') or define('YII_DEBUG',true);


require_once($yii);

Yii::createWebApplication($config)->run();

This was used for the "ccaptcha" feature on the contact page. and is the "scriptUrl" for the request component in the config

The only thing left to do is edit the layout files or create your own theme for the "content" area i.e no header html tags as wordpress would be responsible for this.

The results of the above code can be viewed from the attached screenshots to this reply.

How do I get this as an article as well? Maybe who ever is in charge can put it in the wiki.