Hire the Top 3% of Freelance PHP Developers

Toptal is a marketplace for top PHP developers, engineers, programmers, coders, architects, and consultants. Top companies and start-ups choose Toptal PHP development services for their mission-critical PHP web development projects.

No-Risk Trial, Pay Only If Satisfied.

Clients Rate Toptal PHP Developers4.3 / 5.0on average across 1,757 reviews as of Jan 16, 2021

Hire Freelance PHP Developers and Engineers

Jay Johnston

Freelance PHP Developer

United StatesFreelance PHP Developer at Toptal Since November 6, 2013

Coding HTML, CSS, and JS since his armed forces days in 1997, Jay's experience in adapting web technology to meet customer needs is extensive. He enjoys bringing value to clients via eCommerce solutions, legacy integrations, and optimized PHP and JavaScript-driven applications.

Show More

Arianit Fazliu

Freelance PHP Developer

KosovoFreelance PHP Developer at Toptal Since August 25, 2014

Arianit is a skilled front-end and back-end developer with over nine years of professional experience. He has strong knowledge of Vue.js, React, AngluarJS, PHP Laravel, Node.js, WordPress, Photoshop, Illustrator, HTML5/CSS3, and JavaScript.

Show More

Igor Santos

Freelance PHP Developer

BrazilFreelance PHP Developer at Toptal Since October 20, 2013

Igor is a web developer focused on modern PHP and JS, always striving for new technologies. When he wears his back-end hat, he's focused on performant and DRY code, working on API servers or consumers. When he gets his front-end hat on, he works heavily on maintaining the best UX he can make for his users.

Show More

David Marín

Freelance PHP Developer

SpainFreelance PHP Developer at Toptal Since April 21, 2015

David is an open-source and open data enthusiast with more than 20 years of experience as a professional developer. He has acquired a broad variety of skills, including web programming (PHP and JavaScript), C, C++ (under Linux and Windows), and systems management. Of these skills, David specializes in web programming and has full-stack experience with Symfony PHP-based back ends, jQuery front ends, and WordPress-based sites.

Show More

Alexey Filatov

Freelance PHP Developer

RussiaFreelance PHP Developer at Toptal Since February 8, 2015

Alexey is an experienced full-stack developer with extensive knowledge of OOP and design patterns. He specializes in creating complex web services using modern tech stacks like Node.js and PHP/Laravel. He has over nine years of experience as well as a bachelor's degree in computer science and certifications in PHP and MySQL from Zend and Oracle, respectively.

Show More

Branislav Jovanovic

Freelance PHP Developer

NorwayFreelance PHP Developer at Toptal Since April 4, 2016

Branislav is a highly-skilled, enthusiastic developer. He is hard-working, possesses extensive problem-solving skills, and loves implementing a general algorithmic approach. A team player with a can-do attitude, Branislav is interested in eCommerce and PHP in further connection with other services. He’s worked the full development lifecycle from identifying the client’s real needs to designing the systems architecture as well as implementation.

Show More

Milorad Popovic

Freelance PHP Developer

SerbiaFreelance PHP Developer at Toptal Since September 22, 2014

Milorad has over ten years of experience on IT projects involving Microsoft, Cisco, virtual systems, networking, VoIP, and other technologies. He is very self-motivated and professional QA leader and is always willing to introduce improvements into the work process. He is a strong team player, able to give support and guidance to other staff members. Milorad works well in a variety of environments.

Show More

Alex Gonzalez

Freelance PHP Developer

United StatesFreelance PHP Developer at Toptal Since February 25, 2019

Alex has over ten years of experience developing software, especially web and mobile apps. He’s led the development of interactive projects for companies including AT&T, EMC, Legendary Pictures, Hewlett Packard, Foundation Capital, UCLA, Anaheim Ducks, and LA18 Television. Apps he’s developed have been featured in TechCrunch and iPod commercials. Alex graduated with a degree in Applied Mathematics from the University of California, Berkeley.

Show More

Tyler Standley

Freelance PHP Developer

United StatesFreelance PHP Developer at Toptal Since June 25, 2018

Along with strong communication skills and an exemplary work ethic, Tyler brings his hands-on experience with a wide range of programming languages. Recently, though, his focus has been directed towards JavaScript libraries. Throughout his career, he’s worked on multiple agile teams as a core developer and is now interested in working on anything JavaScript-related.

Show More

Benjamin Kuker

Freelance PHP Developer

CanadaFreelance PHP Developer at Toptal Since October 15, 2019

Benjamin is a solid developer with career highlights of working as a senior full-stack developer for a big data analytics startup, a payment processor, and a user testing service. He's worked across the entire development lifecycle and specializes in the front end. Benjamin is meticulous with implementation details while always considering and balancing broader stakeholder concerns. Communication wise, he is prompt, relevant, and professional.

Show More

Lorand Csatlos

Freelance PHP Developer

RomaniaFreelance PHP Developer at Toptal Since May 29, 2017

With over a decade of programming experience and 6+ years as a business owner, Lorand knows the importance of great communication and understanding with a client. He's obsessed with high quality and attention to detail, and he strives to find the best solutions possible. He currently focuses on using Magento or TYPO3 in his projects.

Show More

Sign up now to see more profiles.

Start Hiring

A Hiring Guide

Guide to Hiring a Great PHP Developer

While many can legitimately claim to "know" PHP, those who are true experts in the language are capable of producing software that is much more scalable, functional, robust, and maintainable. This guide offers a sampling of effective questions to help evaluate the breadth and depth of a candidate's mastery of PHP.

Read Hiring Guide

PHP Hiring Resources

Toptal in the press

... allows corporations to quickly assemble teams that have the right skills for specific projects.

Despite accelerating demand for coders, Toptal prides itself on almost Ivy League-level vetting.

Our clients
Building a cross-platform app to be used worldwide
Thierry Jakicevic
Building a cross-platform app to be used worldwide
Creating an app for the game
Conor Kenney
Creating an app for the game
Leading a digital transformation
Elmar Platzer
Leading a digital transformation

Tripcents wouldn't exist without Toptal. Toptal Projects enabled us to rapidly develop our foundation with a product manager, lead developer, and senior designer. In just over 60 days we went from concept to Alpha. The speed, knowledge, expertise, and flexibility is second to none. The Toptal team were as part of tripcents as any in-house team member of tripcents. They contributed and took ownership of the development just like everyone else. We will continue to use Toptal. As a start up, they are our secret weapon.

Brantley Pace, CEO & Co-Founder


I am more than pleased with our experience with Toptal. The professional I got to work with was on the phone with me within a couple of hours. I knew after discussing my project with him that he was the candidate I wanted. I hired him immediately and he wasted no time in getting to my project, even going the extra mile by adding some great design elements that enhanced our overall look.

Paul Fenley, Director

K Dunn & Associates

The developers I was paired with were incredible -- smart, driven, and responsive. It used to be hard to find quality engineers and consultants. Now it isn't.

Ryan Rockefeller, CEO


Toptal understood our project needs immediately. We were matched with an exceptional freelancer from Argentina who, from Day 1, immersed himself in our industry, blended seamlessly with our team, understood our vision, and produced top-notch results. Toptal makes connecting with superior developers and programmers very easy.

Jason Kulik, Co-Founder


As a small company with limited resources we can't afford to make expensive mistakes. Toptal provided us with an experienced programmer who was able to hit the ground running and begin contributing immediately. It has been a great experience and one we'd repeat again in a heartbeat.

Stuart Pocknee , Principal

Site Specific Software Solutions

We used Toptal to hire a developer with extensive Amazon Web Services experience. We interviewed four candidates, one of which turned out to be a great fit for our requirements. The process was quick and effective.

Abner Guzmán Rivera, CTO and Chief Scientist

Photo Kharma

Sergio was an awesome developer to work with. Top notch, responsive, and got the work done efficiently.

Dennis Baldwin, Chief Technologist and Co-Founder


Working with Marcin is a joy. He is competent, professional, flexible, and extremely quick to understand what is required and how to implement it.

André Fischer, CTO


We needed a expert engineer who could start on our project immediately. Simanas exceeded our expectations with his work. Not having to interview and chase down an expert developer was an excellent time-saver and made everyone feel more comfortable with our choice to switch platforms to utilize a more robust language. Toptal made the process easy and convenient. Toptal is now the first place we look for expert-level help.

Derek Minor, Senior VP of Web Development

Networld Media Group

Toptal's developers and architects have been both very professional and easy to work with. The solution they produced was fairly priced and top quality, reducing our time to launch. Thanks again, Toptal.

Jeremy Wessels, CEO


We had a great experience with Toptal. They paired us with the perfect developer for our application and made the process very easy. It was also easy to extend beyond the initial time frame, and we were able to keep the same contractor throughout our project. We definitely recommend Toptal for finding high quality talent quickly and seamlessly.

Ryan Morrissey, CTO

Applied Business Technologies, LLC

I'm incredibly impressed with Toptal. Our developer communicates with me every day, and is a very powerful coder. He's a true professional and his work is just excellent. 5 stars for Toptal.

Pietro Casoar, CEO

Ronin Play Pty Ltd

Working with Toptal has been a great experience. Prior to using them, I had spent quite some time interviewing other freelancers and wasn't finding what I needed. After engaging with Toptal, they matched me up with the perfect developer in a matter of days. The developer I'm working with not only delivers quality code, but he also makes suggestions on things that I hadn't thought of. It's clear to me that Amaury knows what he is doing. Highly recommended!

George Cheng, CEO

Bulavard, Inc.

As a Toptal qualified front-end developer, I also run my own consulting practice. When clients come to me for help filling key roles on their team, Toptal is the only place I feel comfortable recommending. Toptal's entire candidate pool is the best of the best. Toptal is the best value for money I've found in nearly half a decade of professional online work.

Ethan Brooks, CTO

Langlotz Patent & Trademark Works, Inc.

In Higgle's early days, we needed the best-in-class developers, at affordable rates, in a timely fashion. Toptal delivered!

Lara Aldag, CEO


Toptal makes finding a candidate extremely easy and gives you peace-of-mind that they have the skills to deliver. I would definitely recommend their services to anyone looking for highly-skilled developers.

Michael Gluckman, Data Manager


Toptal’s ability to rapidly match our project with the best developers was just superb. The developers have become part of our team, and I’m amazed at the level of professional commitment each of them has demonstrated. For those looking to work remotely with the best engineers, look no further than Toptal.

Laurent Alis, Founder


Toptal makes finding qualified engineers a breeze. We needed an experienced ASP.NET MVC architect to guide the development of our start-up app, and Toptal had three great candidates for us in less than a week. After making our selection, the engineer was online immediately and hit the ground running. It was so much faster and easier than having to discover and vet candidates ourselves.

Jeff Kelly, Co-Founder

Concerted Solutions

We needed some short-term work in Scala, and Toptal found us a great developer within 24 hours. This simply would not have been possible via any other platform.

Franco Arda, Co-Founder

Toptal offers a no-compromise solution to businesses undergoing rapid development and scale. Every engineer we've contracted through Toptal has quickly integrated into our team and held their work to the highest standard of quality while maintaining blazing development speed.

Greg Kimball, Co-Founder

How to Hire PHP Developers through Toptal


Talk to One of Our Industry Experts

A Toptal director of engineering will work with you to understand your goals, technical needs, and team dynamics.

Work With Hand-Selected Talent

Within days, we'll introduce you to the right PHP developer for your project. Average time to match is under 24 hours.

The Right Fit, Guaranteed

Work with your new PHP developer for a trial period (pay only if satisfied), ensuring they're the right fit before starting the engagement.


  • How are Toptal PHP developers different?

    At Toptal, we thoroughly screen our PHP developers to ensure we only match you with talent of the highest caliber. Of the more than 100,000 people who apply to join the Toptal network each year, fewer than 3% make the cut. You'll work with engineering experts (never generalized recruiters or HR reps) to understand your goals, technical needs, and team dynamics. The end result: expert vetted talent from our network, custom matched to fit your business needs. Start now.

  • Can I hire PHP developers in less than 48 hours through Toptal?

    Depending on availability and how fast you can progress, you could start working with a PHP developer within 48 hours of signing up. Start now.

  • What is the no-risk trial period for Toptal PHP developers?

    We make sure that each engagement between you and your PHP developer begins with a trial period of up to two weeks. This means that you have time to confirm the engagement will be successful. If you're completely satisfied with the results, we'll bill you for the time and continue the engagement for as long as you'd like. If you're not completely satisfied, you won't be billed. From there, we can either part ways, or we can provide you with another expert who may be a better fit and with whom we will begin a second, no-risk trial. Start now.


How to Hire a Great PHP Developer

Ubiquitous…that is definitely one word you could use to describe PHP in relation to the web. In web applications, website development, application development - it really is everywhere. In terms of server-side programming languages, it is by far the most widely used, powering more than 80% of today’s websites (with the next runner up, ASP.NET, trailing way behind at a mere 17%).

Why? What makes PHP so popular and widely-used? While there’s no single answer to this question, PHP’s ease of use is certainly a significant contributing factor. PHP newbies can get up-to-speed and build dynamic PHP-based content into their web sites with a minimum of programming expertise required.

But therein lies much of the challenge of finding highly-skilled PHP web developers. PHP’s relatively low barrier-to-entry and 20 year history means that PHP programmers have become practically as ubiquitous as the technology itself. Yet while many can legitimately claim to “know” PHP, those who are true experts in the language are capable of producing software that is much more scalable, functional, robust, and maintainable.

So how do you distinguish those who have real competency in PHP programming from those with just a cursory knowledge, let alone those who are in the top 1% of candidates?

Toward that goal, this guide offers a sampling of effective questions to help evaluate the breadth and depth of a candidate’s mastery of PHP. It is important to bear in mind, though, that these sample questions are intended merely as a guide. Not every “A” candidate worth hiring will be able to properly answer them all, nor does answering them all guarantee an “A” candidate. At the end of the day, hiring remains as much of an art as it does a science (see In Search of the Elite Few).

Note that we have tried to keep this guide focused on modern PHP (i.e., versions 5.3 and beyond), but there are references to concepts and functions that have been around for a long time and should be familiar to any qualified and experienced PHP developer.

Key PHP Concepts and Paradigms

There are a number of key concepts and paradigms that are essential for a part-time or full-time PHP expert to be well-versed in. Here are some examples.

Q: Describe a closure in PHP. Provide examples of when, why, and how they can be used.

Closures become useful when some piece of logic needs to be performed in a limited scope but retain the ability to interact with the environment external to that scope. The first building block of a closure is the anonymous, or lambda style, function which has no name associated with it. For example:

# The 2nd argument to array_walk is an anonymous function
array_walk($array, function($dog) {
    echo $dog->bark();

Although they themselves have no name associated with them, anonymous functions can be assigned to a variable or passed around as callbacks by higher order functions that require them. For example:

# Define an anonymous function and assign it to a variable
# named $dogs_bark.
$dogs_bark = function($dog) {  
    echo $dog->bark();
array_walk($array, $dogs_bark);

Under the hood in PHP, anonymous functions are implemented using the Closure class.

The contents of an anonymous function exist within their own scope, independent of the scope in which they were created. However, it is possible to explicitly bind one or more variables from the external scope to be referenceable within the anonymous function via the use clause in the function definition. Let’s illustrate:

class Dog {
    public function bark() { echo 'woof'; }

$dogs_bark = function($dog) use (&$collar) { # bind by reference
    if ($collar == 'fitsWell'){
         echo $dog->bark(); # 'woof'
    } else {
         echo 'no bark';    # collar is too tight to bark

$dog = new Dog;

$collar = 'fitsWell'; # external variable
$dogs_bark($dog); # 'woof'

$collar = 'tight';
$dogs_bark($dog); # 'no bark'

This ability to access these external variables within a closure becomes particularly useful when using higher order functions. Take for example our array_walk usage from above which, like other functions of this type, operates in a very specific way on the subject variables which it is passed. As the function iterates over the $array, only the current value and key are passed to the anonymous function callback. There is no opportunity to pass in the $collar variable without the closure and it’s use clause . We could use the global keyword, but would needlessly pollute the global namespace with a variable that only makes sense in our very limited scope.

Closures have additional object oriented uses as well. PHP 5.4 brings new methods to the Closure class’ interface. Specifically, the new bind and bindTo methods can be used to bind to new objects for the closure to operate on, e.g.:

Closure::bindTo($newthis, $newscope); 

This method will actually duplicate the closure itself and bind its scope to that new object, so $this actually references $newthis in the object context. To help illustrate, let’s modify the $dogs_bark function to use $this and then bind it to a new Dog object:

# define the closure, but not bound yet to any object
$dogs_bark = function() {
    echo $this->sound;  # where this is a property
$new_dog = new Dog();
# now create a new closure bound to the $new_dog object
$new_closure = $dogs_bark->bindTo($new_dog);
$new_closure();   # echoes the sound

The fact that a closure can be assigned to a variable and now has access to $this is quite powerful. In particular, this means that it can become a callable property of another object and essentially become a method of that object. For example:

$dog = new Dog();
$dog->closure = $dogs_bark;

This makes it possible to change and add to the behavioral capabilities of an object at runtime without the need to alter the defining class signature. Very useful when functionality enhancements are needed, but the actual code cannot be touched or where the need for the enhanced functionality is limited in scope.

Q: Explain the use and purpose of the global keyword in PHP. Provide an example of a case where its use would be appropriate, as well as one where it would not be.

In the days of “PHP gone by”, the language’s object oriented implementation was much less sophisticated than it is today. It is therefore not uncommon to find older “legacy” PHP code that makes fairly extensive use of the global keyword. In many ways, overuse of global variables “flies in the face” of modern object-oriented programming (OOP) best practices, as it may lead to intertwined dependencies between classes, difficulty decoupling disparate units of logic from one another, and pollution of the global namespace with variables that have no (or very limited) use in that context.

Consider the following simple example:

class Dog {
    function bark() {
        global $sounds;
        return $sounds->bark();

This introduces a hidden dependency of the Dog class on the global $sounds object. While there may be cases where this would be justified (e.g., a system with one single well-defined set of sounds that is never modified), generally speaking, it would be much better to explicitly pass the relevant $sounds object to the Dog class’ constructor, which would then be stored and used within that instance of the class; e.g.:

class Dog {
    protected $sounds; 
    function __construct($sounds) {
        $this->sounds = $sounds;

    public function bark() {
        return $this->getSounds()->bark();

    public function getSounds() {
        return $this->sounds;

But as is true with most things in coding, never say never. There are, in fact, a number of robust and stable products out there written in PHP that make heavy use of globals. The Wordpress Codex, which powers roughly 20% of the websites on the web (and rising yearly), Joomla! 1.5 (which is still in wide use), and the iLance Enterprise Auction system are all examples of projects that have been around for years and make use of ‘mature’ globals. Similarly, there may be situations where the use of globals in your code is appropriate, but their use should always be approach with caution.

Q: Describe namespacing in PHP and why it is useful.

One of the newer additions to PHP’s support for OOP is the namespace. As the name implies, a namespace defines a scope in a program where class, interface, function, variable, and constant definitions won’t produce name collisions with similarly named items in other namespaces.

Prior to PHP 5.4, class names would often become quite long in an attempt to match the package hierarchy and avoid name collisions. For example, let’s say we have a Dogs class defined in the model of the Dog_Pound application. Without namespacing, we might feel compelled to provide a verbose name for our class such as the following:

class Dog_Pound_Model_Dogs {  # wow, that's a mouthful!
    function getDogs();

Namespacing helps alleviate this issue by enabling the developer to explicitly specify the namespace within which all named items (classes, variables, etc.) are to be defined. With namespacing, the above verbose class name could be replaced with:

namespace dog_pound\model;  # specify the current namespace

class Dogs {   # only "Dogs" defined in dog_pound\model
    function getDogs();

$dogs = new Dogs; # unambiguous since only one in this namespace

Relative namespace references are supported as well. For example, when in the dog_pound namespace, you can use the following to instantiate your class:

$dogs = new model\Dogs  # only one "model" defined in dog_pound

In addition, named items in other namespaces can be imported in other files and can then be referenced directly. This is done via the use operator as follows:

namespace this\new\namespace;  # our current namespace

# import Dogs from dog_pound\model namespace and reference it
use dog_pound\model\Dogs;

$dogs = new Dogs;

Q: What are traits? Describe their major characteristics and why they are useful. Give an example of a trait declaration and a class that uses multiple traits.

Traits are an excellent addition to PHP 5.4 that allow behaviors to be added to a class, without needing to extend a parent class to inherit the desired functionality (prior to PHP 5.4, this could only be done via a mixin class pattern at runtime). Additionally, you can make use of multiple Traits in a single class. This makes them a powerful aid in the organization and separation of concerns in the codebase and, as such, helps to honor the composition over inheritance design principle.

Here are a couple of simple trait definition examples:

trait Movement {
    public function topSpeed() {
        $this->speed = 100;
        echo "Running at 100 %!" . PHP_EOL;
    public function stop() {
        $this->speed = 0;
        echo "Stopped moving!" . PHP_EOL;

trait Speak {
    public function makeSound(){
        echo $this->sound . PHP_EOL; 

The use keyword is once again employed, this time for importing from another namespace to include one or more traits in a class definition. For example:

class Dog {
    use Movement, Speak;  // Dog now has these capabilities!

    protected $sound;
    function __construct() {
        $this->sound = 'bark';

$dog = new Dog();
$dog->topSpeed();  // from Movement trait
$dog->stop();      // from Movement trait
$dog->makeSound(); // from Speak trait

PHP at Your Fingertips

Committing to memory what can easily be found in a language specification or API document is no indicator of proficiency. But that said, someone who is intimately familiar with a programming language will have its syntactical and functional details and nuances at his or her fingertips. Here are some questions that help evaluate this dimension of a candidate’s expertise.

Q: Describe the relationship between php://input and $_POST. How would you access the php://input stream?

In the simplest terms, the $_POST superglobal is the formatted or parsed content of the body of a request made to the server with the post method.

POST /php-hiring-guide/php-post.php HTTP/1.1
Referer: http:///toptal.php/php-hiring-guide/php.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 63
article_name=PHP Hiring Guide&tag_line=You are hired!&action=Submit

The body of the request can be accessed through the PHP’s input stream the same as any other file:

$input = file_get_contents("php://input"); 

Q: Name and define at least five superglobals that begin with $_. Describe their relationship to the $GLOBALS variable.

  • $_POST - a hash of key value pairs sent to the server with the ‘post’ method
  • $_GET - a hash of key value pairs sent to the server with the ‘get’ method
  • $_REQUEST - an amalgamation of $_GET and $_POST
  • $_SERVER - a hash of variables set specifically by the web server, and relevant to the execution of the program
  • $_ENV - a hash of variables related to the host machine and it’s configuration
  • $_SESSION - a hash of variables that are meant to be persisted between page views or separate application executions
  • $_COOKIE - a hash of variables that are to be stored with the client
  • $_FILES - a special type of request hash that holds input data related to an uploaded set of files

Akin to the global keyword in PHP is the $GLOBALS super global variable. As the name suggests, superglobals are automatic global variables and as such are stored in $GLOBALS. For example, the $_ENV superglobal could alternatively be accessed via $GLOBALS["_ENV"].

Q: Explain the purpose and usage of the __get, __set, __isset, __unset, __call, and __callStatic “magic” methods. When, how, and why (and perhaps why not) should each be used?

The first four methods in our list, __get, __set, __isset, and __unset are used for property overloading of an object. They let us define how the outside world is able to interact with properties that have a private or protected visibility, and properties that don’t even exist in our object.

# 'whiskers' is not defined in the Dog class but is handled by
# the Dog class' __get method as follows:
function __get($name) {
    if ($name == 'whiskers') {
        # only create one whiskersService per instance
        if (! isset($this->whiskersService)) {
            $this->whiskersService = new Whiskers($this);          
        # so calls to 'whiskers' will load the wiskersService
        return  $this->whiskersService->load();

A caller can then simply retrieve the whiskers property like so:

$hairs = $dog->whiskers;

By using the __get method to “intercept” this reference to a seemingly public property we are able to obscure the implementation details of one or more of the object’s properties.

Use of the __set method is similar. For example:

function __set($name, $value) {
    if ($name == 'whiskers') {
        if ($value instanceOf Whisker) {
            return $this->whiskersService->getData();
        } else {
            throw new WhiskerException("That's not a whisker");
            return false;

A caller can then simply set the whiskers property like so:

$dog->whiskers = $hairs; 

This statement automatically invokes the __set method, using 'whiskers' as its first argument and the right side of the assignment as the second argument.

Lastly, the __isset and __unset methods complete the quartet. They each take just one argument, the $name of the property to be evaluated or operated on; e.g.:

function __isset($name) {
    if ($name == 'whiskers') {
        return (bool) is_object($this->whiskersService) &&

function __unset($name) {
    if ($name == 'whiskers' && is_object($this->whiskersService)) {
        # we don't want to completely kill the service:

The other two methods, __call and __callStatic, perform a similar function for classes, but give us method overloading. Through their use we can define how a class should react when an undefined, protected, or private method is called.

In a __call implementation where we want to ensure all “non-visible” method calls get returned the payload from the whiskersService we might do something like:

public function __call($method, $args) {
    return $this->whiskersService->load();

__callStatic has the same arguments, the same functionality and allow for this same interaction, but outside of a specific object context. This means that if we have this method defined we can use the ClassName::notVisibleMethod() syntax; e.g.:

public function __callStatic($method, $args) {
    if (!is_object(static::$whiskersService)) {
        static::$whiskersService = new Whiskers(__CLASS__);
    return static::$whiskersService->load(); 

$hairs = Dog::whiskers();

In the above set of examples, we have encapsulated the whiskers implementation from the outside world and made it the only available object exposed in this way. The clients of such properties and methods do not need to know anything about the underlying whiskersService or how the Dogs class is storing its data at all.

Collectively, these methods increase our ability to flexibly compose objects. The opportunity for object abstraction and encapsulation, and thus reusable, more compact code (and ultimately a more manageable system as a result) are also increased.

Care should be taken, though, in using these convenient methods, as the benefits can come at a cost. They are slower than straight access to an otherwise public property in question, and also slower than defined getters and setters. They also hamper use of certain useful capabilities (such as object reflection, autocomplete in your IDE, automatic documentation utilities like PHPDocumentor, and so on). So if these are facilities you want or need to rely on, you may consider defining methods and properties explicitly instead. As with most things, there’s no across-the-board right answer. The pros and cons should be evaluated on a case-by-case basis.

Q: Describe one or more Standard PHP Library (SPL) data structures. Give usage examples.

Most of PHP development deals with getting and processing data from one source or another, such as a local database, local files, a remote API, etc. As such, developers spend a great deal of time getting, organizing, moving, and manipulating that data. In some cases, an array just won’t cut it in terms of memory usage and performance and therefore better data structures are called for.

Also, with so much talk and focus on frameworks (this page could be filled with names of PHP frameworks like CakePHP and Codeigniter!), it could be difficult to find a developer who has a great deal of experience with the particular framework that your project is using. The net effect of such an active development community is that the distribution of developers working with a particular framework starts to shrink, and could make it harder for you to find that specific skill.

One area to focus on, and where you be reasonably sure that an expert PHP developer will have familiarity, is in the use of and general makeup of the Standard PHP Library (SPL). If the candidate has a solid background here, the chances of success for that candidate working into and adding value to your application are greater, regardless of the specific frameworks being used in your environment.

Specifically, a candidate should be familiar with some or all of the nine SPL data structures listed in the PHP Manual. Many provide highly similar functionality to one another, but the slight variations make each one more perfectly suited to a particular use. Here’s a brief overview:

  • SplDoublyLinkedList. Each element in this list holds links to the node before it and the node after it in the list. Picture that you are on line at the bank, but you are only able to see the person in front and the person behind you. That is analogous to the ‘link’ relationship between elements in a SplDoublyLinkedList. Inserting an element into the list is akin to someone cutting in front of you at the bank (but you then suddenly forget who was in front of you, and that person also forgets you entirely). Enables efficient transversal through a dataset and lets you list and add large amounts of data, with no internal need to re-hash.
  • SplQueue and SplStack. Very similar to the SplDoublyLinkedList are the SplQueue and SplStack. Both of these are essentially SplDoublyLinkedLists with different iterator flags (IT_MODE_LIFO is “Last In First Out” and IT_MODE_FIFO is “First In First Out”), which govern which order the elements are read in and what to do with those elements after they have been processed. One other distinction is that the SplQueue API might be considered a bit more intuitive, supplying an enqueue() method (rather than push()) and a dequeue() method (rather than shift()).
  • SplHeap. Represented internally as a binary tree, where each node in the tree has a maximum of two child nodes. It is an abstract class which must be extended to define a compare() method. This method is then used to perform real time sorting whenever a value is inserted into the tree.
  • SplMaxHeap and SplMinHeap. Concrete implementations of the SplHeap abstract class. SplMaxHeap provides a compare() method that maintains values in order from highest to lowest, whereas SplMinHeap provides a compare() method that maintains values in order from lowest to highest.
  • SplPriorityQueue. Similar to an SplHeap, but sorting is done based on an additional “priority” value supplied for each member.
  • SplFixedArray. Similar to a regular array, but indices can only be integers and the length of the array is fixed. It provides improved speed when implementing an array. There is no processing speed benefit over an array, the interface is optimized so that the objects don’t need to be hashed manually when adding elements.
  • SplObjectStorage. Provides an interface for mapping objects to data or simply providing a container for a set of objects. Essentially, it can use an object much like an associative array key to relate that object to some data or to no data at all.

Q: What will $x be equal to after the statement $x = 3 + "15%" + "$25"?

The correct answer is 18. Now let’s explain why.

PHP supports automatic type conversion based on the context in which a variable or value is being used.

If you perform an arithmetic operation on an expression that contains a string, that string will be interpreted as the appropriate numeric type for the purposes of evaluating the expression. So, if the string begins with one or more numeric characters, the remainder of the string (if any) will be ignored and the numeric value is interpreted as the appropriate numeric type. On the other hand, if the string begins with a non-numeric character, then it will evaluate to zero.

With that understanding, we can see that "15%" evaluates to the numeric value 15 and "$25" evaluates to the numeric value zero, which explains why the result of the statement $x = 3 + "15%" + "$25" is 18 (i.e., 3 + 15 + 0).

Depending on who you ask, automatic type conversion is either a great feature or one of the worst pitfalls of the PHP language. On the one hand, when used consciously and properly, it can be very convenient for the developer (e.g., I don’t need to write any code to convert “15” to 15 before using it in an arithmetic operation). On the other hand, it can easily lead to headfakes and hard-to-track-down bugs when it is employed inadvertently, since no error message or warning will be generated.

Q: Explain the significance of using the static keyword when invoking a method or property, including how it differs from the self keyword? When would you use it and why? Provide an example.

As of PHP 5.3.0, PHP implements a feature called late static bindings. “Late binding” comes from the fact that static:: will not be resolved using the class where the method is defined but will rather be determined using runtime information and scope. (Incidentally, the term “static” is a bit of a misnomer in that this is not limited to being used with static methods.)

Consider the following example:

class Dog {
    static $whoami = 'dog';
    static $sound = 'bark';

    function makeSounds() {
        echo self::makeSound() . ', ';
        echo static::makeSound() . PHP_EOL;

    function makeSound() {
        echo static::$whoami . ' ' . static::$sound;


Unsurprisingly, this will output “dog bark, dog bark”.

But now let’s extend this example to include the following:

class Puppy extends Dog {
    static $whoami = 'puppy';
    static $sound = 'woof';

    function makeSound(){
        echo static::$whoami . ' whimper';


You may be surprised to learn that this will output “puppy woof, puppy whimper”. To understand why, let’s revisit the makeSounds() method in the Dog class.

The makeSounds() method in the Dog class first invokes self::makeSound(). self:: instructs PHP to always use the scope of the same class (in this case, the Dog class). Therefore, calling self::makeSound() from within Dog’s makeSounds() method will always invoke Dog’s version of makeSound(). This is true even when we call Puppy::makeSounds() since Puppy has no makeSounds() method of its own and instead relies on Dog’s version. This is why the call from Puppy::makeSounds() to self::makeSound() outputs “puppy woof”.

Next, the makeSounds() method in the Dog class invokes static::makeSound(). static:: behaves differently from self::. static:: instructs PHP to use the version in the scope of the class that invoked the method at runtime (in this case, the Puppy class). Hence, when the call to static::makeSound() is made, it invokes Puppy’s version of that method. This is why the call from Puppy::makeSounds() to static::makeSound() outputs “puppy whimper”.

PHP Under-the-Hood

Understanding how PHP works “under the hood” is one of the primary defining characteristics of a PHP expert. Such a candidate will understand not only how to do something, but the various options available, and the performance and functional ramifications of each.

Q: How does PHP build an array internally?

Central to much of PHP development is the array. These are good for most uses where an iterable data structure is needed. Internally in PHP, arrays are stored, like many other data structures, as hash tables. PHP is written in C where there is no such thing as an associative array: arrays in C can only have integer indices. Therefore, a hash function is used to translate PHP array indices (both integer and string) into appropriate numeric indices and the array values are stored at that location or bucket in the hash table.

The process of finding bucket entries based on a hash of the array keys is of O(1) complexity (using Big O notation). This because no iteration over the hash is needed, since the hash function produces the exact location in the table. (Note that this changes slightly if there is more than one element in the bucket.)

PHP automatically increases the size of an array “on demand”. Specifically, when an element is added to an array, if addition of the element would cause the array to exceed its currently allocated size, PHP responds by doubling the memory allocation. The corresponding hash table needs to be completely rehashed as a result.

Let’s consider what that means for just a second: Adding values to an array can in some cases be as complex as iterating over that entire new array, and in that same situation you have doubled the memory footprint of that structure. Given this, where datasets begin to get large and memory is an issue, it may be wise to consider an alternative to an array, where loading the data for processing happens on a more as needed basis.

Q: What is the difference between the ArrayAccess and ArrayObject?

ArrayAccess is simply an interface definition that requires any class that implements it to define the following methods: offsetGet, offsetSet, offsetExists, and offsetUnset.

ArrayObject, on the other hand, is an instantiable class that implements the ArrayAccess interface. A nice usage convenience of an ArrayObject is that its elements can either be accessed the same as a standard array (i.e., via the familiar [] notation; e.g., $dogs['sound']) or via the offsetGet(propertyName) method (e.g., $dogs->offsetGet('sound')).

Q: What is a generator? When might you use it instead of an iterator or a plain array. What do yield and send do?

A generator looks much like any other function in PHP and shares some similarities with closures. When called for the first time in an iterable context (e.g., a foreach statement), the generator returns an object that is an instance of the Generator class, which in turn implements the Iterator interface. The values for iteration are generated in real-time eliminating the need to load an entire data set into memory before hand. That means that the result can be iterated over in much the same way that an array can, but with some important differences; namely they:

  • Can only be used in a forward run, meaning that one can’t iterate backwards over the values or start at the beginning. Calling the rewind() method on the generator will throw an exception.
  • Are slower than processing a pre-populated array (the generator is doing extra processing to produce the value).
  • Are extremely memory efficient.

One of the chief differences between a generator function and other PHP functions or closures is that they don’t make use of return to provide their results. Instead, yield is used to pass values out of the generator (e.g., yield $dog;). In fact, specifying a value on a return statement in a generator will produce a parser error, but an empty return statement will simply stop the generator altogether.

yield pauses execution and returns the current value to the scope of the structure that is using the generator. That structure has the opportunity to send information back to the generator at that same point in its execution via the send method (e.g., $generator->send(-1);).

With that basic explanation, let’s take a look at a simple example of a generator’s use.

First, let’s define our generator:

function dog_generator() {
    foreach (range(0, 2) as $value) {
        # some fake data source
        $dog = DogHelper::getDogFromDataSource($value);
        # catch input from send or use $dog
        $input = (yield $dog);    
        if ($input == -1) {
            return; // stop the generator

Note that, in the above example, we are assigning the result of the yield method call to a variable and must therefore wrap the yield in parentheses in order for it to be syntactically valid.

And now here’s an example of how we would use the above generator:

# Get an instance of the generator and assign it to a variable
$generator = dog_generator();

foreach ($generator as $dog) { # $dog is a result of 'yield'
    echo $dog . PHP_EOL;
    // we wanted to find the terrier
    if ($dog == 'Terrier') {
        # send an input into the generator via 'yield'
        echo 'We found the Terrier, stop the show.';

When we run the above code our example stops when it finds “Terrier”. For example:

We found the Terrier, stop the show.

The key benefits of a generator are ease of implementation, increased readability of code, and overall improved performance and memory usage.

So generally speaking, it’s best to use a generator where there is no need to rewind or iterate back over the values again in another part of the program. On the other hand, if memory is not a concern, then a simple array of the values is much faster.

The Big Picture

Q: List some of the major differences between (or sequential additions and improvements to) PHP 5.3, PHP 5.4 and PHP 5.5.

PHP 5.3 was released back in June 2009 but is still in wide circulation. Key new features in this release included: closures, lambda style functions, namespacing, and late static binding.

PHP 5.4 was released in March 2012, introducing Traits, as well as the ability to declare an array with a shortened [] syntax (e.g., $array = ['shih tzu', 'rottweiler']). In addition, register_globals was removed in this version.

PHP 5.5 was released in June 2013 and is the current release. This version adds support for generators (and their related yield and send keywords), as well as adding finally to the try/catch exception handling syntax. APC Cache is gone in favor of OpCache (based on the Zend Optimizer). PHP 5.5 also takes the array literal even further and supports syntax such as ['shih tzu', 'rottweiler'][1] (which returns “rottweiler”) as well as the handy notation of strings interpreted as arrays (e.g., '6, 5, 4'[0], which returns “6”).


Finding dedicated PHP developers in the USA or abroad can be relatively easy, but finding stellar PHP developers capable of building CRMs, modifying a CMS, doing app development, or more is a formidable challenge. The questions presented in this guide can serve as useful tools in your overall recruiting toolbox to better identify and hire PHP programmers who have mastered the language. Finding such candidates is well worth the effort, as they will undoubtedly have a significant positive impact on your team’s productivity and results.

Featured Toptal PHP Publications

Top PHP Developers are in High Demand.

Start Hiring