Quick And Dirty Guide To Migrating PHP Code To C#
A couple of years back now I was tasked with some fairly heavy duty reporting on data held in Domino. It soon became apparent that only a SQL-based system could produce the data in the required format and so I set about writing some PHP to grab all the Domino data via repeated XML web requests and dump it in to MySQL.
Two years on and there's a chance I'll be picking up where it left off. So, partly as a learning exercise and partly to plan ahead I went about converting the LAMP side of things to ASP.NET. Turns out it wasn't half as hard as I thought it might be and didn't take all that long either.
The app I'm migrating is Flex-based and it makes calls to PHP files to fetch the reporting data in XML format. It's not really a LAMP website as such. After I'd changed all URLs in the Flex code ending in ".php" to end in ".ashx" I then created files with the same names in Visual Studio, but with the .ashx extension (Generic Web Handler file). Then I pasted the body of the PHP code in to the ProcessRequest method.
Syntax Similarities
Once the PHP code was inside Visual Studio it went all red and wiggly as all the errors highlighted themselves. It didn't take too long to get rid of the bulk of these errors due to the similarities between the PHP and C# languages, which use a similar syntax and operators etc.
For example. This PHP code:
$start = 1; $total = 0; $count = 100; $loaded = 0; while ( $total > $loaded || $start==1) { //Load XML from "xmlView?OpenView&start=".$start."&count=".$count $start+=$count; $loaded+=$count; }
Quickly turns in to this C# code:
int start = 1; int total = 0; int count = 100; int loaded = 0; while ( total > loaded || start==1) { //Load XML from "xmlView?OpenView&start="+start.ToString()+"&count="+count.ToString() start+=count; loaded+=count; }
A lot of the work is simply removing the dollar signs. A lot of the rest of what you need to do can be achieved using the Quick Replace feature in Visual Studio.
Here's a list of the find/replace alls I did to take the grunt work out of it.
Search For | Replace With |
". | "+ |
." | +" |
echo " | context.Response.Write(" |
$_POST[" | context.Request[" |
$_GET[" | context.Request.QueryString[" |
isset( | !String.IsNullOrEmpty( |
htmlspecialchars( | HttpUtility.HtmlEncode( |
$someVariable | someVariable |
in_array("aString", $myArray) | myArray.Contains("aString") |
$ |
With all of those replacement done I'd say that about 75% of the wiggly lines gone.
From MySQL to SQL Server
With all the syntax updated I then set about changing all the calls to MySQL to call SQL Server instead. Before I could do this I needed to recreate the database and tables. It's not a massive database so I did this by hand in the SQL Server Management Studio.
Once I'd re-created all the tables I added a Database Diagram in SQL Studio and defined the relationships between all the tables based on their primary key columns. Then in Visual Studio I added a new Data Set (.xsd) file and dragged all the tables on to there. Because I'd already defined their relationship in the Database Diagram, Visual Studio copied these relationships over for me.
With all the tables in the Data Set I then saved it and this then added a new TableAdapter class for each of my tables. Let's see how helpful these adapters are:
Here's the PHP code I was using to loop all the Products
$query="SELECT * FROM Products;"; $result = mysql_query($query); $data = db_fetch_rowset($result); mysql_free_result($result); foreach ($data as $key => $row) { echo $row["id"]; }
And the same thing in C#:
ProjectsTableAdapter pta = new ProjectsTableAdapter(); DataTable products = pta.GetData(); foreach (DataRow row in products.Rows) { context.Response.Write(row["id"]); }
Notice I've not had to use any SQL in the C# code. We'll see later on how much easier it makes adding data to the tables too.
Getting Data Via XML
The SQL data held in both versions came from Domino-based XML views. In PHP and C# it's actually quite easy to load and loop XML. Let's imagine we're loading XML in this format:
<products> <product> <id>1</id> <name>Product 1</name> </product> <product> <id>2</id> <name>Product 2</name> </product> </products>
In PHP you fetch, process and store the XML data like this (requires PHP5 to use "Simple XML"):
$products = simplexml_load_file($BasePath+"ProductsAsXML?OpenView&start="+$start+"&count="+$count); foreach ($products->products->product as $product) { $query = "INSERT INTO Products VALUES ("+$product->id+", '"+$product->name+"');"; $result = mysql_query($query); }
In C# you achieve the same thing like this:
XElement xml = XElement.Load(BasePath + "ProductsAsXML?OpenView&start=" + start.ToString() + "&count=" + count.ToString()); foreach (XElement product in xml.Element("products").Elements("product")) { pta.Insert(Convert.ToInt32(product.Element("id").Value), product.Element("name").Value); }
Not that "pta" is the same ProjectsTableAdapter we mentioned earlier. Notice how it added an Insert method when we created the Data Set and it takes the right number and types of arguments. Again, no need for any SQL code. It's much, much simple to deal with SQL in C# than PHP!
The XML processing code in PHP might read a little easier than in C# but they're both equally (and surprisingly) easy to achieve.
Summary
So, there you go. Porting PHP code to C# doesn't require you to re-write the code. Just tweak it a little. It's no 10 minute job but then nor does it take weeks. More likely to be days, but will always depend on size of app etc. The starting point has to be a find/replace though.
What did I get out of the exercise? Well, I learnt a bit more C# and all practice and exposure is good at this point. In the long run though I now have something that is much easier to maintain and development doesn't involve text editors and FTP clients. Instead I have a local web server to test on and full type-ahead predictive coding.
I'm not saying PHP is better than ASP.NET or vice versa. It's just that, given the choice of which I'd rather develop in, ASP.NET wins hands down. Give me a GUI any day!
Hi Jake,
Thank you very much for your example.
As always, very clear !
Reply
Funny how that syntax is so similar, I think it is because both languages have a big C heritage.
To me your post confirms the importance of always using friendly urls to begin with. It's no big deal in your example, but you could have saved one step if your initial URLs were not platform specific.
Reply
I've used PHP a couple of years. I'm now trying to learn C#. This article is useful in that process! Thanks a lot!
Reply