Tuesday, October 26, 2010

Notes from porting C# code to PHP

(Summary: I ported my TrueSkill implementation from C# to PHP and posted it on GitHub. It was my first real encounter with PHP and I learned a few things.)

I braced for the worst.

After years of hearing negative things about PHP, I had been led to believe that touching it would rot my brain. Ok, maybe that’s a bit much, but its reputation had me believe it was full of bad problems. Even the cool kids had issues with PHP. But I thought that it couldn’t be too bad because there was that one website that gets a few hits using a dialect of it. When Kaggle offered to sponsor a port of my TrueSkill C# code to PHP, I thought I’d finally have my first real encounter with PHP.


<?php echo "Disclaimer:"; ?>

To make the port quick, I kept most of the design and class structure from my C# implementation. This led to a less-than-optimal result since PHP really isn’t object-oriented. I didn’t do a deep dive on redesigning it in the native PHP way. I stuck with the philosophy that you can write quasi-C# in any language. Also, I didn’t use any of the web and database features that motivate most people to choose PHP in the first place. In other words, I didn’t cater to PHP’s specialty, so my reflections are probably an unfair and biased comparison as I was not using PHP the way it was intended. I expect that I missed tons of great things about PHP.

Personal disclaimers aside, even PHP book authors don’t claim that it’s the nicest language. Instead, they highlight the language’s popularity. I sort of got the feeling that people mainly choose PHP in lieu of languages like C# because of its current popularity and its perception of having a lower upfront cost, especially among cash-strapped startups. Matt Doyle, author of Beginning PHP 5.3, wrote the following while comparing PHP to other languages:

“Many would argue that C# is a nicer, better-organized language to program in than PHP, although C# is arguably harder to learn. Another advantage of ASP.NET is that C# is a compiled language, which generally means it runs faster than PHP’s interpreted scripts (although PHP compilers are available).” - p.5

He continued:

“ASP and ASP.NET have a couple of other disadvantages compared to PHP. First of all, they have a commercial license, which can mean spending additional money on server software, and hosting is often more expensive as a result. Secondly, ASP and ASP.NET are fairly heavily tied to the Windows platform, whereas the other technologies in this list are much more cross-platform.” - p.5

Next, he hinted that Ruby might eventually replace PHP’s reign:

“Like Python, Ruby is another general-purpose language that has gained a lot of traction with Web developers in recent years. This is largely due to the excellent Ruby on Rails application framework, which uses the Model-View-Controller (MVC) pattern, along with Ruby’s extensive object-oriented programming features, to make it easy to build a complete Web application very quickly. As with Python, Ruby is fast becoming a popular choice among Web developers, but for now, PHP is much more popular.” - p.6

and then elaborating on why PHP might be popular today:

“[T]his middle ground partly explains the popularity of PHP. The fact that you don’t need to learn a framework or import tons of libraries to do basic Web tasks makes the language easy to learn and use. On the other hand, if you need the extra functionality of libraries and frameworks, they’re there for you.” - p.7

Fair enough. However, to really understand the language, I needed to dive in personally and experience it firsthand. I took notes during the dive about some of the things that stuck out.

The Good Parts

  • It’s relatively easy to learn and get started with PHP. As a C# developer, I was able to pick up PHP in a few hours after a brief overview of the syntax from a book. Also, PHP has some decent online help.
  • PHP is available on almost all web hosts these days at no extra charge (in contrast with ASP.NET hosting). I can’t emphasize this enough because it’s a reason why I would still consider writing a small website in it.
  • I was pleasantly surprised to have unit test support with PHPUnit. This made me feel at home and made it easier to develop and debug code.
  • It’s very easy and reasonable to create a website in PHP using techniques like Model-View-Controller (MVC) designs that separate the view from the actual database model. The language doesn’t seem to pose any hindrance to this.
  • PHP has a “static” keyword that is sort of like a static version of a “this” reference. This was useful in creating a quasi-static “subclass” of my “Range” class for validating player and team sizes. This feature is formally known as late static binding.

The “When in Rome...” Parts

  • Class names use PascalCase while functions tend to use lowerCamelCase like Java whereas C# tends to use PascalCase for both. In addition, .NET in general seems to have more universally accepted naming conventions than PHP has.
  • PHP variables have a ‘$’ prefix which makes variables stick out:

    function increment($someNumber)
    {
    $result = $someNumber + 1;
    return $result;
    }
    This convention was probably copied from Perl’s scalar variable sigil. This makes sense because PHP was originally a set of Perl scripts intended to be a simpler Perl.
  • You access class members and functions using an arrow operator (“->”) like C++ instead of the C#/Java dot notation (“.”). That is, in PHP you say “$someClass->someMethod()” instead of “someClass.someMethod()
  • The arguments in a “foreach” statement are reversed from what C# uses. In PHP, you write:

    foreach($allItems as $currentItem) { ... }
    instead of the C# way:

    foreach(currentItem in allItems) { ... }
    One advantage to the PHP way is its special syntax that makes iterating through key/value pairs in an map easier:

    foreach($someArray as $key => $value) { ... }
    vs. the C# way of something like this:

    foreach(var pair in someDictionary)
    {
    // use pair.Key and pair.Value
    }
  • The “=>” operator in PHP denotes a map entry as in

    $numbers = array(1 => ‘one’, 2 => ‘two’, ...)
    In C#, the arrow “=>” is instead used for a lightweight lambda expression syntax:

    x => x * x
    To define the rough equivalent of the PHP array, you’d have to write this in C#

    var numbers = new Dictionary<int, string>{ {1, "one" }, {2, "two"} };
    On the one hand, the PHP notations for maps is cleaner, but it comes at a cost of having no lightweight lambda syntax (more on that later).
  • PHP has some “magical methods” such as “__construct” and “__toString” for the equivalent of C#’s constructor and ToString functionality. I like C#’s approach here, but I’m biased.

The “Ok, I guess” Parts

  • The free NetBeans IDE for PHP is pretty decent for writing PHP code. Using it in conjunction with PHP’s XDebug debugger functionality is a must. After my initial attempts at writing code with a basic notepad, I found NetBeans to be a very capable editor. My only real complaint with it is that I had some occasional cases where the editor would lock up and the debugger wouldn’t support things like watching variables. That said, it’s still good for being a free editor.
  • By default, PHP passes function arguments by value instead of by reference like C# does it. This probably caused the most difficulty with the port. Complicating things further is that PHP references are not like references in other languages. For example, using references usually incurs a performance penalty since extra work is required.
  • You can’t import types via namespaces alone like you can in C# (and Java for that matter). In PHP, you have to import each type manually:

    use Moserware\Skills\FactorGraphs\ScheduleLoop;
    use Moserware\Skills\FactorGraphs\ScheduleSequence;
    use Moserware\Skills\FactorGraphs\ScheduleStep;
    use Moserware\Skills\FactorGraphs\Variable;
    whereas in C# you can just say:

    using Moserware.Skills.FactorGraphs;
    PHP’s way makes things explicit and I can see that viewpoint, but it was a bit of a surprising requirement given how PHP usually required less syntax.
  • PHP lacks support for C#-like generics. On the one hand, I missed the generic type safety and performance benefits, but on the other hand it forced me to redesign some classes to not have an army of angle brackets (e.g. compare this class in C# to its PHP equivalent).
  • You have to manually call your parent class’s constructor in PHP if you want that feature:

    class BaseClass
    {
    function __construct() { ... }
    }

    class DerivedClass extends BaseClass
    {
    function __construct()
    {
    // this line is optional, but if you omit it, the BaseClass constructor will *not* be called
    parent::__construct();
    }
    }
    This gives you more flexibility, but it doesn’t enforce C#-like assumptions that your parent class’s constructor was called.
  • PHP doesn’t seem to have the concept of an implicit “$this” inside of a class. This forces you to always qualify class member variables with $this:

    class SomeClass
    {
    private $_someLocalVariable;
    function someMethod()
    {
    $someMethodVariable = $this->_someLocalVariable + 1;
    ...
    }
    }
    I put this in the “OK” category because some C# developers prefer to always be explicit on specifying “this” as well.
  • PHP allows you to specify the type of some (but not all kinds) of the arguments of a function:

    function myFunction(SomeClass $someClass, array $someArray, $someString) { ... }
    This is called “type hinting.” It seems that it is designed for enforcing API contracts instead of general IDE help as it actually causes a decrease in performance.
  • PHP doesn’t have the concept of LINQ, but it does support some similar functional-like concepts like array_map and array_reduce.
  • PHP has support for anonymous functions by using the “function($arg1, ...) {}” syntax. This is sort of reminiscent of how C# did the same thing in version 2.0 where you had to type out “delegate.” C# 3.0 simplified this with a lighter weight version (e.g. “x => x * x”). I’ve found that this seemingly tiny change “isn’t about doing the same thing faster, it allows me to work in a completely different manner” by employing functional concepts without thinking. It’s sort of a shame PHP didn’t elevate this concept with concise syntax. When C#’s lambda syntax was introduced in 3.0, it made me want to use them much more often. PHP’s lack of something similar is a strong discourager to the functional style and is a lesson that C++ guys have recently learned.
  • Item 4 of the PHP license states:
    Products derived from this software may not be called “PHP”, nor may “PHP” appear in their name, without prior written permission from group@php.net. You may indicate that your software works in conjunction with PHP by saying “Foo for PHP” instead of calling it “PHP Foo” or “phpfoo”
    This explains why you see carefully worded names like “HipHop for PHP” rather than something like “php2cpp.” This technically doesn’t stop you doesn’t stop you from having a project with the PHP name in it (e.g. PHPUnit) so long as the official PHP code is not included in it. However, it’s clear that the PHP group is trying to clean up its name from tarnished projects like PHP-Nuke. I understand their frustration, but this leads to an official preference for names like Zope and Smarty that seem to be less clear on what the project actually does. This position would be like Microsoft declaring that you couldn’t use the “#” suffix or the “Implementation Running On .Net (Iron)” prefix in your project name (but maybe that would lead to more creativity?).

The Frustrating Parts:

  • As someone who’s primarily worked with a statically typed language for the past 15 years, I prefer upfront compiler errors and warnings that C# offers and agree with Anders Hejlsberg’s philosophy:
    “I think one of the reasons that languages like Ruby for example (or Python) are becoming popular is really in many ways in spite of the fact that they are not typed... but because of the fact that they [have] very good metaprogramming support. I don’t see a lot of downsides to static typing other than the fact that it may not be practical to put in place, and it is harder to put in place and therefore takes longer for us to get there with static typing, but once you do have static typing. I mean, gosh, you know, like hey -- the compiler is going to report the errors before the space shuttle flies instead of whilst it’s flying, that’s a good thing!”
    But more dynamic languages like PHP have their supporters. For example, Douglas Crockford raves about JavaScript’s dynamic aspects:
    “I found over the years of working with JavaScript... I used to be of the religion that said ‘Yeah, absolutely brutally strong type systems. Figure it all out at compile time.’ I've now been converted to the other camp. I've found that the expressive power of JavaScript is so great. I've not found that I've lost anything in giving up the early protection [of statically compiled code]”
    I still haven’t seen where Crockford is coming from given my recent work with PHP. Personally, I think that given C# 4.0’s optional support of dynamic objects, the lines between the two worlds are grayer and that with C# you get the best of both worlds, but I’m probably biased here.
  • You don’t have to define variables in PHP. This reduces some coding “ceremony” to get to the essence of your code, but I think it removes a shock absorber/circuit-breaker that can be built into the language. This “feature” turned my typo into a bug and led to a runtime error. Fortunately, options like E_NOTICE can catch these, but it caught me off guard. Thankfully, NetBean’s auto-completion saved me from most of these types of errors.
  • PHP has built-in support for associative arrays, but you can’t use objects as keys or else you’ll get an “Illegal Offset Type” error. Because my C# API heavily relied on this ability and I didn’t want to redesign the structure, I created my own hashmap that supports object keys. This omission tended to reinforce the belief that PHP is not really object oriented. That said, I’m probably missing something and did it wrong.
  • PHP doesn’t support operator overloading. This made my GaussianDistribution and Matrix classes a little harder to work with by having to invent explicit names for the operators.
  • PHP lacks support for a C#-like property syntax. Having to write getters and setters made me feel like I was back programming in Java again.
  • My code ran slower in PHP. To be fair, most of the performance problem was in my horribly naive matrix implementation which could be improved with a better implementation. Regardless, it seems that larger sites deal with PHP’s performance problem by writing critical parts in compiled languages like C/C++ or by using caching layers such as memcached. One interesting observation is that the performance issue isn't really with the Zend Engine per-se but rather the semantics of the PHP language itself. Haiping Zhao on the HipHop for PHP team gave a good overview of the issue:
    “Around the time that we started the [HipHop for PHP] project, we absolutely looked into the Zend Engine. The first question you ask is 'The Zend Engine must be terribly implemented. That’s why it’s slow, right?' So we looked into the Zend Engine and tried different places, we looked at the hash functions to see if it’s sufficient and look some of the profiles the Zend Engine has and different parts of the Zend Engine. You finally realize that the Zend Engine is pretty compact. It just does what it promises. If you have that kind of semantics you just cannot avoid the dynamic function table, you cannot avoid the variable table, you just cannot avoid a lot of the things that they built... that’s the point that [you realize] PHP can also be called C++Script because the syntax is so similar then you ask yourself, 'What is the difference between the speed of these two different languages and those are the items that are... different like the dynamic symbol lookup (it’s not present in C++), the weak typing is not present in C++, everything else is pretty much the same. The Zend Engine is very close to C implementation. The layer is very very thin. I don’t think we can blame the Zend Engine for the slowness PHP has.”
    That said, I don’t think that performance alone would stop me from using PHP. It’s good enough for most things. Furthermore, I'm sure optimizers could use tricks like what the DLR and V8 use to squeak out more performance. However, I think that in practice, there is a case of diminishing returns where I/O (and not CPU time) typically become the limiting factor.

Parting Thoughts

Despite my brief encounter, I feel that I learned quite a bit and feel comfortable around PHP code now. I think my quick ramp-up highlights a core value of PHP: its simplicity. I did miss C#-like compiler warnings and type safety, but maybe that’s my own personal acquired taste. Although PHP does have some dubious features, it’s not nearly as bad as some people make it out to be. I think that its simplicity makes it a very respectable choice for the type of things it was originally designed to do like web templates. Although I still wouldn’t pick PHP as my first choice as a general purpose web programming language, I can now look at its features in a much more balanced way.

P.S. I’d love to hear suggestions on how to improve my implementation and learn where I did something wrong. Please feel free to use my PHP TrueSkill code and submit pull requests. As always, feel free to fork the code and port it to another language like Nate Parsons did with his JSkills Java port.

39 comments:

wakeless said...

I'm not sure if I've got you wrong re: PHP not having property functionality, but with a bit of setup in your parent class you can use an array to support your properties and then using __get and __set fallback to a getter or setter when you want special functionality.

This means you can do $obj->foo = "bbb";

and have code executed on the set or not as you please.

mhitza said...

The most objective article about PHP I have ever read.

Jeff Moser said...

Wakeless: Right. You can use the __get and __set magical methods (C# 4.0 offers something similar) but I didn't see a way in PHP to do lightweight properties like C# supports (e.g. "int SomeProperty { get; set; }") other than resorting to public fields.

mhitza: Thanks for the kind words!

IonuČ› G. Stan said...

Regarding your HashMap implementation, you missed SplObjectStorage.

Anonymous said...

Much of PHP's poor reputation is from badly written, old, open source projects, which had "PHP" in their names. Perhaps that's the reason why they discourage this practice in the license.

The main reason PHP is so accessible in terms of web hosting, is the commercial control panels, which most hosts use, support it by default. I would love it if the big control panel providers added options to enable and heavily configure Ruby/RoR and Python/Django.

Michael Kimsal said...

@wakeless

That's basically glorified error handling. By default, you can't *define* your attributes in code (as in "public $name") *and* also have that ability to have custom get/set functionality. Which do you want - flexibility or readable code?

pkeane said...

I'm constantly amazed that article sizing up PHP never seem to mention to mention the one single factor that makes it more popular and more widely deployed than any other language: its CGI-based execution model. ( http://blog.ianbicking.org/2008/01/12/what-php-deployment-gets-right/ ). Of course, as a result, it can be quite lacking as a general purpose programming langauges (poor garbagr collection. etc.).

Anonymous said...

Like another poster said: a great article and wonderfully objective. PHP was my first programming language - I'm now, solely, a Python web developer; PHP certainly wins in many cases for web development but I found myself writing library after library to overcome the warts and weaknesses in its design.

After having many bad habits and odd notions about what a language should do changed by learning Python, C, Scheme, and Erlang - I realized PHP is sub-par to the programming task. Not because it can't do it but because it forces the programmer into a sloppy paradigm (where you only survive by being uber-anal about things you never need to be in other languages).

kuroikaze85 said...

Whoa, Trueskill in PHP. I've attempted this code some time before (ported algorithm from F#), but not succeeded. I've deleted my code from Github since then. Glad you've managed it.

brad said...

coming at php from the direction of c# only exposes a few of its glaring inadequacies. from the direction of more capable dynamic languages...php is also completely deficient. any perl or python or even javascript developer who exploits the interesting elements of those languages will find php lacking.

php's overriding design goal seems to be to remove anything interesting from the language. it's like the golden arches - cheap, accessible garbage.

what is often overlooked is how deficient php's community is. look at pear...how can the php community be so much larger than the perl community yet be so incapable of producing even an equal number of free modules? it can't be because the php community is busy closing many of the well-aged egregious bugs against the ghastly runtime itself.

MANCHUCK said...

@jeff Great article really enjoyed it. When you talked about performance, are you running some kind of optimizer in prod? Something like Zend Optimizer will greatly improve performance since it will cache all the opcode that PHP generates.
Even though its a loose language, when you declare a variable, PHP creates a C struct which contains all the possible values of the variable. So when declaring a variable, its best that you cast the variable to the type you want:

$var = (int) 5;

That way PHP wont allocate the memory needed to have var as a string.

Wade Tandy said...

@Michael Kimsai & Jeff Moser
It's still very easy to have private, defined attributes in your classes. You can create a private associative array to define your properties and their defaults. Then in your __get and __set methods, you can can call array_key_exists against your data array. I've included a code sample here

Jeroen Bolle said...

method overloading is possible using func_num_args() and func_get_args()

though it still requires some extra work.

Jeff Moser said...

IonuČ› G. Stan: I totally missed that when I was looking for something like it. Thanks!

Anonymous #1: I agree, but would also like ASP.NET MVC :)

Michael Kimsal: Thanks!

pkeane: Interesting thoughts. As you mentioned, a lot of the advantages you mentioned can also be tackled by worker processes. This is what IIS uses with ASP.NET the advantage there is that you can configure what type of model you want (e.g. per process) as well as how often to "recycle" the process.

Anonymous #2: Thanks for stopping by. I agree that good programmers can make most languages decent by avoiding the bad stuff -- hopefully the language doesn't have too many bad parts.

kuroikaze85: I didn't see any other factor graph implementations of TrueSkill in PHP, so I hope it might help the community out in some small way.

brad: I got the feeling that PHP was a hobby project that just kept getting bigger rather than anything with a master plan. I don't think the designers intentionally remove good things, but it does seem to lack some polish.

MANCHUCK: Thanks for the nice remarks! I hadn't run any optimizer on it. As I mentioned, my code's main problem is the algorithmic complexity of my naive matrix code. Fixing that would probably lead to a better improvement than a general optimizer. Thanks for the casting tip. It seems that a smart interpreter could do similar things (e.g. if you initialize with an int, it'll probably remain an int). This hints at what the HipHop presenter mentioned as well.

Wade Tandy: Interesting solution. It would still be nice if it were part of the language, but your approach seems reasonable as an alternative.

Jeroen Bolle: Yeah, it's possible as you mentioned, but not quite elegant.

Davey Shafik said...

A note about arguments passing by reference or by-value.

In userland PHP, as far as a developer is concerned, default behavior is for objects to pass by reference, and scalars/arrays to pass by-value.

In reality, scalars/arrays are passed through using copy-on-write. That is, a reference is passed through, that is only copied when the variable is modified — therefore, unless you are modifying the variable, there is no performance hit; and any modification is likely going to be more of a performance hit than the copy anyhow.

Now, not that I'm disputing anything you're saying, but all in all, I think some more time with PHP would help your usage of the language and negate some of the issues you are having. That said your observations as a newcomer are the same as others will have, and will ring true for many until they learn better — this is the same with anything.

- Davey

Anonymous said...

Emmmm....
Zope is python/plone based framework.

odino said...

Hi Jeff, it's doable to use objects as array, in PHP, you should implement the ArrayAccess interface.

http://php.net/manual/kr/class.arrayaccess.php

Great article, BTW.

Steve said...

Great article, thanks! I think you need to clarify this statement though:

"By default, PHP passes function arguments by value instead of by reference like C# does it. "

Actually, that it not true, .Net passes params by value (unless you override that by using out or ref modifiers). Of course, if you pass a reference type by value you are passing a reference, but that's still not the same as pass by reference.

roysimkes said...

Just more implementation example for custome get and set methods.

class Foo{
private $bar;
public function __get($var) {
return $this->$var;
}
public function __set($var, $value) {
$this->$var = $value;
}
}

The above implementation uses variable variable "power" of the PHP. It takes the value of the $var (in this case "bar"), and use it to execute to the code like. Then the code in the __get() becomes "return $this->bar;"

If we increase the complexity a little bit to something like this:

class Foo{
private $bar;
public function __get($var) {
$methodName = "get" . ucfirst($var);
if (method_exitst($this, $methodName)) {
return $this->$methodName();
}
return $this->$var;
}
public function __set($var, $value) {
$methodName = "set" . ucfirst($var);
if (method_exists($this, $methodName)) {
$this->$methodName($value);
}
$this->$var = $value;
}
}

So this way you can override the call of __get and __set methods by writing methods like getBar() or setBar($b)

Jeff Moser said...

Davey Shafik: Thanks for the comment. I understand the copy-on-write optimization, but I was speaking of cases where if I didn't have the &'s around variables then I would get different results. Specifically, this came up when I wanted to return an array from a class that I could add items to.

Anonymous #3 You're right. I was referring to this from the License Information page where they say "So, please, pick a name that stands on its own merits. If your stuff is good, it will not take long to establish a reputation for yourselves. Look at Zope, for example, that is a framework for Python that doesn't have Python in the name. Smarty as well doesn't have PHP in the name and does quite well."

odino: Interesting. I didn't know about that. Still, it would have been nice to have it by default without the need for extra work, but this is good to know.

Steve: Fair point. I wasn't referring to "ref" style parameters, but passing references/pointer-like things around for objects, especially lists/arrays. You're right though, I could have been clearer there.

roysimkes: Interesting use of that feature - sort of like pointers to pointers but with names.

Jonathan Bond-Caron said...

Great article.

It's refreshing to see a c# developer not bashing but pointing out the good & the bad of php.

Very professional attitude, welcome to php.

Wayne said...

Jeff, PHP works pretty similarly to C# when it comes to references. Scalars and arrays are value types (passed by value) and everything else is passed by reference.

I think explicit references are rarely needed in production PHP code. It sounded like you wanted to be able to pass arrays around by reference, in that case, you may have been better off with the ArrayObject class. That would be closer to a C# style of array.

As for getters and setters, there is a trick you can do for those. If you create a common base class for all your classes (I call mine Object) you can declare __get/__set magic methods that will automatically turn undeclared property references ($this->someProperty) into method calls ($this->getSomeProperty(), $this->setSomeProperty()) automatically. I do this in my code base so I can have easy getters and setters. In my subclasses, I just have to prefix my method name with get or set and it becomes a property. There is some overhead this way, but it's not significant and it's very convenient. If there is some interest, I can post the code here.

wazz said...

excellent work. thanks.

Anonymous said...

Well, there is two things you can do to make it easier to import things. One would be to "semi emulate" namespace, by creating a PHP file with a proper name, that just contains the includes for that "namespace" and nothing else.

Another, much better way is Autoloading: http://php.net/manual/en/language.oop5.autoload.php

A quick dirty example would be, name your class like "mynamespace_foo" and place it in a folder like "mynamespace/foo.php"

and then write (yes, this is a ugly way, but just to illustrate the conecpt quick) to define a __autload like:

function __autoload($classname)
{
$classname = str_replace("_", "/", $classname);
require_once($classname . ".php");
}

and just include that...
(yes, this particular example has some performance loss, due to str_replace but I think you will get the rough idea).

And now whenever saying something like "$myclass = new mynamespace_foo();" it will load it for you, also a way to make sure that things only get loaded when needed etc.

Anonymous said...

Oh, and also take a look at SPL -> http://www.php.net/manual/en/book.spl.php

Jeff Moser said...

Jonathan Bond-Caron/wazz: Thanks. I hope this post helps reduce some of the language bashing and helps keeps things objective.

Wayne: I didn't know about ArrayObject. Thanks for the info. Your approach for properties sounds similar to roysimkes's. You're welcome to post it here or as a GitHub Gist.

Anonymous #4: Interesting workaround idea on the namespace idea. I hadn't heard of autoloading. Thanks for pointing that out!

Sanjib Sinha said...

A very readable, interesting article. I am curious about the comparison of these two great languages that rule the web world now, and found your article feeded my apetite.
In this context I'd like to know if there is any software like Visual Studio in PHP, that could make things easier for the developers?
Best of luck.

schkovich said...

@Sanjib: Jeff mentioned Netbeans IDE several times in his post. Davey Shafik article Netbeans for PHP: Continues to impress brings some interesting opinion on IDEs available for PHP developers. The Big PHP IDE Test: Why Use One And Which To Choose nicely compares almost all available IDEs.

Jeff Moser said...

Sanjib Sinha As I mentioned in the post, NetBeans IDE for PHP is what I used. It was reasonable. Also, check out the Stack Overflow question I linked to: Any good PHP IDE, preferably free or cheap?. It's where I first learned about NetBeans.

Note on other comments: There are a few places that also have comments on this post: Hacker News, the Programming Subreddit, and the PHP Subreddit

Jazzie Casas said...

Java and to some degree .Net are the main choices because they have been consistently pegged as the “safe” choice to go with for mid-level project managers in the corporate world. No one was ever fired for choosing Java or Microsoft.

However, there are many large distributed applications these days that run primarily with technologies like Python, PHP, et al. Even companies like Google and Yahoo are heavily invested in these technologies. Java may be the main choice for enterprise development now, but it’s days are numbered as the only stalwart option to go with.

Let’s face it, many of these so called “enterprise applications” could easily have been written much faster and with less overhead using technologies like Python, PHP, et al.

AlaskanShade said...

I looked into PHP a couple years ago for a small web application we were going to be building. The goal was to keep things as cheap as possible for the client. The deciding factors ended up being hosting cost and time to build. Once we discovered that GoDadddy (their current host) does not cost any more for Windows hosting, we focused on time. Our biggest problem with PHP was that there doesn't seem to be a lot of well developed controls to build good user interfaces as opposed to a huge variety of libraries and code examples for .Net. To me, PHP always feels like building with legos and only having 1 by 1 blocks as opposed to having Technics parts. Just my two cents worth.

jon said...

"I understand the copy-on-write optimization, but I was speaking of cases where if I didn't have the &'s around variables then I would get different results. Specifically, this came up when I wanted to return an array from a class that I could add items to."

It's actually the same thing. Copy-on-write is used for any kind of value copy, be it passing parameters by value, returning by value, or even just using the assignment operator. (When you return a large array, there's no performance hit until you write to it. At that point its copied and, as you discovered, you're not altering the array that the object returned.)

I think you could get around this by using ArrayObject, which would be returned by reference.

By letting the client change something you've returned by reference, though, isn't that just kind of a public variable? Wouldn't it be better design to let the client code change the array via some method?

Jeff Moser said...

Jazzie Casas: Sometimes I wonder how much this relates to "Worse is better" philosophy.

AlaskanShade: Thanks for sharing your experiences.

jon: Yeah, I probably should have used ArrayObject. A lot of the cases were for protected mode accessors (e.g. a derived factor graph factor) where I was less worried about exposing it publically.

The Foolish said...

You know, I think there's a lot that you're missing here with Php, but like you said... it's your first shot at it. It's not your fault, php can be a very complicated language with a lot of subtly to it.

C# is the same way. Other than the "php is not really object oriented" comment, I found the article insightful.

Only thing I wanted to chime in is that you can absolutely use objects inside of an associative array in php, provided that the pieces of the objects you're using output something. Another thing you could do is dynamically set variables inside of objects, even if you don't know what they are. I've always had trouble doing crazy things like that in .net, but I will concede that I'm not a .net expert (yet).

I hear about php's performance issues a lot from windows developers. My sincere thought on this is that the only time php doesn't keep up with .net is when you're using the standard slow CGI that comes stock with IIS 6 with default settings, and not using 5.3 features like Phars to reduce file i/o. Of course in that scenario, you're not running php under .net or FastCGI like you should be on a windows machine.

Lamp is a different world.

I will say it's a totally different mindset. Every language has it's own thought process, and often times the languages that you know often color the experience you have with the ones you learn.

I honestly don't mean to be insulting by any of this. It is my sincere hope you don't take it that way.

But the thing I really enjoyed about this article was how much I learned about C#.

Good stuff.
Thank you for taking the time to share your thoughts and experiences.

Jeff Moser said...

The Foolish:

Regarding your object oriented comment: do you think that PHP was originally designed to be object oriented? If not, do you think it's fair to say that you can program in PHP without orienting yourself towards objects? See more discussion on this very topic over at Hacker News.

For most websites, you're right in that I don't think the performance is going to get in the way of real work.

I think that the language affecting thinking is a big idea.

Thank you for sharing your feedback!

Galvin Alvarado said...

The primary reason PHP is so available with regards to web web host and it is the professional control sections which most serves use support it by standard.

Kelly Strong said...

The platform has often been the most preferred development language and gives a compact structure in generating apps and diverse types of websites.

Don said...

A big part of why your matrix code was slow is that PHP does not actually have arrays. It has something that looks syntactically like an array but is, in fact, a hash with a linked-list backing the key set. If you use foreach to iterate on an array whose members were not set in numerical order, you'll see the problem. There's a huge performance penalty for this with anything that deals with array data.

php development said...

waoooooooooooo very nice post