The Ultimate Guide To Object Oriented PHP

object oriented php

PHP is now a mature language that has very strong support for object oriented programming. We like to talk about frameworks a lot, and these frameworks are built using object oriented PHP. In order for us to make the very best use of these wonderful programming frameworks, we must have a very strong grasp of object oriented techniques and best practices. The benefits are many, but at the top of the list are much greater code reuse, clean design, and simplified code maintenance. Let’s dig into object oriented PHP!


All About Objects

The Terms To Know For Your OOP Journey

One thing about OOP in PHP is that the verbiage is insane. We’re talking jargon like you’ve never seen, but in reality, the concepts are fairly straightforward – the terms just make them sound like rocket science. Fear not however, as rocket science is not a prerequisite to learning object oriented php! In order to set the stage for our object oriented journey, let’s first get the terms outlined.


Class:

It all starts with the class. The class is the master plan, dare I say the cliche but true, blueprint, for your code. I like master plan though, it sounds a little more grand. In basic terms, the class is a template or outline for creating objects.


Object:

The object comes from the class, much like a house would be built using a blueprint. We call an object an instance of the class. One class can have many instances. Let’s say we have a Person Class. As you know, we can have many people. At last count, I think there are about 7 with a B, Billion of us on the planet. That’s a lot of objects coming from the master class 🙂


Properties:

Objects have variables to store and manipulate data, but in OOP, they are called properties.


Methods:

Just as we have variables, we also have functions, but again in OOP, they go by a different name, method.


Encapsulation:

Our methods and properties in the class have visibility. You have likely seen the public, private, and protected keywords. When you see these, you know that the code is implementing encapsulation, or determining what can, or can not be, accessed from inside and outside the class. The key points to know are:

  • Private: The private keyword is used to label a property or method as accessible from inside the class only.
  • Public: The public keyword is used to denote a property or method that can be accessed anywhere, including outside of the class, or any classes that extend the parent class.
  • Protected: Last up, we have the protected keyword. Protected says that the properties and methods of a class can be accessed and manipulated only by the parent class, or classes that extend the parent class. We can learn more about visibility in php at the official docs.

Inheritance:

Inheritance is what we love about object oriented php. Inheritance is where we are able to have very powerful code reuse. A new class can extend the parent class and even add or modify existing properties and methods. It’s like a child that inherits all of her parent’s greatness, and adds her own as well! The original class gets named things like base class, parent class, or superclass. The new class is called the subclass or derived class.

Using inheritance makes it possible to build on existing generic classes. Using a general base class, one could create more focused and complex child classes as the need becomes apparent. By following this convention, frequent and repeating blocks of code can be written once in the superclass, instead of over and over in different subclasses. It may also help to better resemble real world relationships. A simple test to see if inheritance could or should be used is to insert an “is a” between the classes. If it makes sense, then you could likely use inheritance. For example the sentence, “A Teacher is a Person”, makes sense. It could make sense for a Teacher subclass to inherit from a Person superclass. Not all Persons are Teachers however, so a Person would not inherit from a Teacher.


Instantiating an Object

It’s easy to create a new object to use in our PHP program. We make use of the new keyword following this format:

Let’s pretend we have a Car class already defined. In order to create an object or instance of that Car class we could do this:

Depending on how the class was defined, we might be able to pass arguments during the creation of an object. Let’s assume we can in this example so we can pass arguments like so:

This would create a new car object and store it in $car. We can now access the methods and properties of the object using the arrow operator. The official name is T_OBJECT_OPERATOR, however arrow operator is easier to remember since it looks like an arrow ->!


Property and Method Access

Accessing the properties and methods of our class is easy using the -> operator like so:

We can also pass an argument to a method call. The method can also return a value just like normal php functions:

As we mentioned in the terms section above, encapsulation allows us to set the methods and properties to either public, private, or protected in the class definition. In addition to this normal process of object creation, we can use what are called static methods and properties. When you do this, the method is called on the class itself, not the created object. Statics are somewhat frowned upon in the community, but they are great for quick and dirty problem solving, and their syntax is very elegant. The example from our File Class is very easy to read and use:

You may not want to build a whole application out of static methods and properties, but for helper type classes, they make a great option.

Passed by Reference

Objects are passed by reference in PHP. This saves memory in the computer and provides the ability to maintain state of the object. For example:

Wow! Even though we called the setMake() method on the $car object, a var_dump of $c shows that the make is changed to ‘Porche‘! This is because both $c and $car point at the same object 🙂

To make a true copy you can use the __clone() method like so:

Cool Now we can see that a copy has been made and $car will contain Porche while $c will contain Subaru!


Defining A Class

Using classes that have been created for us is quite easy. We simply use the new keyword, instantiate some objects, and then we can enjoy all the methods and properties that the developers created for us. A great example of this is when we create a new object in one of the many great php frameworks. Defining our own classes is a little more tricky! When we define a class, we determine a class name, class properties, and class methods. Class names are case insensitive, though it’s best practice to capitalize your class names. At a minimum we can declare a class like so:

If we include all available options to us when creating our classes, the syntax would look like so.

That’s a lot of info, so let’s go through them one by one.


Defining Methods

A method is simply a function defined inside of a class. We can follow all the guidelines of creating regular functions then, like choosing a descriptive name, and using approved PHP characters. Stay away from the double underscore when naming your own functions since this has special meanings in the language, depending on the context.

$this is a special keyword in PHP and can be a little tricky. Basically, it is a reference to the current object. We can see how $this is used in this class definition of a Car.

This shows how the setMake() method makes use of $this to access and set the $make property of the current object. We can also declare a static method using the static keyword, just remember when calling that method, you call it on the class, not the object. Recall from our php file functions tutorial:

and the use case:

Note that we use the Scope Resolution Operator, or double colon, instead of the arrow operator, which allows access to static, constant, and overridden methods or properties in a class. The official name for the double colon operator is, get this, the Paamayim Nekudotayim, for which I have no idea how to pronounce 🙂

We can lock down our methods by using the final keyword. This stops classes that extend the parent class from overriding the method.

For example:

Setting the visibility of a method is easy by using any of the keywords public, private, or protected. If you do not specify a visibility, the method will default to public. For example if we set $make to private, we’ll now get a fatal error if we try to access it outside of the class:

We could however still set the private property and get access to the private property since the methods we use to access it setMake() and getMake(), are public.

Pretty Cool!


Defining Properties

We’ve been defining properties all along in the examples so far. No doubt you’re used to working with variables in your programs, well properties work the same way except they are tied to an instance of an object. In order to get access to them, we need to use the object. Declaring properties are optional, but certainly a best practice since it makes our code much more readable. For the lazy among us, we could rewrite the Car class without explicit property declaration like so and we can still set and get the make property:

You can also set default values to properties on declaration so long as those default values are simple constants:

As you know, we have the option of declaring our properties to public, private, or protected, based on how much visibility we would like to assign to them. We can also set them to static and interact with them like so:

Inside the object class, you can get access to the static property using the self keyword, like so self::$color.

Getters and Setters

A key advantages of OOP is that it encourages encapsulation. This can be enforced with the use of __get and __set functions. They may seem a little mundane, but the way these get and set functions work is really cool! This allows you to access the class properties via those methods rather than directly. For example:

If, instead of accessing the attributes of a class directly, you write accessor functions, you can make all your accesses through a single section of code. When you initially write your accessor functions, they might look as follows:

Note! The __get() function simply returns the value of the property, while the __set() function assigns a value to a property. __get() takes a single parameter, and __set() uses two. These functions do not get called directly! They have special meaning in PHP just like __construct() and __destruct(). When trying to set or get properties by something like $car->make = 'Toyota'; or echo $car->make;, what happens is under the hood, the __set() or __get() functions get magically called for you with the parameters supplied! So what’s the benefit you ask? Well, you could write the __set() function so that it filters or restricts what data can be assigned. Maybe we don’t like Chevy cars. Well we can prevent our objects from becoming Chevys like so:

Now, try as you may to assign Chevy to the make property, it will retain a null value.

Declaring Constants

You can assign constants within a class by using the const keyword. Access is similar to that of static properties in that you use the self keyword or :: operator like so:

Inheritance

When we want to inherit methods or properties from a class we must use the extends keyword. We could extend our Car class like so:

Cool! You’ll note that that there are no property or method definitions whatsoever in our Racecar class, yet we can still set and get the make of our new Racecar! That is because Racecar has inherited everything from Car by way of the extends keyword.

Private and Protected

If you are not specifying otherwise, everything from the base class will get extended to the child. You may want to limit what can be inherited though. In that case you could use either private or public like so:

We can also control the access to methods like so:

Interfaces

Interfaces are becoming more popular in use. The Laravel Framework and it’s community is especially keen on their use. Interfaces are a contract that define what methods a class must implement. Any class that implements the interface must provide implementations for all methods in the interface. The benefits to using an interface are many, once an application begins to grow in size. Testing, code maintenance, and swapping of implementations are the main factors to consider. An example interface might look something like this:

Note that the interface is merely a definition, it does not contain any actual code!

Constructors

No discussion of object oriented programming is complete without talking about constructors. Constructors are very useful to us for setting default values and getting our object ready for use right away. They also allow us to pass arguments to our objects as they are created. Let’s rewrite our Car class using a constructor:

This is great! We can see that as soon as the object is created, it’s key properties are set right away. Let’s make one more $car object and pass in different parameters just to be sure it works:

Yes this is working just as we expect!

Destructors

Though not as useful or important as constructors, destructors are worth a mention. Basically, a destructor is the opposite of a constructor. When the last reference to an object is removed or the end of the script is reached, the destructor gets called. The intention is to unset and clean up resources at this point. In reality, since PHP automatically cleans up all resources as soon as they fall out of scope, we don’t really need to worry about it. If you needed to, this is how to write a destructor:


Conclusion

Object Oriented PHP is a large topic and one blog post can not do it justice! This was however, a great overview of the key terms, techniques, and ideas when beginning to learn OOP in PHP. Since we like to talk about and implement many of the great PHP frameworks, it is mandatory that we know how their object oriented core works under the hood. I hope you found some good bits of information here whether you are a beginner or even a more experienced programmer just brushing up on the fundamentals.