Phalanger http://www.php-compiler.net The PHP language compiler for .NET Framework Tue, 07 Feb 2012 15:39:46 +0000 en hourly 1 http://wordpress.org/?v=3.3.1 Writing compiled PHP extensions in PHP http://www.php-compiler.net/blog/2012/php-extension-in-php http://www.php-compiler.net/blog/2012/php-extension-in-php#comments Tue, 07 Feb 2012 14:11:40 +0000 Jakub Míšek http://www.php-compiler.net/?p=813 Continue reading ]]> PHP offers a lot of various extensions which add additional library functions, classes, constants and other constructs. Common extensions include for example php_mysql and php_iconv. Since extensions are implemented in C language, the performance is great. It also allows programmers to use other native libraries that are not available in PHP. However there is one big disadvantage; writing such extensions is not easy. C code is harder to maintain, it requires learning lower-level language and it is easier to make mistakes that lead to program failures that are hard to handle.

Writing custom extensions is mostly done by companies requiring high performance code. Most of the normal libraries are written in PHP as a bunch of standard PHP scripts containing functions and classes. Users then include these libraries as normal, and the result is very similar. Writing libraries in PHP is much easier then writing extensions in C language, but it has significant performance costs. Also the author has to expose the source code of their library, which is not always desirable (I know, there is a obfuscation; but also deobfuscation).

Phalanger approach

With Phalanger (the PHP compiler for .NET) developers can simply compile their PHP libraries as they are into a DLL file. Taking advantage of pure mode, the resulting compiled assembly can be used both from PHP scripts running on Phalanger or from any other .NET language.

Extension advantages

So there are three approaches of extending PHP scripts with your library functionality. Every approach has some advantages. As you can see, Phalanger offers best of both worlds. You can:

  • Write a bunch of PHP scripts as a “library”. Any PHP programmer is able to write such library. However library has to be processed and loaded every time it is used. Also you don’t have an access to native libraries written in other languages.
  • Implement PHP extension in C language. This requires better knowledge of PHP internals and C language. The prize for that effort is maximum performance. Also you can take advantage of other libraries written in C/C++.
  • Implement Phalanger extension in PHP langage. When you take your PHP library and compile it using Phalanger, the result is DLL working as any other extension. You are using simple PHP syntax, but you have access to all the .NET libraries including your own. The extension is fast, compiled, and loaded only once. Moreover Phalanger compiler optimizes usage of such extension more than usage of a bunch of PHP scripts.

An example

The extension has to be compiled in pure mode. It has only one (logical) limitation – you are not allowed to write a global code. You can only declare global functions, global classes or global constants. Also there are no inclusions; all the source files are processed together, as one big script containing everything (the order of scripts is not important since there is no global code).

Imagine you need simple extension with one function. Something you cannot do efficiently in PHP :) , such as calling a .NET method. Sure you can call it directly from Phalanger-compiled PHP code without using an extension, but this is just for the demonstration:

<?php

function getextension($fname{
    return System\IO\Path::GetExtension($fname);
}

// Expose constant or a class as follows:
//   const MY_CONST = 123;
//   class MY_CLASS{};

?>

The code can be compiled by the following command or from Visual Studio:

phpc.exe /target:dll /pure+ /out:myex.dll /r:mscorlib ex.php

The command references .NET library “mscorlib” where the System.IO.Path class is defined and compiles the “ex.php” script. Resulting assembly “myex.dll” can be used as any other Phalanger extension by adding following into the configuration:

<add url='myex.dll' />

Thats all. Functions, classes and constants defined in the extension will be available in the PHP code. The extension can be distributed compiled, so the source code is safe. Since it is loaded as an extension, the performance is not degraded; and it does not matter how big your extension is.

Summary

This article is, of course, just a simple demonstration, but it shows a very powerful approach for extending PHP with extensions when using Phalanger. The approach described in this article has a number of applications - when porting applications from PHP to Phalanger, you can use it to reimplement a C extension that you’re using, so that you don’t have to change a single line of your program. You can also use it to wrap .NET functionality in a PHP-friendly way. Finally, the technique can be also used to re-implement standard PHP extensions that are not yet available in Phalanger (although, all major extensions are already available).

Complete example with sample usages is available at  discussion forum. See PHP extension in PHP. Note you can use Phalanger Tools for Visual Studio if you don’t like command line :-)

]]>
http://www.php-compiler.net/blog/2012/php-extension-in-php/feed 2
WordPress on .NET with SQL Server is Possimpible using Phalanger 3.0 http://www.php-compiler.net/blog/2012/wordpress-on-dotnet-with-sql-server-using-phalanger-3-0 http://www.php-compiler.net/blog/2012/wordpress-on-dotnet-with-sql-server-using-phalanger-3-0#comments Mon, 23 Jan 2012 14:05:36 +0000 Marc Mezzacca http://www.php-compiler.net/?p=776 Continue reading ]]> In a recent scenario I wanted to run WordPress as a subdirectory of a .NET application. I also wanted to avoid installing PHP and MySql on the Windows server. Impossible? Apparently not! (I’ll get to the word Possimpible a bit later).

I already have IIS and SQL Server setup, so I want to utilize those with WordPress. To do this I installed a pre-compiled version of WordPress, using Phalanger, as well as a simple WordPress plugin to avoid having to install MySql.  Here is what I did…

Contents

Download the Goods

First, you’ll need to grab a few things prior to starting.

The environment I worked on was IIS 7/7.5 with SQL Server 2008 Express and .NET 4.0 on Windows 2008. You should have a similar combination of software installed if you expect it to work properly after following this tutorial. I also used SQL Server Management Studio Express to make things a bit easier for creating the database. If you don’t have it, you can grab it here.

NOTE: This post is heavily based on Miloslav’s previous post for Installing WordPress on .NET 4.0, however I’m using SQL Server instead of MySql and a newer version of Phalanger.

Install Phalanger 3.0

Extract the contents of the download and run the Setup Wizard to install Phalanger by following the on-screen instructions. Should be simple enough!

NOTE: You can skip this step if you wish to do a standalone deployment or don’t have access to the server, as written in the Installation Free Phalanger article previously by Jakub. Be sure that you have the Microsoft Visual C++ 2010 SP1 x86 Redistributable installed or it will throw an error about php4ts.dll not being found!

Install WordPress

Extract WordPress to a directory of your choosing within IIS.

NOTE: I downloaded the IIS version of WordPress, although I’m not certain it matters.

In this tutorial I already have an ASP.NET 4.0 Web Application running in a directory (cfv2). I am going to install WordPress as a separate Web Application, but as a sub-directory that lives within this website. There are a couple ways to do this, but in this case I am installing it in a physical subfolder of the existing .NET web application. I created the directory at:

c:\inetpub\wwwroot\cfv2\wpblog\

NOTE: You can use wwwroot of IIS or any other virtual directory.

Next, set write and modify permissions for IIS_IUSRS on this folder. This is necessary since WordPress creates wp-config.php file during the installation. Also, WordPress needs the write permission to allow auto update feature, downloading themes, plugins, etc.

To set the permissions, open Command Prompt with the Administrator permissions and run the following command:

icacls c:\inetpub\wwwroot\cfv2\wpblog /grant BUILTIN\IIS_IUSRS:(OI)(CI)(M)

NOTE: If you don’t want to allow this you can create the configuration file manually during the installation. WordPress recognizes that it doesn’t have permissions to create the file and gives you content for this file. Then you can create the file manually.

Setup the Web Application

I’ve created the physical subdirectory (wpblog), but now I need to set it up as a Web Application in IIS. There are a couple steps here that may differ for you depending on your setup.

Create a 32-Bit Application Pool

For the open source version of Phalanger to work properly you’ll need an Application Pool that is 32-Bit enabled. So here I will create a new Application Pool that will run in 32-Bit Mode. In IIS go to the Application Pools area under your server. Right click and do “Add New Application Pool…” I called mine WordPress. Select .NET 4.0 or above and click OK.

clip_image002

Next, check the list of Application Pools that should appear on the right. Select the newly created one and right click and select “Advanced Settings” option. Change “Enable 32-Bit Applications” from False to True.

clip_image004

Create a Web Application

In IIS right click and select the “Add Application”, then set the Physical Path to the wpblog directory. I’m going to call it “blog” so eventually it will look like http://mysite/blog/

clip_image006

Next select the previously created Application Pool (called WordPress as mentioned in the previous step)

clip_image008

Add a Web.config File

Configure ASP.NET using Web.config.  The web.config file will reside in the root of the wordpress directory (in this case wpblog). Here is an example web.config file that uses Phalanger 3.0 references.

View the sample web.config file.

Alternatively, view the sample web.config file for standalone installations including URL rewrites for pretty permalinks.

More information about configurations can be found here in the wiki.

Setup your SQL Server database

Create a new empty SQL Server database for the WordPress stuff to reside. Optionally, you can skip this if you have already created one or are planning on using an existing database.

clip_image010

Be sure to setup a user with high enough privileges to create the tables.

clip_image012

Setup the WP Database Abstraction Plugin

Now we’ll need to follow the DB Abstraction plugin instructions.

Upload wp-db-abstraction.php and the wp-db-abstraction directory to wp-content/mu-plugins. This should be parallel to your regular plugins directory. If the mu-plugins directory does not exist, you must create it.

clip_image014

Move the db.php file from inside the wp-db-abstraction directory to wp-content/db.php

Setup and install the plugin by going your wordpress url (eg. http://localhost/blog/) with the subdirectory /wp-content/mu-plugins/wp-db-abstraction/setup-config.php appended to generate your wp-config.php file.

clip_image016

Follow the on-screen instructions from the point on…

That is it. Now just follow the normal WordPress setup and you’re home!

NOTE: After installation, see Miloslav’s article for information about setting up permalinks by modifying your web.config file.

Optional: Pre-Compile WordPress with Phalanger

Phalanger can compile the source code to a .NET assembly for improved performance. This is suggested!

NOTE: It is not necessary to precompile the web page; single scripts will be compiled during first requests subsequently. However it is recommended to precompile the application to make sure the application is error free and to lower response time during first request.

To do this, create a build.bat file in the wordpress directory with something similar to the following content:

@echo off
"C:\Program Files (x86)\Phalanger 3.0\Bin\phpc" /target:web /root:. /recurse:. /out:Bin /static+ /debug-

This batch file runs the Phalanger compiler to perform the pre-compilation. Detailed documentation for each of phpc option can be found here.

clip_image018

Error during Build? Here is a quick fix!

It will likely give you an error when you attempt to build (although this may be fixed in the future), so you have to make a slight modification to the WP Abstraction Plugin. I encountered an error with the Data Abstraction plugin at line 562 of the pdo.php:

clip_image020

It seems to choke on the “break;” line in the pdo.php since it is not in a loop. Modify it to “return;”, save the file, and then it should compile OK.

After it compiles successfully, the Bin folder should have a WebPages.dll file inside.  If you are doing a standalone install, you’ll need to drop all the necessary Phalanger DLLs in the Bin as well.

Concluding Thoughts

This is a real-world walk-through from notes as I set it up for my own purposes. There are numerous variations you can take along the way to set it up in your own environment and this post should only be used as a guideline. Definitely spend time testing it out in a local or sandbox environment before putting it into production.

I would highly suggest using the pre-compiled version versus non-compiled as it seems to offer some speed benefits. I tried both — the non-compiled version seemed to intermittently take long periods to load pages and sometimes would even timeout (load a blank page).

For high-level production environments, Devsense offers a Managed Extensions Pack for a fee, which provides increased speed, security and the ability to run in 64-Bit mode.

I’m a big advocate of using open-source .NET stuff, and also giving back. If you use the open-source version of Phalanger, please be sure to contribute by donating to the project.

That’s all! See, I told you WordPress on .NET with SQL Server is possible. In fact, it’s Possimpible (finally see the reference here). Still a skeptic? Check it out live at http://couponfollow.com/blog/ and be amazed! Well it needs some UI theme updates… and some content… but hey, it is working.

About the Guest Author

Marc Mezzacca is a .NET Programmer, entrepreneur, and founder of NextGen Shopping, a company dedicated to creating innovative shopping mashups. Marc’s latest venture is a social-media based coupon code website called CouponFollow that utilizes the Twitter API.

]]>
http://www.php-compiler.net/blog/2012/wordpress-on-dotnet-with-sql-server-using-phalanger-3-0/feed 12
Phalanger riding Mono http://www.php-compiler.net/blog/2012/phalanger-php-mono http://www.php-compiler.net/blog/2012/phalanger-php-mono#comments Tue, 17 Jan 2012 18:00:55 +0000 Jakub Míšek http://www.php-compiler.net/?p=637 Continue reading ]]> Phalanger is a complete reimplementation of PHP, written in the C# language. It was always being developed with the Mono platform in mind. This means you can compile and run PHP application on Linux web servers using Mono. Since Phalanger 3.0, this become more official, periodically tested and maintained.

Notes

Mono since 2.10.8 contains few fixes that allow running Phalanger powered applications. Mainly it fixes the recursive ReaderWriterLockSlim issue, which disallowed Phalanger in some special cases. If you encounter this issue, please update your Mono to version that has this fixed.

Installing Phalanger on Linux

Briefly, see configuration and add listed configuration options into your web.config file. Dependant Phalanger’s assemblies copy into Global Assembly Cache using “mono gacutil.exe -i” util. You will need PhpNetCore.dll, PhpNetClassLibrary.dll and required extensions (e.g. PhpNetMySql.dll, PhpNetSimpleXml.dll).

The rest of configuration is the same as for ASP.NET 4.0 web on Mono.

Too short?

This post is more an announcement than a tutorial of installing Phalanger on Mono. Phalanger installer for Linux will be published soon, so you don’t have to care about installing :-)

]]>
http://www.php-compiler.net/blog/2012/phalanger-php-mono/feed 2
.NET interoperability overview of Phalanger 3.0 http://www.php-compiler.net/blog/2012/net-interoperability-overview-of-phalanger-3-0 http://www.php-compiler.net/blog/2012/net-interoperability-overview-of-phalanger-3-0#comments Sat, 14 Jan 2012 16:35:43 +0000 Miloslav Beňo http://www.php-compiler.net/?p=696 Continue reading ]]> The main goal of Phalanger is to provide fast and easy means for PHP and .NET languages to interoperate with each other. When using Phalanger, PHP becomes a .NET language, but it’s still a dynamic language. That means that, in order to communicate with strongly typed languages as C#, we need more sofisticated architecture. This comes with DLR (Dynamic Language Runtime) and dynamic keyword in C#.

So far we had only few choices how to allow C# and PHP to communicate:

  • Pure mode – PHP gets compiled as standard .NET assembly http://wiki.phpcompiler.net/Pure_mode. Therefore it is easy to use PHP code from C#, but PHP code can’t use global code and inclusions.
  • Duck typing – PHP code can be standard with global code and inclusions. But you have to prepare special strongly-typed interfaces in C#. More details can be found here: http://tomasp.net/blog/ducktyping-in-phalaner.aspx. It is also possible to generate these interfaces from documentation comments.

With Phalanger 3.0 (January 2012) we have one more choice and so far it looks like most convinient one for most of the cases. This is a benefit of incorporating the .NET interoperability model provided by DLR. Using the DLR, it is much easier to call PHP functionality from C# using the dynamic keyword. In one of the previous posts my collegue explains how to use dynamic keyword in C# in combination with Phalanger 2.1. Some of it has changed since, so I want to show how it looks with the current release.

Globals

In Phalanger 3.0 we have implemented convenience dynamic object for simple access to global variables, functions etc. Motivation for this object is that .NET world is fully object-oriented and there is no way to invoke global functions or access global variables from C#.

You can get the instance of the object representing PHP globals from ScriptContext:

dynamic globals = ScriptContext.CurrentContext.Globals;

Following operations are currently available in this object:

  • globals.x - Global variable access.
    This construct assign or read global variable. If variable doesn’t exist it gets created.
    PHP: $x
  • globals.foo(arg1,arg2,...argn) - Global function invocation.
    Global PHP function foo gets invoked with the given arguments and variable is returned (if supplied in PHP function). All the necessary conversions are taken cared of.
    PHP: foo(arg1,arg2,...argn)
  • globals.@const.c Global constant access.
    Global constants can be assigned or readed like this or created if the constant doesn’t exist. The @const syntax is necessary to avoid collisions with variables.
    PHP: c
  • globals.@class.PhpClass(arg1,arg2,...argn) - Creates a new instance.
    The constructor of a class named “PhpClass” is called and new PHP instance is returned which has to be typed as dynamic in C#. Again, the @class syntax is necessary to avoid collisions with global function.
    PHP: new PhpClass(arg1,arg2,...argn)
  • globals.@class.PhpClass.xStatic variable access.
    This construct assigns or reads static class variables of a PHP class named PhpClass.
    PHP: PhpClass::$x
  • globals.@class.PhpClass.foo(arg1,arg2,...argn) - Static method invocation.
    Invokes a static method foo of a PHP class named PhpClass
    PHP: PhpClass::foo(arg1,arg2,...argn)
  • globals.@class.PhpClass.@const.x - Class constant access.
    Class constant can be assigned or read or created if doesn’t exist.
    PHP: PhpClass::x

All the constructs mentioned above work well also if PHP namespaces are used, it’s just necessary to specify the namespace using a special @namespace syntax: globals.@namespace.ns1.ns2.*

For example, globals.@namespace.ns1.ns2.@class.MyClass() – creates an instance of MyClass which is in ns1.ns2 namespace. PHP: new ns1/ns2/PhpClass().

Note: If your PHP is code compiled in pure mode using Phalanger(http://wiki.phpcompiler.net/Pure_mode). You don’t need the globals class at all, as you can access compiled PHP classes directly from C#.

Object Operations

In .NET, an object is the king and although some PHP applications still use procedural approach, there is a plenty of applications built using objects. In this part of the post I’ll explain basic operation on PHP objects that can be used from C# (or any other .NET language that supports DLR).

Create Instance

With globals object explained above you can create a new instance of class X with this construct:

dynamic x = globals.@class.X(arg);

In a previous version of Phalanger, this was also possible, but using a more complex syntax. You could create a new instance of PHP class by calling New method on ScriptContext.

Method Invoke

When we have dynamic object x, we call method just as we are used to in C#.

result = x.Hello(arg1,arg2,...argN);

Arguments can be any value type, reference type or strongly typed delegate which allows you callbacks from PHP code to C#. If PHP object is expected to be returned it has to be assigned to dynamic type.

You can also expect PHP magic method __call to work. If PHP object doesn’t contain method which is called and defined __call method, the method gets invoked with suplied arguments.

The current version of Phalanger does not yet implement the interoperability in the other direction (calling DLR objects from PHP code in Phalanger). This means that dynamic objects defined in C#, IronRuby or IronPython won’t work as expected from PHP code now, only standard CLR objects. This functionality is planed in a future release.

Get and Set Property

Getting or setting properties on PHP objects from C# works as you’d expect.

x.Field = 7;
int i = x.Field;

This works, but you have to be sure that x.Field contains int (or any other type you assign this field to), otherwise runtime exception will be thrown. We are considering implicit conversions with PHP semantics to avoid this in the future. But for the reference types it’s usually sufficient just to use C# operator as.

If you assign to the field that doesn’t exist runtime field is created or if PHP object defines special method __set(), the method will be called with two arguments, name of the assigned field and value to be assigned. Same principle applies when reading a value from field and object defines __get() method.

function __set($name,$value){ }
function __get($name){ }

Invoke on the object

In Phalanger 3.0 it’s possible to invoke PHP object that implements __invoke method or PHP delegate, but how? :-) . The code is surprisingly simple:

dynamic phpObj = globals.@class.PhpClass();
phpObj(arg1,arg2,...,argn);

The method __invoke gets called and any number of arguments can be supplied.

function __invoke($arg1,$arg2,...,argn){}

There’s however one limitation. The object can’t be called if it’s contained as a field of another object.

phpObj(); //this works
y.Field = phpObj;
y.Field(); // this won't work

The reason for this not to work is that we can’t be sure if you want to
invoke a method or invokable field.

Sample

Download the sample

I’ve created small PHP web site as a sample. The web site consits of three important files:

  • default.php – contains definition of PHP class PhpFriend
  • CsFriend.cs – This file is located in App_code folder and contains class CsFriend written in C#. This class gets automatically loaded when the AppPool starts.
  • web.config – Configuration of web site which in
    system.web/compilation/assemblies configration section adds PhpNetCore assembly, so it can be used from C# code

Default.php also contains global code which creates an instance of CsFriend C# class which is in namespace CsLib and calls its method called run.

$cs = new \CsLib\CsFriend();
$cs->run();

The run method just contains few demonstration of the operations I’ve explained here.

First we want to get PHP output stream, which is necessary to use for outputs. Because we want C# to output everything to the same stream as PHP, in order to PHP output control functions to work properly http://www.php.net/manual/en/ref.outcontrol.php . Then we’ll get the Globals object.

TextWriter output = ScriptContext.CurrentContext.Output;
dynamic global = ScriptContext.CurrentContext.Globals;

All the other parts of the sample are with comments so I won’t be explaining them here.

Conclusion

When I say PHP and .NET interoperability, there are two sides of the coin. First one solves how to use .NET in PHP (PHP -> .NET) and the other one solves how to use PHP world from .NET world (.NET -> PHP) which I was explaining in this post. Phalanger 3.0 and .NET with its dynamic type gives us an oportunity to use PHP code from .NET world in a very convinient way.

]]>
http://www.php-compiler.net/blog/2012/net-interoperability-overview-of-phalanger-3-0/feed 0
Passing .NET delegates into PHP http://www.php-compiler.net/blog/2011/pass-delegates-into-php http://www.php-compiler.net/blog/2011/pass-delegates-into-php#comments Sat, 10 Dec 2011 15:33:22 +0000 Jakub Míšek http://www.php-compiler.net/?p=701 Continue reading ]]> Phalanger is the only solution allowing to seamlessly interoperate between PHP and .NET world. It allows to use e.g. .NET generics, namespaces, properties, method overloads, global variables, constants and .NET delegates in both worlds. In this post I will show how to pass delegates from C# into PHP, and how to use them in PHP.

This interoperability feature is available since Phalanger 3.0, and it is very useful e.g. when writing C# plugins for PHP systems.

Imagine you have PHP function foo, getting a callable argument. Now you can call such function from C#, and pass a delegate as you are used to:

x.foo(new Action<int>((int i) =>
{ // do something
}));
x.bar(new Func<int, bool>(this.someMethod));

The conversion to PHP callable function accepts any .NET MulticastDelegate. In this way you can extend functionality of PHP application by passing .NET methods inside. PHP code itself does not need to be changed. It uses .NET delegates as usual PHP callable object; it can be called, copied or passed as callback to any function.

function foo( $func ) {
    $func(123);
}

Demo

To demonstrate the feature, we have a simple demo called ClrDelegates.

The application lets the .NET code to pass some delegates into PHP, and then it calls them to transform given text. It makes use of App_Code feature and other interoperability features that will be described in some future article.

foreach ($callbacks as $fnc)
     $str = $fnc($str);

The usage from within PHP code is very natural, as you can see above.

How does it work

When a MulticastDelegate object is passed from .NET to PHP world, Phalanger wraps the delegate into PHP object with __invoke() method. The __invoke() method is a natural way of creating callable PHP objects. Inside the function, it simply invokes original MulticastDelegate with given arguments. Thanks to this mechanism, PHP code does not even notice, it uses .NET delegates. You can only notice it by checking the class’s name.

Phalanger also checks if you are passing right amount of arguments. Note the types are not implicitly converted yet. .NET may throw an exception if argument’s type does not match the delegate’s type.

Conclusion

Phalanger 3.0 offers easy and useful way of injecting .NET method callbacks into PHP. It is natural to use from within C# and PHP too. Download and try the ClrDelegates  to see how seamlessly it works.

]]>
http://www.php-compiler.net/blog/2011/pass-delegates-into-php/feed 0
Using C# in App_Code from PHP scripts http://www.php-compiler.net/blog/2011/c-sharp-app_code-php http://www.php-compiler.net/blog/2011/c-sharp-app_code-php#comments Mon, 05 Dec 2011 12:00:38 +0000 Jakub Míšek http://www.php-compiler.net/?p=662 Continue reading ]]> Phalanger 3.0 brings several cool and useful features, making interoperability between C# and PHP even easier. In this post, I will show one of them.

Use cases

Imagine several use cases.

  • You have a PHP web site consisting of many .php scripts, and you want to extend its functionality or completely rewrite its back-end into C#. As you are used to, you would like to write your C# code into special App_Code folder.
  • You have ASP.NET web site already. And you are going to add some PHP scripts, because it is easier for your programmers or you have already the presentation layer in PHP. You still have to use existing C# objects from within these PHP scripts.
  • You have PHP web site, and you are going to slowly migrate to C#. You have to subsequently rewrite crucial parts of PHP code into C#, while other parts of your web are still in PHP. This hybrid web has to be working during the process normally.
All these cases have a common architecture. There are .php scripts all over the web site, and .cs scripts in App_Code folder. And you would like to use all your C# methods and classes seamlessly in the PHP code and vice versa.

Setup

Before Phalanger 3.0 release, you would need to write C# code in separated class library project, compile it into an assembly and add the reference into web.config file. This process is being used, however makes development a little slower than it has to be.
Now this process is handled by ASP.NET and Phalanger altogether. You don’t have to configure anything and things do work as expected.
Any public class, written in a script in a .NET language and placed in the App_Code folder is seamlessly visible in your PHP code, using standard PHP syntax.

Demo

I’ve created simple demo here: App_Code interoperability. The demo consists of one PHP page, containing the presentation layer, using Class1 written in C#. Notice there is no configuration linking these two worlds, the things work as it would be expected in any other ASP.NET site.

The demo takes advantage of several features of Phalanger & ASP.NET.

  • The web application remembers the last requested text and amount of requests. It is very easy thanks to the (real) static variables living in instance of ASP.NET AppPool. This technique can be used to achieve very effective in-memory caching.
  • PHP scripts are automatically compiled into .NET assemblies, and automatically recompiled if they change.
  • Backend of the application is easily written in C#, or partially written in C#. In this way crucial parts of the web application can be effectively implemented in C#, while you keep existing code in PHP.
  • Finally C# code in App_Code folder is automatically visible in PHP code, including namespaces, constants, properties and methods.
<b>Camels created: </b><?= Class1::$CamelsProcessed ?><br/>
<b>Previous camel: </b><?= Class1::$LastCamel ?><br/>

<?php
    $x = new Class1;
    $growncamel = $x->MakeCamelFromGet(); // $x->Camel( $_GET['babycamel'] );
    if ($growncamel):
    ?><h2><?= $growncamel ?></h2><?
    endif;
?>

The code above shows simple usage, seamlessly using C# class in PHP code. It really does not seem to use any .NET class, however Class1 is written in C#. It is auto-loaded from App_Code folder.

How does it work

The App_Code thing takes advantage of ASP.NET which automatically pre-compiles all the code in special /App_Code folder. The resulting assembly is placed in the HttpRuntime.CodegenDir (Temporary ASP.NET Files). The assembly name can be found in XML file “App_Code.compiled“, in the XML element “preserve“, attribute “assembly” (if it is not configured differently).

Phalanger itself was able to reference .NET assemblies before. However now it loads the App_Code assembly automatically without a need of an other configuration and compilation.

The App_Code assembly is loaded in compile time. This results in several compile time optimizations, so using such classes is naturally fast. Also when changing the App_Code content Phalanger automatically recompiles PHP scripts.

Conclusion

In this post I tried to demonstrate how easily write a part of PHP web in C#. In this way you can integrate existing C# code base with PHP presentation layer, or just subsequently transform crucial parts of PHP code into C# classes. You can try the ASP.NET website I’ve prepared (App_Code interoperability). It needs just Phalanger 3.0 installed and ASP.NET web server (easiest way is to open Visual Studio 2010, hit File-Open-Web Site, and browse for the folder containing the demo. Hit F5 and run.

]]>
http://www.php-compiler.net/blog/2011/c-sharp-app_code-php/feed 1
PHP, Global.asax and Output caching http://www.php-compiler.net/blog/2011/php-global-asax-cache http://www.php-compiler.net/blog/2011/php-global-asax-cache#comments Sat, 03 Dec 2011 14:33:26 +0000 Jakub Míšek http://www.php-compiler.net/?p=387 Continue reading ]]> Global.asax file gives web developers great posibilities of handling the life-cycle of their web app. It is a common practice to take advantage of this file in ASP.NET applications. Now you can make use of it in a PHP web application too.

Since Phalanger runs PHP web as a native ASP.NET application, you can extend its functionality using ASP.NET features. In this post I would like to show some advantages and possibilities of using Global.asax file in PHP web applications.

Adding Global.asax

Global.asax file is an optional file that contains code for handling application-level and session-level events raised by ASP.NET. To add that file into you Phalanger powered web, simply create Global.asax file in the web root, aside of your Web.config. You can use Visual Studio to create file for you (New > File > Global application class) or just copy following content. The process is the same as in any other ASP.NET application.

<%@ Application Language="C#" %>
<script runat="server">
    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
    }

    void Application_End(object sender, EventArgs e)
    {
        //  Code that runs on application shutdown
    }

    void Application_Error(object sender, EventArgs e)
    {
        // Code that runs when an unhandled error occurs
    }

    void Session_Start(object sender, EventArgs e)
    {
        // Code that runs when a new session is started
    }

    void Session_End(object sender, EventArgs e)
    {
        // Code that runs when a session ends.
    }
</script>

From the code above you can see some possibilities. There are many other events you can handle, e.g. Application_BeginRequest or Application_AuthenticateRequest.

ASP.NET output cache

The advantage of using Global.asax in a PHP web is that it gives you a way to easily extend the functionality of an application without the need to modify existing PHP code. This way, you can separate the core functionality of the application from an additional cross-cutting concerns, such as caching.

As a sample I will show how to enable output caching as easily as it is on ASP.NET pages. The whole trick consists of making use of Application_BeginRequest method and simulating <%@OutputCache%> tag, well known from .aspx code.

The OutputCache tag has many attributes; and when compiled by ASP.NET, it is translated into code calling several methods on Response.Cache object in specific order. This order have to be preserved to simulate the behaviour properly. Also it is valid for single page, whilst Application_BeginRequest is called on every page.

void Application_BeginRequest(object sender, EventArgs e) {
if (request.CurrentExecutionFilePath=="/index.php")
{
    var cache = Response.Cache;

    cache.SetCacheability(HttpCacheability.Server);
    cache.SetExpires(this.Context.Timestamp.AddDays((double)365));
    cache.SetMaxAge(new TimeSpan(365, 0, 0, 0));
    cache.SetValidUntilExpires(true);
    cache.SetLastModified(System.IO.File.GetLastWriteTime(request.PhysicalPath));
    cache.VaryByParams["*"] = true;
}
}

The code above simulates OutputCache tag, that would be placed on index.php page. By this, you programmically turn on caching of index.php. Using Global.asax has several advantages, as you can customize the caching behaviour. For example, you can extend the above example to turn off caching for pages if there is a cookie with specific values etc.

Cache dependency

Another feature of the ASP.NET caching mechanism is that you can specify dependencies. This means that a page is regenerated automatically if the dependency changes. With this we can invalidate page when something has been changed.

var cacheKey = Request.RawUrl;
if (HttpContext.Current.Cache[cacheKey] == null)
    HttpContext.Current.Cache[cacheKey] = new object();
Response.AddCacheItemDependency(cacheKey);

Here we add a dependency to currently requested page. Later in the PHP code when the page has to be regenerated, we can invalidate this cache by removing cacheKey from the Cache object.

// note: on Phalanger 2, use ::: syntax instead of \
$contextCurrent = \System\Web\HttpContext::$Current;
$key =  $RawUrlOfPageToBeInvalidated;
$contextCurrent->Cache->Remove($key);

Conclusion

In this short example we have shown that you can simply turn on caching of existing PHP web responses. Also we demonstrated an approach of extending functionality of PHP application by handling ASP.NET life-cycle. In the similar way you can handle new sessions, users authentication, authorization, errors, application start etc.

]]>
http://www.php-compiler.net/blog/2011/php-global-asax-cache/feed 0
Phalanger 3.0 http://www.php-compiler.net/blog/2011/phalanger-3-0 http://www.php-compiler.net/blog/2011/phalanger-3-0#comments Tue, 22 Nov 2011 13:22:41 +0000 admin http://www.php-compiler.net/?p=613 Continue reading ]]> Today we have released sources of Phalanger 3.0 – the PHP compiler for .NET Framework. It represents a big step for PHP compatibility, .NET interoperability and overall performance.The main changes include PHP 5.3 namespace support, PHP constants using const keyword, the support for Mono on Linux, improvements that enable using Phalanger with numerous open-source PHP applications and several bugfixes.

EDIT: Phalanger 3.0 is released under Apache 2 license.

Installation package

EDIT: The installation package of Phalanger 3.0 (for Windows) can be downloaded from phalanger.codeplex.com.

List of main changes

Configuration changes

  • Assembly versions changed to 3.0.0.0 (PhpNet*, php_*.mng)
  • Regenerated managed wrappers
  • DynamicWrapper directory doesn’t need to be specified
  • scripts are automatically recompiled if configuration changes
  • license updated to Apache 2

PHP 5.3 features

  • Full PHP 5.3 namespace syntax and semantic
    • parse-time full qualified name resolving (dynamically constructed qualified names ignore aliasing)
    • Function call and constant use from within namespace as it is in PHP (first look in the current namespace, then in the global namespace)
    • Compile time checks for type name duplicity
    • CodeDOM redesigned for PHP namespace semantics
  • Phalanger “import” statement deprecated
  • Phalanger “import” statement allowed only in Pure mode, postpones the parse-time qualified name resolving
  • callback can be specified as “CLASS::MEMBER”
  • constant(), defined() recognizes “CLASS::CONST”

Mono functionality

  • Fixed configuration loading
  • Fixed FileSystem debug asserts for linux
  • Fixed compiling of scripts in subdirectories on linux

.NET interoperability

  • MulticastDelegate automatically converted into callable PHP object (when passing from .NET to PHP)
  • Dynamic operations on PHP objects (method call, properties get and set) (DLR)
  • App_Code seamless integration

 PCRE

  • regexps group names are allowed to start with a number
  • preg_match_all() when used with PREG_PATTERN_ORDER should return groups even if there isn’t any match (PREG_SET_ORDER should return empty array)
  • Fix of preg_match(): indexed groups with more than one digit added also as named group
  • Fix of preg_match_all()

Compilation

  • Fixed emitting of namespaced empty statements
  • Fix of compilation (tried to generate ghost stubs in already built base interface)
  • Fix of creating long delegates (type name duplicity within a module exception)
  • Debugging information fix for “IF … ELSEIF …”, “IF … IF … ELSE”
  • Optimized CallSites container emitting, less types created and baked
  • Fix of emitting optional argument with TypeHint, that is not used in the function
  • Fix of abstract __construct declaration
  • Fixed Eval in Eval (when deferred class is being compiled, causing autoload which creates another deferred class)
  • Fixed __call() invocation when expecting a reference to be returned

 Code maintenance

  • Compiling Phalanger does not output any warnings
  • phpinfo() displays Phalanger version and whether it runs in debug and x64
  • some String.ToLower() replaced with CultureInfo.InvariantCulture.TextInfo.ToLower() (faster)

Other features

  • “libxml” extension stubs
  • Removed php6 language features
  • Implemented “const” keyword in global or namespaced code
  • stripslashes () erases “\” if it’s last character, as it is in PHP
  • Updated installer for new version, new output path
  • Fix of DOM childNodes, when there is a whitespace
  • base64_decode() with second parameter
  • ob_gzhandler() crash fix when browser e.g. does not send “accept-encoding” header properly
  • quoted_printable_encode() implemented
  • User-friendly error message when trying to use native extensions in 64 process.
  • Implicit conversion of PHP objects altered to comply with PHP ( $obj == 1 always )
  • Binary and some unary operations support PHP objects
  • join() with one argument
  • Internal optimization avoiding of repetitious Dictionary resizing
  • Internal optimization saving memory and garbage collector when declaring global function
  • dynamic call of global function optimization avoiding lookup in dictionary

SPL

  • iterator_apply(), iterator_count(), iterator_to_array()
  • interface OuterIterator, interface RecursiveIterator

Tests

  • Tests for PHP namespaces
  • New tests for PCRE
  • Tests for const keyword
  • Samples updated
]]>
http://www.php-compiler.net/blog/2011/phalanger-3-0/feed 11
“dynamic” keyword and PHP objects http://www.php-compiler.net/blog/2011/dynamic-keyword http://www.php-compiler.net/blog/2011/dynamic-keyword#comments Thu, 06 Oct 2011 14:21:34 +0000 Jakub Míšek http://www.php-compiler.net/?p=574 Continue reading ]]> We’ve already demonstrated, how to use PHP scripts from within a .NET application using Phalanger. For reference you can take a look at PHP as a scripting language for C# article or Standard mode interoperability tutorial. In this way we can take an existing PHP web or a library, load them into C# context and reuse their functions, classes, constants or global variables. In addition we can even define new functions and classes in C# and inject them into PHP, so the code in PHP seamlessly uses these declarations as they would be declared in PHP too.

EDIT: Phalanger 3.0 removes all the limitations mentioned below.

In this post I would like to show you, how to easily reuse objects defined in PHP code from C# environment – by using “dynamic” keyword introduced in C# 4. Since Phalanger translates PHP classes into general .NET types, the usage is very intuitive. However there is one catch …

For this demo, I have prepared ASP.NET application, that loads PHP scripts. First it loads a PHP script into C# context:

context.Include("script.php", false);

This “runs” script.php, and as a result context contains all the PHP declarations. At this point, you can e.g. take a look on context.DeclaredTypes, and list declared PHP types.

Now we can instantiate a PHP type, and take advantage of the dynamic keyword. Following statement instantiates a PHP class “X”, and passes its reference into a C# dynamic variable:

dynamic x = context.NewObject("X");

Then we can call methods on X class as we are used to. C# compiler automatically implements polymorphic inline cache (the same as we used in Phalanger compiler earlier) in run time, to determine what method should be called and to cache the call, so repetitious calls are executed faster.

var result = x.bar(context, 11);

You can notice the additional first argument here which is the only catch you should keep in mind. Phalanger requires the current context to be passed as the first argument in every method call. It is used later internally, mostly to enhance runtime performance.

EDIT: Phalanger 3.0 does not require the context to be passed.

Limitations (Phalanger 2.1)

Since this is the fastest way how to call PHP methods from C# context, several internal conversions between PHP and .NET world are skipped. It means you should only pass PHP/Phalanger compatible types as an argument: int, long, bool, string, PHP.Core.PhpBytes, PHP.Core.PhpArray and PHP.Core.Reflection.DObject (base class for all PHP objects, so any other PHP class instance is allowed).

Conclusion

In this post I have demonstrated how to take advantage of the “dynamic” keyword in C# so you can intuitively use your PHP objects in C# application. Please download attached ASP.NET demo to see it working. In addition to that, Phalanger allows many other ways of interoperability, e.g. the strongly typed Duck Typing.

]]>
http://www.php-compiler.net/blog/2011/dynamic-keyword/feed 6
Phalanger takes advantage of DLR http://www.php-compiler.net/blog/2011/php-compiler-dlr http://www.php-compiler.net/blog/2011/php-compiler-dlr#comments Mon, 01 Aug 2011 14:40:02 +0000 Miloslav Beňo http://www.php-compiler.net/?p=434 Continue reading ]]> We are happy to announce that Phalanger 2.1 for .NET 4 (August 2011), our PHP language compiler, takes advantage of Dynamic Language Runtime (DLR) [1] which is present in .NET 4.0 Framework and Mono.

We’ve decided to use DLR for a few PHP operations in order to improve their performance. So far, the operations that use DLR are field read access and instance method invocation. Using DLR improved the performance significantly, for some operations we measured even more than 6x performance improvement. This significant progress was possible because of DLR caching system which is actual implementation of polymorfic inline cache [2].

Before DLR, we were classifying operations into two cases (not counting eval), bound during compilation and bound during run time. The goal for Phalanger as dynamic language compiler is to compile as much as possible as compile-time bound operations and use runtime-bound operations only for cases that can’t be determined during compilation. DLR caching system allows compiling operation at run time when we know particular types for the operation and store compiled operation into cache. This can work efficiently because of the idea that when particular operation occurs, there is a big chance that the next time operands will have the same type.

Benchmarks

Following picture shows some selected micro-benchmarks. Each test of an operation was performed ten million times on Core i7 2600, 3.5 GHz, 16GB DDR3 desktop machine, running Windows 7 64 bit with .NET 4.0. You can clearly see the progress we’ve made with Phalanger in this release. The chart shows time required to run the operation 10 million times (so a smaller value is better):

PHP compiler microbenchmark

You may wonder why Phalanger performs static operations so efficiently. The reason is that operation is bound during compilation. At run time there are just few CPU instructions going on. In dynamic operations where we need to bind the operation at run time, we have to do more stuff, but still it’s pretty fast now thanks to DLR.

Our slowest operation at the moment is static method indirect call which is not using DLR. The reason is this operation isn’t frequently used in any PHP application I know. Anyway we are planning to improve it in the future.

If you want to try this benchmark by yourself you can get its sources from the source code repository on CodePlex from \Testing\Benchmarks\Micro directory.

Future work

August release is just the beginning of Phalanger’s incorporation with DLR. We’ve started with re-implementation of just few of the basic operations, mainly because of performance benefit of using DLR caching system. The goal here is that if we can’t bind the operation during compilation, the operation can take performance benefit of DLR. This doesn’t apply to the operations that are already implemented more efficiently in Phalanger and DLR would not improve their execution speed. Such operations are, for example, arithmetic operations, array access, comparison operators etc.

References

]]>
http://www.php-compiler.net/blog/2011/php-compiler-dlr/feed 8