Blogs

You Asked for it, You got it, PHP in dotCMS

What is different this time?  

The original PHP+dotCMS effort was simply trying to get PHP files to be executed from the dotCMS web server.  Basically, the idea was that you would go to http://mydotcms.org/php/myphpfile.php and it would parse the php and render the output on the screen using the Querticus servlet provided by Caucho.   This time around, we came at the problem from a different direction and worked to get PHP running directly from Velocity, using the Scripting Plugin.  This means that you are able to evaluate PHP snippet or even call functions from a PHP file within your dotCMS from your templates, containers, and most importantly your content. You can even define a function in a piece of content and then call it on the same page.

This brings us to an interesting point. The primary purpose of the Scripting Plugin is to bring more flexibility and power to the dotCMS Web Developer. You can certainly do anything you want with Velocity but eventually you will be left with two options. 1) deploy Java on your system (Viewtools, Struts Actions, Restart, etc...) Or 2), limiting your custom tooling, which is not an option.  

The dotCMS plugin system provides phenomenal flexibility for creating custom tooling – it allowed us to develop this Scripting Plugin.  The problem is eventually your plugins will become more complex, require Java knowledge and deploying plugins always requires a restart. With the Scripting Plugin you can break into your favorite scripting language, create your custom logic, and then move along with HTML/Velocity. None of this requires a restart.  Adding in dotCMS’s built in WebDav support makes development fun again.  It feels like old times using my text editor (BBEdit) connected via WevDav to JS(Executed on the Server Side) or PHP and seeing my application come alive in real time.

Consider this scenario. You have a User Management Application written in PHP. You love dotCMS and would love to do more with it but haven't reached the point where you are ready to rewrite your existing code as a dotCMS Plugin. The Scripting Plugin allows you to bring your PHP library files to the dotCMS (because of course in your application you have separated the business logic :-) Now your PHP functions can be utilized to the fullest from anywhere with in dotCMS.

Note: Remember how the Scripting Plugin functions. When it deploys you get a role added to your system "Scripting Developer". If you use scripting from a piece of content you must make sure the last modified user of that content has that role or the script will NOT execute. The same is true for files. The last modifier of the file must have the role.

 

What can the scripting plugin with PHP do for you?


1. Let’s start off with the basic Hello
   I have a user with the role "Scripting Developer". I created a blank template and added a simple widget to my page with the following code.

   $scriptingUtil.evalPHP('return "Hello From PHP"')

   As you can see from the output PHP returned to us a String which is being displayed in our content widget.

2. Lets do the same thing but now lets declare a global variable and have PHP return its value to us.
   So now our code looks like this

   $scriptingUtil.declare('myname','Jason')
$scriptingUtil.evalPHP('return "Hello $myname From PHP"')

 

3. Now lets add our code to a function and call it

   #set($phpwrapper = $scriptingUtil.evalPHP('
   function callme($name, $calledfrom)
{
return "Hello $name From PHP called from $calledfrom";
}
'))

#set($args = $scriptingUtil.evalPHP('return array("Jason", "Velocity")'))
$scriptingUtil.callMethod($scriptingUtil.getPHPLanguage(),$phpwrapper,'callme',$args.getValue().valuesToArray())


This example requires some explaining. First I never have any luck defining arrays in Velocity. I know I can use the dotCMS viewtools to get an empty ArrayList and add elements to it and then call toArray() on the list but why not use PHP to build the array?  It might have been easier to use Groovy as the objects translate easier to Java, but I think building the array in PHP provides us a good example. Keep in mind we could have used any of the languages to break into Java and build the Array.

In this example 2 arguments were added to the function. There were passed to the $scriptingUtil Viewtool as an object[]. The $scriptingUtil.evalPHP returns an Object the plugin created which wraps the PHP output and PHP return value. This occurs because there are times your PHP outputs text or otherwise. For example an echo. Other times you return an object/value. When Velocity displays an Object it automatically calls the toString() method. It shows a String representation of the Object. Some Objects don't specify how to do this and on the screen you see a memory address of sorts. The wrapper object tries to be smart and figure out what you really want in its toString(). You can always call getOut() or getValue() to get at the values directly. That is what we demonstrated here. The PHP Array Value needed to be converted into something Velocity and ultimately our Java Viewtool can understand. The examples final argument uses $args.getValue().valuesToArray() to build our Object[] for the Viewtool.

I knew the object Object coming out of PHP was a PHP Array so I looked at the following doc. http://www.caucho.com/resin-javadoc/com/caucho/quercus/env/ArrayValue.html
If you look here you can see other classes which extend Value
http://www.caucho.com/resinjavadoc/com/caucho/quercus/env/Value.html

4. We also can do a similar test by placing our function in a PHP file

Here are the contents of the PHP file /global/php/test.php

<?
function callme($name, $calledfrom)
{
global $globalvar
return "Hello $name From PHP called from $calledfrom and the global is $globalvar";
}
?>


And here is my Velocity code in my content

$scriptingUtil.declare('globalvar','global from velocity call php file')

$scriptingUtil.execFile("/global/php/test.php")

#set($phpwrapperobject=$scriptingUtil.evalExpression("/global/php/test.php",''))

#set($args = $scriptingUtil.evalPHP('return array("Jason", "Velocity")'))
$scriptingUtil.callMethod($scriptingUtil.getPHPLanguage(),$phpwrapperobject,"callme",$args.getValue().valuesToArray())


Note: I had to execute my file first $scriptingUtil.execFile. This compiles the file and gets it ready for use. Then the file name becomes a key to the compiled and cached PHP file providing great performance. The exec doesn't return anything but I needed the wrapper object.

#set($phpwrapperobject=$scriptingUtil.evalExpression("/global/php/test.php",'')). 

What's Next

  1. I will be cleaning up the tooling. I will provide more utility and helper tooling making it easier to interact with the scripting languages. For example eliminating needing to exec the file before evaluating an expression on it.
  2. Drop files and/or PHP applications in dotCMS allowing them to be run them directly via a URL (now in beta). Imagine dropping WordPress in dotCMS!

I hope the above examples help and provide direction. Now go download the Scripting Plugin and test it out. http://www.dotcms.org/plugins/

August 08, 2009

Filed Under:

php scripting plugin

Recommended Reading

Headless CMS vs Hybrid CMS: How dotCMS Goes Beyond Headless

What’s the difference between a headless CMS and a hybrid CMS, and which one is best suited for an enterprise?

Why Global Brands Need a Multi-tenant CMS

Maintaining or achieving a global presence requires effective use of resources, time and money. Single-tenant CMS solutions were once the go-to choices for enterprises to reach out to different market...

14 Benefits of Cloud Computing and Terminology Glossary to Get You Started

What is cloud computing, and what benefits does the cloud bring to brands who are entering into the IoT era?