Looking for the perfect PHP IDE

I’ve got a problem. I haven’t found the perfect IDE for me. Yet. I’ve got problems with every software. Now I will try to explain the problems I have and maybe someone shows me the light and helps me to discover the perfect editor/IDE.

First important thing. I’m a Linux user so Windows only softwares are out. I know Mac user really love Textmate but buying a mac is not in my scope. They are good hardware, reliable and of course cool. I know nowadays there are a lot of web developers working with mac but I’m not convinced yet to change my computer from PC with linux to mac. Probably I will make myself the question when the core breaks down. Don’t ask me why but my last three PCs broke down with a fail the core (after years of usage). So the baseline is clear. Software must work with linux and it must work in a native way. Not with wine or things like that.

My requirement list is the following ones:

  • Code auto-completion.
  • Syntax highlight.
  • Debugger.

Easy, isn’t it? But even with those simple requirements I haven’t found yet my perfect IDE. So I’m going to enumerate the problems I’ve got with each one.

Zend Studio 7

It’s not free. That’s not the main problem. But we can find another similar for free. Debugger works fine. Code auto-completion really good. Syntax highlight perfect. Auto indentation and one of my favourite feature code analysis. Really useful. It detects problems such as:

[sourcecode language=”php”]
$var = 0;
if ($Var == 0) { // $Var and $var are different variables. It’s probably a type error very difficult to detect in a glance

}
[/sourcecode]

It’s look like the perfect IDE but it’s maddeningly slow. If you are working with a few files is perfect but is your project is big (hundred of files) sometimes you are forced to make too many coffee breaks when it becomes crazy (building workspace…). Maybe if you’ve got a super pc with infinite RAM and hundred cores it works fine but, at least for me it’s irritating.

Eclise PDT

Zend Studio 7 is based on eclipse. PDT it’s almost the same than Zend Studio 7 (without its great integration with the zend services that I don’t use). Exactly the same problems (very slow) but even without some extra features, such as code analysis (really useful for me). By other hand it’s free (as free beer)

Netbeans

Similar features than Eclipse PDT and lighter. Also free. The problem here it’s the debugger. Only works with xdebug. Not a real problem for me. I don’t really mind what debugger to use. Zend debugger and xdebug meets my requirements. But it’s a bit strange how to debug. I don’t like it. In early versions it created the url when you started to debug. And that url cannot be changed properly. That’s means it doesn’t worked for me. Now it’s better but still not good. It looks like the PHP plugin of Netbeans isn’t as good as Java one’s. The future of Netbeans isn’t clear with the acquisition of Oracle. They said Netbeans isn’t an strategical project (that’s means they cut some funds)

VIM

It looks like the perfect editor but It’s hard to learn, at least in the beginning. Syntax highlight perfect. Really light. Works perfect everywhere even on remote hosts via ssh. Code auto-completion works but not as good as in eclipse and Netbeans (but it’s fair enough). I said is not as good as Eclipse and Netbeans because for example it doesn’t hint me with the variables of the function or ignores PHPDoc in the auto-completion pop up, and I really appreciate it. The main problem I have is with the debugger. It’s so strange for me. I thing I need a couple of hours working on it because nowadays debugging with VIM is something like a miracle a miracle for me. Sometimes work but I it’s too many endeavor. Yet. I hope so. If you want more about about PHP and VIM, you must take a look to this link.

Emacs

I must admit that I am too lazy to learn to use it. I invested time with VIM. I feel that I need more and I don’t want to start with another one like emacs from zero. Maybe I’m wrong and that’s the perfect IDE but it’s not in my mind now.

Zend Studio 5.5

That “was” the perfect IDE. It was not for free but it was really good. Fast. Even with big projects (sometimes become crazy and crashed, I known). Debugging was perfect. Only with Zend debugger but really easy to use. You don’t need a great pc. 2G RAM was fair enough. But there’s a problem. This software is obsolete. Zend changed to an Eclipse based one. We can still using it but there isn’t any update. The main problem with it is we cannot use any new PHP5.3 features, such as namespaces. OK we can use them if our server has PHP5.3 but IDE mark those new keywords as syntax errors. So If we work with this software and a PHP5.3 project we need to assume that the red warnings of our editor (syntax errors) are not always errors. It’d be a great new for me if Zend people releases Zend Studio 5.5 as open source a someone continues the project adding PHP 5.3 support.

As you can see I’m not 100% happy with any IDE. Do you have a perfect IDE? I’d really like to be wrong in my assumptions. So I’ll keep looking for.

My development tips

Another unsorted list of ideas this time about coding tips.

code = mass

The source code isn’t an abstract element. OK it’s not as touchable as apples or bricks but it’s somehow under physical laws too. You must write as less code as you can to meet your requirements. Big code means big mass and if you have a big mass you will need more energy to change whatever you need. I can stop a car toy with my hand but I need something more to stop a real train with the same speed. Less code means less failure points and it’s easier to manage. Some people claim proudly they have written a library with thousands of code lines. Nobody pay us for writing lines of code. They pay us for the solutions. The lines of code that we write is our problem. So be as minimalistic as you can. The problem is that writing less code is more complicated than write more. We need to think more to write less code.

DRY (Don’t repeat yourself)

Original, isn’t it?.  Copy & paste is evil. Never use it in your projects. Spread the same code among different files means that you will need to remember where are those pieces of code when a bug appear (they appear, believe me). There’re a lot of techniques to avoid copy & paste source code. Use them. There isn’t any excuse to it.

Coding standards

The source code is one of your deliverables as developer. You must care about it. Adopt a coding standard. Chose one and use it. If you work with a team take this decision with your team, but don’t try to create one standard by your own. It’s a big job. If you use one of the existing coding standards (let’s say Zend Framework’s one) you will find tools to validate your code against it and the most common IDEs and text editors will be able to use it too. In other way if you create a new one you will need to develop those plug-ins and tools and even you will need to document it if you want to show it to another developer. To many work that nobody will pay for it only because you dismiss an existing one.

Revision control.

Mandatory. Even for small and personal projects. I like Mercurial. it’s easy to use and easy to install. Anyway there are others similar like git or bazzar. Or if you are old school, CVS and Subversion. When I start a project, after create an empty folder with the name of the project I always execute “hg init” to create my repository. Commit you code often. Every time you make something important commit your work. Don’t wait until your project is finished. Revision control is a great backup system too. When something wrong happens like accidentally delete of a folder or something similar you can recover it easily without any problem. Also with a simple hg push (or similar command with another software different from mercurial) you will save your project into another place. If you don’t know to use any revision control system aside time for it. Believe me. You will not need too many time to learn how to use it. At least a basic usage.

Text editor

Is your main tool as a developer. It’s like the hammer for a carpenter. You must train yourself in the use of it. A good skill in the use of a text editor or IDE will give great benefits. If you think in term of ROI, the investment you use in your IDE will return sooner or later. Some of them are not trivial. For example Eclipse needs time to learn how to configure it. You must skill yourself into the IDE if you don’t want to lose your time developing (remember time = money). I’ve seen people programming PHP with notepad. You need at least syntax highlight, syntax error detection, auto-completion, auto-completion with code introspection and debugging. Don’t waste your time.

Digressing about working with old code, refactoring and scope creep.

Maybe there’re people who write code without bugs and never need to change one line of their source code. That’s not me. I try to improve my coding skill for the years. That means sometimes I need to face against my old code and if need to rewrite it probably I will do in a different way. I always feel the desire to refactor it. Refactor code is a good thing but is not always viable.Let’s show an example. Nowadays I’ve embraced Zend coding standard. For instance one not camelized variable creeps me out. But in my early days as a PHP developer (almost ten years ago) I didn’t take care about any coding standards. If code worked, it was OK. Now I realized that’s not enough. Code must work. Indeed!. But it must be ready to be changed, adapted to new needs and meet new requirements, and another developer must be able to understand it. Last days before holidays I’ve been working adapting a project to PHP5.3. It’s not a hard job. Some functions have disappeared, now we only have one kind of regular expressions and a couple of things more. I need to check a lot of lines of code. Sometimes I blush myself when I see the code I wrote five or even eight years ago. I want to change a lot of things. Refactor again and again but I must remember that’s not in the scope of the project. The objective of the project is clear: The application must work in a server with PHP5.3. If I start to refactor code the project deviates from project’s main scope. That’s a clear scope creep’s signal.

According with theory the main signals of scope creep are:

  • More work has been done than required
  • Product features don’t match the specifications.

Scope creep one of the most important problems in real projects. It’s very difficult to explain to someone that you will delay your project because you have decided to refactor some pieces of code (code that worked). That’s means your project will be delayed because you’ve decided to improve something that nobody ask for it. If you are on schedule maybe you can assume some refactor but think this kind of work is only viable if the triple constraint model (aka Scope + Budget + Schedule) keep unaltered. You must assess if those unsolicited changes have any impact in the project. Projects must end at some point. At some point you will need to submit the project’s deliverables, put your feet up and relax. But the temptation is big. I know.

First impressions about namespaces in PHP

I’ve been working wih my first project using namenspaces in PHP. As a PHP developer I have been suffering the lack of a program language without namespaces for years. But now it’s over. Finally we have namespaces in PHP since PHP 5.3. My early impressions wasn’t good. I had a problem. I really liked PEAR naming conventions. I know that leads to those ugly long class names, but I felt very comfortable with them. I even started to write a post in my blog called “Things I don’t like in PHP. Namespaces”. But I decided not to publish it since have been working a bit seriously with them. Now I have use them and my impressions have been changed. I’ve embraced them and they are not so bad. They have the same advantages than PEAR naming conventions and they give us some extra benefits further. Here we have a great article about namenspaces in PHP5.3

The only doubt I have is: Are they really better than classical naming conventions?
I make myself the question because as well as in classical naming convention the Classes are fully defined, with namespaces we must take care about aliases, ‘use’ statements and the scope. When I say ‘fully defined’ it means that in a glance to the class name we known exactly the location of the class in the filesystem.. We pay a tax for it. Our class name become bigger. Namespaces come to help us but they add to our code a bit of complexity. I feel really comfortable with classical naming conventions but namespaces are cool. Are they some kind of hype? I don’t think so but I am not 100% convinced. Yet. What do you think?

Flushing files with PHP

Sometimes we need to show files as pdf from PHP. That’s pretty straightforward.

[sourcecode language=”php”]
$buffer = null;
$f = fopen($filePath, "rb");
if ($f ) {
$buffer.= fread($f, filesize($filePath));
}
fclose ($f);
[/sourcecode]

And now we flush the buffer with the right headers.

[sourcecode language=”php”]
$filename = basename($filePath);
$type = ‘attachement’; // can be ‘innline’

// get mime type. finfo must be installed. PHP >= 5.3.0, PECL fileinfo >= 0.1.0
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);

header("Expires: Wed, 20 Sep 1977 16:10:00 GMT");
header("Cache-Control: no-cache");
header(‘Cache-Control: maxage=3600’);
header(‘Pragma: public’);
//header("Content-Length: " .filesize($path) );
header("Content-Disposition: {$type}; filename={$filename}");
header("Content-Transfer-Encoding: binary");
header("Content-type: ".mimeType”);

echo $buffer;
[/sourcecode]

Apparently the order of the headers is irrelevant but if you need to work with IE (poor guy), use those headers exactly in this order. I don’t know exactly the reason but this combination always works for me and if I overlook it and I change the order it’s likely to have problems with IE.

Another trick is the commented line.

[sourcecode language=”php”]
//header("Content-Length: " .filesize($path) );
[/sourcecode]

According to standards it must be set the length of the file with the Content-Length header, but I noticed that if I don’t set this header, the browser opens associated application (Acrobat reader e.g with pdf files) earlier than if I set it. This behaviour is visible with big files. With the Content-Length header the browser opens associated application to the file when the file if fully downloaded and without this header the browser don’t wait to finish the download of the file to open it. That’s means better user experience.

Clustering PHP applications. Tips and hints

Sometimes a web server and a database is fair enough to meet our project requirements. But if the project scales we probably need to think in a clustered solution. This post is an attempt at being an unsorted list of ideas working with clustered PHP applications. Maybe more than a list of ideas is a list of problems that you will face when swapping from a standalone server to a clustered server.

Source code

If you’re going to spread your code among different servers, one important fact is the source code must be always the same. You cannot assume differences in the source code. If you need to mark something related to the node, use environ variables and point your code to those environ variables instead of using different source code in each node. Perhaps changing the code is the fastest way to do the things initially but you will mess up your deploy system or at least turn it into a nightmare.

Databases

Here you are the biggest problem. Clustering databases is a hard job. All Databases normally have one kind or another of replica system but replication as way to solve problems can backfire on you. The easiest way of database replication is a master slave replica system. Inserts in one node and selects in all. This scenario can be easy to implement and not very hard to maintain but maybe you need a multi-master replica system (inserts in all) and this can turn your database administration into a nightmare. One solution is use noSql databases. They have a simple and useful multi-master replica system. My recommendation is use a noSql database for those kind of information we need to have distributed in all nodes. I know it isn’t always straightforward but all the work done in this direction will be will be worthwhile in our outcomes. In fact noSQL’ main purpose is data scalability but also there are people who thinks noSql databases are some kind of hype actually. Who is right?

File-systems

Problems again. Imagine you need to write a simple log system in your application. fopen, fwrite, a few PHP lines and your log is ready. But: Where is it located?. Probably on your local filesystem. If you want to place your application on a distributed cluster, you cannot use those simple functions. You must consider using a distributed filesystem. Maybe a simple rsync would work. Maybe a single fileserver mounted on every node of your cluster. You need to balance between them and choose the solution that fits to your requirements. One smart and simple solution is benefit from CouchDB’s attachments in addition to its replication system. (can you feel I like CouchDb?)

Deploy

That’s a mandatory point. You must have an effective deploy system. You can’t rely on you to deploy the code on the among the cluster by hand. This work must be automated. PHING, rsync, pull/push actions in a distributed revision control (e.g. mercurial) or maybe a simple bash script can be enough. But never do it by hand.

Authentication and Authorization

If your application is protected with any authentication mechanism you must ensure all nodes will be able to authenticate against the same database. A good pattern is to work with an external authentication mechanism such as OAuth in a separate server. But if it’s not possible for you must consider where is located user/password database. CouchDB is good solution.

After your user is authenticated you need no check the authorization. OAuth servers can help you on authentication but your application must deal with authorization (aka user roles and role groups) anyway. My best choice here is CouchDb but you can use relational databases too. As I said in Databases section I avoid multi-master Database Replication with relational databases like the plage, but if you need to use relational replication in the authorization database you can use master-slave replica and update all role and authorizations in the master database.

Sessions, Logs and Cache files

Witch session handler do you use in your application?

File based (go to filesystem section of this post),  Database (go to database section of this post).

The same with cache and logs. With cache files you can consider keep it locally. If your cache system works unattended you can maintain the cache in local node instead to replicate it among the cluster. You can save bandwidth.

Vuvuzela in PHP

South Africa’s World Cup is here. Someone will win. We will remember goals, players, mistakes but definitely we will remember the sound of this world cup. The annoying vuvuzela. There’re filters to avoid this sound in the matches. And here is my personal contribution to the word cup. A vuvuzela in PHP. A standalone single php script with a mp3 Embedded inside. Put it in your server and enjoy with the sound.

My website is slow. What can I do?

You are working with a website. The website works. All is perfect but your clients told you it’s very slow. You must face the problem and improve the behaviour of the web site. But remember all site works properly. There isn’t any errors. The common way to resolve problems (understand the problem, reproduce the problem in test environment, solve the problem) doesn’t fit in this scenario. What can we do? I want to give some recommendations to improve performance problems in this post. Let’s go

Don’t assume anything

It’s very typical in our work to assume what is the problem when someone gives us an issue. Normally the user is not a technician. He suffer a problem and tell us the symptoms. For example some people from procurement office call you telling the application doesn’t work. You assume he is speaking about the application he use every day doesn’t work. You can go to check the server. It’s OK. Server logs OK. What happens? Finally you discover there is a network problem. Not a problem in the application. but the effects to the users are the same.
When you face a performance issue don’t assume anything. First of all you must debrief the user to take a picture of the problem. Forget the solution just now. In this phase you only need to collect the information and perform an analysis later. If it possible speak and go to his office and see the problem with him. I remember a performance problem some time ago. The user had serious problems with the application. I tested the application and I didn’t find anything wrong. But the problem persists and she was the main user of the application. I went to her office and I discover the real problem. The application was slow. But the screen-saver was slow too. Spreadsheet was slow. In fact all was slow there. The problem was the RAM memory of the PC. More RAM and magically all applications become faster.

Measure the problem

If something is slow you must check times. But take care about it. Wrong measures can make you waste your time trying to solve the problem. A typical mistake is check times only at server-side. For example you start a timer when the script start and finish it when it ends. Imagine you have 1 second. It can be improved but, is the end-user complaining for a performance issue with 1 second of response time? Probably not. You can start to improve your server-side code. You spend some time coding and you turn from 1 second to 0.1 second. You are very proud of your improvements, and you tell to the user the problem is solved. But the user is not agree with you. The problem persists. You’ve been working on a different problem. A problem indeed but different one than user claims. Why? Because you’ve assumed the problem was in server code and your time measurements have been done in a wrong scenario.It’s quite probably the problem in in client site. If you take a look into firebug’s net tab you can realize server-side part (e.g. php ones) normally is the first one but is not the only one. Even it’s not the longest part. It can be a short percent of full-page load and render time. If you want to acheive significant success within your performance problem you must attack directly to the main bottle neck (and detect them before of course). If you want to learn a lot about client side performance, please pick up Steve Soulders’s “High performance web sites” book. You can also read the another Steve’s book “Even faster web sites” but first one is definitely a must read book for people who work in this area. You can also see many conferences of great Steve Soulders in youtuve. Do it. He is a great guru in this area and also a good speaker. After watching his conferences you will have  the desire to drink a beer with him. Probably working on “High performance web sites”’s recommendations you will achieve a significant results, following a really simple rules.

Cache it

I know I not very original giving recommendations about caching in this post but caching is very important. There is a lot theory about caching. You must cache all as you can. But don’t do it like mad. You will get a cache nightmare if you don’ have a good caching plan. You must define the storage, the ttl (time to live) and what is going to be cached and what not.  A wrong caching politics can jeopardize a project but a good caching ones will improve the performance.

Do it offline

Doing all online is cool. The user will get the fresh results when he clicks a button but what happen if the action takes too many time?. Imagine you have a button that sends ten emails every time the user clicks on it. In normal situations the operation is fast enough but what happens if mail server has a big load, or even it’s down. Your application will freeze and your user will become angry. Think moving operations to background. There are great tools like gearman to perform those kind of work. Transform your button from: user clicks, mail one is sent, mail 2, … mail 10 is sent, OK  to: use clicks, new task in our job server, OK. Now true doesn’t mean the ten emails have been sent. Now means they will be send. Balance the possibility of this new behaviour. I realize sometimes it isn’t possible but it is viable in other cases.Imagine you have an important report that uses a complex SQL to extract information from database. This SQL uses several tables to met user expectations. Is it mandatory to perform always the query to get the results? Think in the possibility of creating some statistic tables to collect old information (non changed ones, such as old months or years). Take a snapshot offline of your real-time data and perform queries over those snapshots instead of real information. Sometimes this technique is not possible but if it is available you can achieve important time benefits within your database queries.

Database Connections.

Working with relational databases the creation of database connection is a slow operation. Take care about it. It’s a good practise to put a counter in your script to show you how many connections you create in your script, how many queries and how many results gives your queries to your application. You can realize unpleasant problems with this simple log. If your application perform more than one connection to the same database within the same execution script it’s very sure you are doing something wrong. Use always lazy connections to the database. I also have seen scripts that connects to the database without doing any operation. That’s means you are wasting time connection to the database. Connect only when you really are going to use it. Not always in the beginning of the script as general rule.Check the sql you are using. If for example you are always doing the same query every click on the site to check some kind user information a red light must appear in your mind with a flashing box with the text: cache it! inside.

Trace long query and analyze them into the database. Check indexes and execution plans. This normally is a great bottle neck in the web applications.

Debug flags

Use debug flags to measure the problem. Firebug in combination with FirePHP are a great team to help us in our work. But don’t forget to turn those flag off in the production server. To many debug information collectors active in our production servers will slow down or application with unnecessary actions

Detecting errors and bottle necks in PHP.

In this post I want to make a short list of different ways to detect errors and bottle necks in our PHP projects. It’s an informal list of recommendations and best practises useful at least for me

Indent code.

Python has a great characteristic. Code blocks are defined with indentation. Not with any especial character like other program languages. That’s means if you don’t want syntax errors and you want to execute your program, your script must be properly indented. That’s is a great practise., even in program languages not as restrictive as python with code indention. For example when I need to check a piece of code with a any kind of error, if it isn’t correctly indented I start to indent it. I know it isn’t necessary but for me at least it helps me to understand the code (if I’m not the original developer of the code) and quickly find errors like wrong if clauses and another things like that.

Analyze code and check syntax

You must use a modern text editor or IDE with at least check syntax and also code analyze tools. That’s mandatory. Chose what you want but use one. Zend Studio is a great tool but you also can do it with another editors, even with vi. You can programing PHP with notepad but it’s definitely a waste of time. You will use significant less time programming with modern IDE. I like Zend Studio code Analyzer. It helps you with errors easy to implement and difficult to find like :

[sourcecode language=”php”]
// error 1
if ($a=1) {

// error 2
$variable= 2;
if ($Variable == 2) {

}
[/sourcecode]

I like to fix every warning even if those warnings are recommendations and not in fact a problem.

Check indentation level.

Even with a perfect indentation big indentation level is a clear signal of “code smell”. Take care of it. If you see a big indentation level you must ask yourself: Is it really the way to do it?

Loops.

If you want to check performance issues and you don’t have too many time,focus yourself finding loops and analyze them. If there is a performance problem is very probably to discover your problem inside a loop. One slow operation executed one time is a problem. But if this operation is executed 1000 times inside a loop is definitely a big problem. OK it’s the same problem but the impact is 1000 times bigger.

Copy-paste code

Avoid them like a plague. It can be helpfully and attractive but the use of the same piece of code distributed among a set of source code files will give you definitely a headache in the future, Be sure about it. We have a lot techniques in to avoid copy and paste code.

PHPDoc, code completion and iterations with PHP

Coding is very important part within our work as developers. Maybe it isn’t the outcome of our work. Our clients don’t really mind if our code is smart or not. They only want the product or service we give  them. Code is our problem. However smart code and agile programming skills are really useful to accomplish with our objectives. One useful tool is PHPDoc.
PHP is not Java. Java is a strongly typed programming language. Because of that modern IDE helps us a lot when we are coding Java. In PHP we don’t need to declare the type of a variable when we declare it. Even we don’t need t declare the variables. This behaviour can be good or bad. For IDEs it’s very bad. I’m not going to start the first flame-war between Java and PHP now. The fact is that we want to code as fast as we can making less mistakes and writing the less code as we can to reach our goals. PHP has some limitations but we also have some tools as PHPDoc to help us.

Let’s start with an example

[sourcecode language=”php”]
class MyClass
{
function hello($name)
{
return "Hello " . $name . "\n";
}
}
[/sourcecode]

When we want to use this class and we type:

[sourcecode language=”php”]
$obj = new MyClass;
echo $obj-> <—— code completion appear in our IDE suggesting hello function
[/sourcecode]

But now we put a simple singleton function in MyClass

[sourcecode language=”php”]
class MyClass
{
private static $_instance = null;
function singleton()
{
if (is_null(self::$_instance)) {
self::$_instance = new self;
}
return self::$_instance;
}

function hello($name)
{
return "Hello " . $name . "\n";
}
}
[/sourcecode]

And we use our singleton:

[sourcecode language=”php”]
echo MyClass::singleton()-> <—- ups nothing happens
[/sourcecode]

That’s because our IDE doesn’t know the return type of our singleton function. Because of that we are going to help to our IDE with a bit of PHPDoc magic.

[sourcecode language=”php”]
private static $_instance = null;
/**
* @return MyClass
*/
function singleton()
{
if (is_null(self::$_instance)) {
self::$_instance = new self;
}
return self::$_instance;
}
[/sourcecode]

And now our IDE will help us.

And now something a bit different. We have other class:

[sourcecode language=”php”]
class MyClass2
{
static function getAll()
{
return array(new MyClass, new MyClass, new MyClass);
}
}
[/sourcecode]

According to PHPDoc manual we can hint getAll function with @return array[int]MyClass but code completion doesn’t work, at least on my tests (please tell me I’m wrong because it’s the best solution).
So I need to use a small trick to get the autocompletion:

[sourcecode language=”php”]
foreach (MyClass2::getAll() as $row) {
/* @var $row MyClass */
echo $row-> <——————- code completion appear
}
[/sourcecode]

I’ve tried with @return array[int]MyClass and also using SPL Iterators but that’s the only way I know to ensure autocompletion.

Other possible solution is use a dummy cast function in MyClass. It’s a bit ugly solution but also works always:

[sourcecode language=”php”]
/**
* @param MyClass $cls
* @return MyClass
*/
static function cast($cls)
{
return $cls;
}
[/sourcecode]

Now We can use:

[sourcecode language=”php”]
foreach (MyClass2::getAll() as $row) {
echo MyClass::cast($row)->hello("Gonzalo"); // code completion works
}
[/sourcecode]