PHP Articles
self:: vs static:: in PHP
self:: vs static:: in PHP is all about inheritance and late static binding. It’s used when you are dealing with overrides and methods coming from the parent class.
self::
- Refers to the class where the method is defined.
- Does not consider inheritance overrides.
static::
- Refers to the class that is actually called at runtime.
- This is called late static binding.
- Allows child classes to override static properties/methods and still be respected.
class Automobile {
public static $type = "Automobile";
public static function getTypeUsingSelf() {
return self::$type; // bound to Automobile
}
public static function getTypeUsingStatic() {
return static::$type; // late static binding
}
}
class Car extends Automobile {
public static $type = "Car";
}
class Truck extends Automobile {
public static $type = "Truck";
}
class Van extends Automobile {
public static $type = "Van";
}
// ------------------- USAGE -------------------
echo Car::getTypeUsingSelf(); // Output: Automobile
echo "<br>";
echo Car::getTypeUsingStatic(); // Output: Car
PHP Access Modifiers (public, private, protected)
In PHP Object-Oriented programming, public, private, and protected are access modifiers (visibility keywords) used to control how properties (variables) and methods (functions) of a class can be accessed.
They are important in Object-Oriented Programming (OOP) because they enforce encapsulation (controlling how data is exposed and used).
Public
Members declared public can be accessed from inside the class, outside of the class and by subclasses (child classes). If no visibility is specified on a property the default will be public.
class Car {
public $brand;
public function setBrand($brand) {
$this->brand = $brand; // accessible inside the class
}
}
$car = new Car();
$car->brand = "Toyota"; // accessible outside the class
echo $car->brand; // Output: Toyota
Private
Members declared private can only be accessed inside of the class that defines them. They cannot be accessed from outside the class or by subclasses.
class Car {
private $engineNumber;
public function setEngineNumber($num) {
$this->engineNumber = $num; // accessible inside the class
}
public function getEngineNumber() {
return $this->engineNumber; // allowed via public method
}
}
$car = new Car();
$car->setEngineNumber("ENG123");
// echo $car->engineNumber; ERROR: Cannot access private property
echo $car->getEngineNumber(); // Output: ENG123
Protected
Members declared protected can be accessed inside of the class, in child(sub) classes that inherit from it. They cannot be accessed directly from outside of the class… only subclasses.
class Vehicle {
protected $type = "Generic Vehicle";
protected function getType() {
return $this->type;
}
}
class Car extends Vehicle {
public function showType() {
return $this->getType(); // accessible in child class
}
}
$car = new Car();
// echo $car->type; ERROR: Cannot access protected property
echo $car->showType(); // Output: Generic Vehicle
PHP Object Oriented Class Inheritance
PHP class inheritance is a mechanism that allows one class (called the child class or subclass) to inherit properties and methods from another class (called the parent class or superclass).
This allows you to reuse code, extend existing functionality, and follow the principle of "Don’t Repeat Yourself (DRY)".
Basics of Inheritance
1. The extends keyword is used in PHP to create inheritance.
2. A child class automatically inherits all the public and protected properties and methods of its parent class.
3. The child class can:
A. Use the inherited methods and properties directly.
B. Override methods from the parent class.
C. Add new methods and properties.
Example 1: Basic Inheritance
Here, the Dog class inherits from the Animal class but overrides the speak() method.
// Parent class
class Animal {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function speak() {
echo "$this->name makes a sound.<br>";
}
}
// Child class
class Dog extends Animal {
public function speak() {
echo "$this->name barks! Woof Woof!<br>";
}
}
// Usage
$animal = new Animal("Generic Animal");
$animal->speak(); // Output: Generic Animal makes a sound.
$dog = new Dog("Buddy");
$dog->speak(); // Output: Buddy barks! Woof Woof!
Example 2: Using parent:: to Call Parent Methods
The Car class overrides the start() method but still uses the parent’s method with parent::start().
class Vehicle {
public function start() {
echo "Starting the vehicle...<br>";
}
}
class Car extends Vehicle {
public function start() {
// Call the parent method first
parent::start();
echo "Car engine started!<br>";
}
}
$car = new Car();
$car->start();
// Output:
// Starting the vehicle...
// Car engine started!
Example 3: Multilevel Inheritance
Human inherits from Animal, and Animal inherits from LivingBeing. So, Human has all methods from both parents.
class LivingBeing {
public function breathe() {
echo "Breathing...<br>";
}
}
class Animal extends LivingBeing {
public function eat() {
echo "Eating...<br>";
}
}
class Human extends Animal {
public function speak() {
echo "Speaking...<br>";
}
}
$person = new Human();
$person->breathe(); // From LivingBeing
$person->eat(); // From Animal
$person->speak(); // From Human
How To Use PHP Late Static Binding
self:: vs static:: in PHP is all about inheritance and late static binding. So what is late static binding. When building a child class there may be a static property that overrides that same static property on the parent. So when extending this class you will potentially need access to the property on both classes. The way to do this is through late static binding. You can use the self:: and static:: operators to accomplish this.
self::
- Refers to the class where the method is defined.
- Does not consider inheritance overrides.
static::
- Refers to the class that is actually called at runtime.
- This is called late static binding.
- Allows child classes to override static properties/methods and still be respected.
Example: self:: vs static::
class Animal {
public static $type = "Generic Animal";
public static function getTypeUsingSelf() {
return self::$type; // bound to Animal
}
public static function getTypeUsingStatic() {
return static::$type; // late static binding
}
}
class Dog extends Animal {
public static $type = "Dog";
}
// ------------------- USAGE -------------------
echo Dog::getTypeUsingSelf(); // Output: Generic Animal
echo "<br>";
echo Dog::getTypeUsingStatic(); // Output: Dog
PHP $this, self and parent operators
Sometimes different aspects of object oriented programming can be a little confusing if you can’t picture a use case for them. Three class operators in PHP where usage can be a little confusing at times are $this, self and parent. In this article I will try to break things down and maybe you can see where you can use this in your code. Ok so let’s begin.
1. $this
- Refers to the current object instance.
- You use $this when you want to access properties or methods of the current object.
Example:
class Animal {
public $name;
public function setName($name) {
$this->name = $name; // "this object’s" name
}
public function getName() {
return $this->name; // returns "this object’s" name
}
}
$dog = new Animal();
$dog->setName("Buddy");
echo $dog->getName(); // Output: Buddy
2. self
- Refers to the current class itself, not the instance.
- Used for static methods and static properties.
- Does not depend on an object ($this is not available in static context).
Example:
class MathHelper {
public static $pi = 3.14159;
public static function circleArea($radius) {
return self::$pi * $radius * $radius; // accessing static property with self
}
}
echo MathHelper::circleArea(5); // Output: 78.53975
3. parent
- Refers to the immediate parent class.
- Used when you want to access a method or constructor from the parent class that is overridden in the child.
Example:
class Animal {
public function makeSound() {
return "Some generic animal sound";
}
}
class Dog extends Animal {
public function makeSound() {
// Call parent method, then add more
return parent::makeSound() . " and Woof!";
}
}
$dog = new Dog();
echo $dog->makeSound(); // Output: Some generic animal sound and Woof!
Now to summarize:
- $this refers to an instance of the class. It isn’t available in a static context, therefore cannot be used within a static class function.
- The self:: operator refers to the class-level property. It is used in a static context and refers to the actual class itself.
- The parent:: operator calls the overridden method from the parent class. It’s used in inheritance typically to call an overwritten method on the parent class.
Here is a really good example that should help you concieve these concepts and clear up any confusion.
class Animal {
public $name;
public static $kingdom = "Animalia";
public function __construct($name) {
$this->name = $name; // instance reference
}
public function describe() {
return "I am an animal named {$this->name}.";
}
public static function getKingdom() {
return "Kingdom: " . self::$kingdom; // static reference
}
}
class Dog extends Animal {
public function describe() {
// Use parent to get base description
$base = parent::describe();
// Add Dog-specific description
return $base . " I am also a dog that says Woof!";
}
public function introduce() {
// `$this` calls instance method
return $this->describe();
}
public static function getInfo() {
// `self` calls static property from this class (or parent if not overridden)
return "Dogs belong to " . self::$kingdom;
}
}
// ------------------- USAGE -------------------
// Create an object
$dog = new Dog("Buddy");
// $this -> instance reference
echo $dog->introduce();
// Output: I am an animal named Buddy. I am also a dog that says Woof!
echo "<br>";
// self -> static reference
echo Dog::getInfo();
// Output: Dogs belong to Animalia
echo "<br>";
// parent -> calling parent method inside child
echo $dog->describe();
// Output: I am an animal named Buddy. I am also a dog that says Woof!
echo "<br>";
// static method from parent
echo Animal::getKingdom();
// Output: Kingdom: Animalia
Install and Configure ImageMagick for PHP with brew package manager
This tutorial will show you step-by-step how to use brew package manager to install ImageMagick and then configure it to work with PHP.
First check if ImageMagick already exists. Either command below should do that for you.
brew info imagemagick
If ImageMagick isn't installed you can simply use the command below to install it.
brew install imagemagick
Now we need to setup PHP to use the ImageMagick extension. To do so we can use the pecl package manager.
Check if pkg-config is installed.
brew info pkg-config
If pkg-config isn’t installed run the following command.
Set a few configurations for pecl. Run the following 3 commands.
export PKG_CONFIG_PATH="$(brew --prefix imagemagick)/lib/pkgconfig"
export CPPFLAGS="-I$(brew --prefix imagemagick)/include/ImageMagick-7"
export CFLAGS="-DMAGICKCORE_HDRI_ENABLE=1 -DMAGICKCORE_QUANTUM_DEPTH=16"
Install the pecl imagick extension.
pecl install imagick
Restart PHP with brew.
brew services restart php
Check that gd and imagick extensions are set up properly.
php -m | grep -E "gd|imagick"
And that’s it! You may run into an issue with a non-existing imagick extension. If you have multiple versions of PHP installed and frequently switch between different versions you will need to install the Imagick extension for each PHP version.
Upload and Resize an Image with Laravel Vue and ImageMagick
In this example I use the Laravel and Vue frameworks to implement a SPA tool to upload images and display a list of images that have been uploaded. The application also demonstrates image resizing with the amazing PHP ImageMagick library. So there are a few prerequisits to get started however I won't cover that in this tutorial. I've added some links to get you through the prerequisits:
- Install imagemagick and the pecl imagemagick package. Configure the extension in php.
- Install and set-up Laravel to use the Vue 2 Options API with Webpack compiler.
- Create required Controllers, Blade Views, routes(web.php, api.php, routes.js) and Vue components
Assuming you have an initial setup you will need to generate an API controller to handle requests made from the Vue components. You can generate the controller with php artisan:
php artisan make:controller Api/ImageController
Next, we need to specify a directory to store these images. For this tutorial we will upload our images to /public/images. So notice in the ImageController the method public_path('images/'.$imageName) is used to specify this location.
/app/Http/Controllers/Api/ImageController.php
We need two methods to handle the functionality for this application. An index method for GET requests to retrieve a list of all images. And an upload method to handle a POST request to upload an image.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Imagick;
class ImageController extends Controller
{
/**
* index
*/
public function index()
{
$fileNames = [];
$imagesPath = public_path('images/');
$files = File::files($imagesPath);
foreach ($files as $key=>$file) {
$fileNames[] = [
'file'=>$file->getFilename(),
'path'=>$file->getPathname(),
'size'=>$file->getSize(),
'ext'=>$file->getExtension()
];
}
return response()->json($fileNames);
}
/**
* upload
*/
public function upload(Request $request)
{
$request->validate([
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
// Create a new Imagick object
$imagick = new Imagick();
// Read the uploaded image
$imagick->readImage($request->file('image')->getPathname());
// Resample the image (change the resolution)
$imagick->resizeImage(100, 100, Imagick::FILTER_LANCZOS, 1);
// Save the image
$imageName = time() . '.' . $request->file('image')->getClientOriginalExtension();
$imagick->writeImage(public_path('images/' . $imageName));
// Clear the Imagick object
$imagick->clear();
$imagick->destroy();
$fileNames = [];
$imagesPath = public_path('images/');
$files = File::files($imagesPath);
foreach ($files as $file) {
$fileNames[] = [
'file'=>$file->getFilename(),
'path'=>$file->getPathname(),
'bytes'=>$file->getSize(),
'ext'=>$file->getExtension()
];
}
return response()->json($fileNames);
}
}
/resources/js/Image/Upload.vue
The Upload.vue component will display an image upload form and a script to interact with the form actions. Once the user selects an image, they will be able to preview the image before upload. Notice the API request made with Axios POST to /api/images. These routes are specified in /routes/api.php
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
Upload Image Form
<div class="row m-1 g-1">
<div class="form-group col-md-12">
<input class="form-control" :class="[{'text-danger': 'image' in errors && errors.image.length > 0}]" type="file" @change="onFileChange" name="image" id="image" accept="image/*" >
</div>
<div v-if="'image' in errors" class="text-danger">
<span v-for="(error, index) in errors['image']" :key="'type-'+index">
{{error}}
</span>
</div>
</div>
<div v-if="preview" class="mt-3">
<img :src="preview" alt="preview" width="100" height="100" />
</div>
<div class="row m-1 g-1">
<div class="form-group col-12">
<button type="button" @click.prevent="cancelUpload" class="btn btn-sm btn-fw btn-danger float-end mx-2">
Cancel
</button>
<button class="btn btn-sm btn-fw btn-primary float-end" type="submit" @click.prevent="uploadImage">Upload Image</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
image: null,
preview: null,
user: {},
errors:{
image: []
},
};
},
methods: {
cancelUpload(){
let redirectTo = this.$route.query.redirect || { name: 'admin-images' };
this.$router.push(redirectTo);
},
async uploadImage(){
if(this.image)
{
let fd = new FormData();
fd.append('image', this.image);
try {
let resp = (await axios.post('/api/images', fd)).data.data;
let redirectTo = this.$route.query.redirect || { name: 'admin-images' };
this.$router.push(redirectTo);
} catch(error) {
this.errors = error;
}
}
else {
this.errors.image.push(`An image file is required for upload.`);
}
},
onFileChange(e) {
let file = e.target.files[0];
if (file) {
this.image = file;
this.preview = URL.createObjectURL(file);
}
}
},
created() {
console.log('Image/Upload COMPONENT CREATED.');
}
}
</script>
/resources/admin/js/Image/Index.vue
The Index.vue component will display a list of images that currently exist in the /public/images directory. Also notice the API GET request made to /api/images.
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-10">
<router-link
class="btn btn-primary mb-2 float-right"
:to="{ name: 'image-upload', query: {redirect: $route.fullPath} }">
Image Upload
</router-link>
<div class="mb-4 row" v-for="(image, index) in images" :key="index">
<img
:src="`/images/${image.file}`"
class="img-thumbnail "
width="100"
/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
images: [],
user: {}
};
},
methods: {
},
async created() {
let response = await axios.get("/api/images");
this.images = response.data.length ? response.data : [];
}
};
</script>
/resources/js/routes.js
In order to see the Image/Index.vue and Image/Upload.vue components we need to specify a route for each in routes.js. Because the path /images and /image/upload routes are handled via Vue we need to use a <router-link> inside of another Vue component order to navigate to /images and /image/upload.
Then configure the routes in /resources/js/routes.js like below:
import ImageIndex from "./Image/Index";
import ImageUpload from "./Image/Upload";
const routes = [
// add these 2 new routes
{
path: "/images",
component: ImageIndex,
name: "image-index",
},
{
path: "/image/upload",
component: ImageUpload,
name: "image-upload",
}
];
/routes/api.php
Finally we create API routes to upload and retrieve images. Notice both routes both go to /images and either Route::get or Route::post will be used to identify them properly in a request.
// GET request to ‘/api/images’
Route::get('/images', [App\Http\Controllers\Api\ImageController::class, 'index']);
// POST Request to ‘/api/images’
Route::post('/images', [App\Http\Controllers\Api\ImageController::class, 'upload']);
PHP Anonymous Functions Example Implementation
In PHP, an anonymous method is usually referred to as an anonymous function or a closure. These are functions defined without a name, and they're often used as callbacks or for short-term use.
Here are a few example usages of anonymous methods (closures) in PHP:
- Assign to a Variable
$greet = function($name) {return "Hello, $name!";};echo $greet("Mike"); // Output: Hello, Mike! - Use as Callback (e.g., array_map)
$numbers = [1, 2, 3, 4];$squared = array_map(function($n) { return $n * $n; }, $numbers);print_r($squared); // Output: [1, 4, 9, 16] - Use with use to Capture Variables from Parent Scope
$multiplier = 5;$multiply = function($n) use ($multiplier) {return $n * $multiplier;};echo $multiply(10); // Output: 50 - Inside of a Class as a Property
class Greeter {
public $greet;
public function __construct() {
$this->greet = function($name) {
return "Hi, $name!";
};
}
}
$greeter = new Greeter();
echo ($greeter->greet)("Ralph"); // Output: Hi, Ralph!
Remember to wrap class and property inside of parentheses. It's necessary in that specific form because $greeter->greet is a property that holds a closure, not a method. PHP interprets $greeter->greet("Taylor") as trying to call a method named greet, not a closure stored in a property.
5. Anonymous Method Bound to Object (Closure::bind)
class Person { private $name = "Secret Name";}$getName = function() {return $this->name;};$person = new Person();$bound = $getName->bindTo($person, 'Person');echo $bound(); // Output: Secret Name
If you would like more examples or have a question please shoot me a comment. Thanks!
PHP Ternary Operator ? :
$val = 10;$total = 0;$total = $val > 9 ? ($val + 10) : 0;
echo $total; // $val equals 20
Here is another example:
$newValue = $val ?: 9;
In this example $newValue is 10. Notice when $val is NOT null the $newVal will be the value of $val otherwise it's the value behind ?: which is 9 in this case.
Use PHP Recursion to Calculate the Sum of Multi-dimensional Arrays
For this example I will use PHP to create a script that calculates the sum of a multi-dimensional array of integers. We need a recursive method to do this. Well not necessarily in this example because the dimensions of array $numbers is known. So we can just use standard for, foreach or while loops embedded to traverse the array. However when the structure of $numbers is unknown, recursion is necessary.
Infact, the only way to traverse this kind of array is with recursion. At some point you will need to learn recursion. This example breaks things down and makes it easy to understand.
$numbers = [
2,
7,
5,
[
4,
8,
6
],
[
2,
3,
[
9,
3,
6
],
4,
5
],
[
7,
8,
9,
[
5,
5,
4
]
]
];
function calculate($input)
{
$sum = !is_array($input) ? $input : 0;
if(is_array($input))
{
foreach($input as $child)
{
$sum += calculate($child);
}
}
return $sum;
}
$sum = calculate($numbers);