DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Languages
  4. 5 features of PHP that seem hacks, but save your life

5 features of PHP that seem hacks, but save your life

Giorgio Sironi user avatar by
Giorgio Sironi
·
Nov. 01, 10 · Interview
Like (0)
Save
Tweet
Share
15.77K Views

Join the DZone community and get the full member experience.

Join For Free

Back at the PHP Barcelona conference, Ilia Alshanetsky made a talk about some hidden features of PHP. Ilia is one of the people that get his hands dirty in the PHP core, and PHP has indeed many overlooked features.

Of course, the GOTO introduction in PHP 5.3 really sucks and is a symptom of how PHP lacks a shared vision and consistency as a programming language; vision and conceptual integrity that we find for example in Python. Note that I'm a PHP guy: imagine what a Java programmer would say.

However, thinking about this load of features inspired me to write this article: I'll include here 5 features that at first seem an hack, but can save your life while coding in PHP. In fact, you probably use or will use them every day without noticing.

With great power comes great responsibility. -- Uncle Ben

Access to private properties

The Reflection API in PHP 5.3 has the capability of access private properties. Private properties are designed for encapsulation and shouldn't be normally referred to from outside a class, but using reflection to set them is a standard way of dealing with object persistence.

Doctrine 2 follows an Hibernate-like structure, and use this feature to introspect your object graph and put it into a database where each object loosely correspond to a row and each column contain a property value. On the converse, it can also reconstitute an object by setting its private properties. Without the reflection support, object would need to provide an Api for accessing their internal state, an Api open to misuse.

eval()

eval() executes a string containing PHP code. It can easily get out of hand, but dynamic creation of classes can be very handy. For example, eval() can be used for automatic generation of Test Doubles in test suites.

Since Mocks and Stubs must be a subclass/implementation of a chosen class or interface, their code can't be written in advance: they have to extend/implement a particular target class, and override the methods when present to provide hooks for insertion of canned results and expectation on parameters.

PHPUnit generates the code of a Mock and passes it to eval(), so that the new class becomes available for instantiation. PHPUnit must create this class with a generated name, before instatiating the object to pass back.

By the way, Doctrine 2 does the same for proxies without calling eval(): since it reuses the generated code, it saves the class in a .php file that then includes. The source code can be recycled in subsequent HTTP requests, and the effect and the mechanics, apart from the need to pass from a .php file, are the same of eval().

__DIR__

Indeed PHP code should not depend on where it is stored: a class should work even if I include it from another totally different script, which reside in another working directory. The __DIR__ constant provides information a particular file, that do not change when it is included from another point of the application. Thus it can be breaking this principle.

However, during bootstrap, it's very handy to have __FILE__ and, in PHP 5.3, __DIR__ available. They respectively point to the path of the file, or directory containing the file, that they are written in.

Bootstrap files commonly read __DIR__ to setup autoloaders with path referring to fixed __DIR__ instead of the current working directory, which may change depending on the including source. For example:
new MyAutoLoader($libraryPath = realpath(__DIR__ . '/../library'));

The other entry points of the application can then just include the boostrap file, without worrying about their relative position or anything else.

<?php does not need ?>

In PHP, you do not have to close your <?php tags with a corresponding ?> at the end of .php files.

Eliminating this closing tag means that no trailing spaces will be printed: coding standards for major projects include the prescription to never close ?> in class definition files.

Trailing spaces and any other content, when output buffering is not activated, define the end of the HTTP response headers section, so after any output you can't do HTTP redirects or send cookies anymore. Of course you can activate output buffering with ob_start(), that means the output will be kept in a buffer instead of being sent, until you decide otherwise.

The problem is that output buffering is activated by frameworks usually after startup, and due to autoloading your and their class files can be loaded well before then. So, just avoid introducing invisible content after ?> solves the root cause of the problem.

When output is already started and you try to start sessions (which sends a cookie) or do a redirect, PHP will raise a nice error containing the file and line number when output is started. It probably relates to a ?> tag.

__sleep()

I heard Stefan Priebsch saying the __sleep() and __wakeup() magic methods are a crime, and I agree that in the majority of use cases the serialization and deserialization of an object should not include these hooks.

Indeed, __wakeup() is almost nonsensical, since an unserialized object should pull, inside that method, every resource it needs to return in a functional state. Since unserialization means the object has usually lost contact with application resources like database connections, it will have to call some static method or singleton, and rely on the global state to work. It's much better to think of a solution where the object is injected its dependencies, previously detached on storage, upon returning in the land of the living.

In my opinion, __sleep() has instead some usefulness. When developing Doctrine 2 lazy loading support, we created Virtual Proxy implementation that subclass an Entity, and have an internal reference to the Entity Manager. This means that if you try to serialize your loaded User, which has a reference to a Group instance (these are two made-up domain classes), it will pull into the serialized graph the GroupProxy subclass and everything it is attached to, like the Entity Manager (main Facade of Doctrine), and its internal database connection, along with the whole Doctrine 2 runtime.

Our __sleep(), inserted automatically during Proxy generation, excludes the Entity Manager from the picture. If you want to then save your Proxies in the session, an act that triggers serializaton, you can easily treat them as normal objects: after they have been loaded they become equivalent to the real object they represent.

PHP Database Object (computer science) Hack (falconry)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How Agile Architecture Spikes Are Used in Shift-Left BDD
  • Reconciling Java and DevOps with JeKa
  • Securing Cloud-Native Applications: Tips and Tricks for Secure Modernization
  • Scaling Your Testing Efforts With Cloud-Based Testing Tools

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: