loading...
Cover image for How to write a different PHP?

How to write a different PHP?

adnanbabakan profile image Adnan Babakan (he/him) Updated on ・4 min read

Hey there DEV.to community.

PHP is one of the most discussed programming languages out in the development world. Some people call it a dead programming language, some call it a disgusting programming language which has no convention or architecture, which I agree with some of them because they've got fair points. But here I'm going to share some of my experience with PHP that I got all these years programming in PHP. Some of these tips are only available in most recent PHP versions so they might not work in older versions.

Type hinting and return types

PHP isn't a perfect language when it comes to data types but you can improve your code quality and prevent further type conflicts by using type hinting and return types. Not many people use these features of PHP and not all PHP programmers know that it is possible.

<?php
function greet_user(User $user, int $age): void {
    echo "Hello" . $user->first_name . " " . $user->last_name;
    echo "\nYou are " . $age . " years old";
}

A type hinting can be declared using a type's name or a class before the argument variable and a return type can be declared after the function's signature following a colon sign.

A more advanced use of this can be when you are designing your controllers in a framework like Laravel:

<?php
class UserController extends Controller
{
    // User sign up controller
    public function signUp(Request $request): JsonResponse
    {
        // Validate data
        $request->validate([
            'plateNumber' => 'required|alpha_num|min:3|max:20|unique:users,plate_number',
            'email' => 'required|email|unique:users',
            'firstName' => 'required|alpha',
            'lastName' => 'required|alpha',
            'password' => 'required|min:8',
            'phone' => 'required|numeric|unique:users'
        ]);

        // Create user
        $new_user = new User;

        $new_user->plate_number = trim(strtoupper($request->input('plateNumber')));
        $new_user->email = trim($request->input('email'));
        $new_user->first_name = trim($request->input('firstName'));
        $new_user->last_name = trim($request->input('lastName'));
        $new_user->password = Hash::make($request->input('password'));
        $new_user->phone = trim($request->input('phone'));

        $new_user->save();

        return response()->json([
            'success' => true,
        ]);
    }
}

Ternary operator and a shorter way

Ternary operator is a thing that almost 70% of programmers know about and use it widely but in case you don't know what a ternary operator is see the example below:

<?php
$age = 17;
if($age >= 18) {
    $type = 'adult';
} else {
    $type = 'not adult';
}

This code can be shortened to the code below using a ternary operator:

<?php
$age = 17;
$type = $age >= 18 ? 'adult' : 'not adult';

If the condition is met the first string will be assigned to the variable if not the second part will be.

There is also a shorter way if you want to use the value of your condition if it is evaluated to a truly value.

<?php
$url = 'http://example.com/api';
$base_url = $url ? $url : 'http://localhost';

As you can see $url is used both as the condition and as the result of the condition being true. In that case, you can escape the left-hand operand:

<?php
$url = 'http://example.com/api';
$base_url = $url ?: 'http://localhost';

Null coalescing operator

Just like a ternary operator you can use a null coalescing operator to see if a value exists, note that existing is different than a falsely value since false is a value itself.

<?php
$base_url = $url ?? 'http://localhost';

Now $base_url is equal to http://localhost but if we define $url even as false the $base_url variable will be equal to false.

<?php
$url = false;
$base_url = $url ?? 'http://localhost';

Using this operator you can check if a variable is defined previously and if not assign it a value:

<?php
$base_url = 'http://example.com';
$base_url = $base_url ?? 'http://localhost';

You can shorten this code using null coalescing assignment operator

<?php
$base_url = 'http://example.com';
$base_url ??= 'http://localhost';

All these nall coalescing techniques can be implemented on array values as well.

<?php
$my_array = [
    'first_name' => 'Adnan',
    'last_name' => 'Babakan'
];

$my_array['first_name'] ??= 'John';
$my_array['age'] ??= 20;

The array above will have the first_name as Adnan since it is already defined but will define a new key named age and assign the number 20 to it since it doesn't exist.

Spaceship operator

Spaceship operator is a pretty useful operator when it comes to comparison when you want to know which operand is larger rather than only knowing if one side is larger.

A spaceship operator will return one of the 1, 0 or -1 values when the left-hand operand is larger, when both operands are equal and when the right-hand operand is larger respectively.

<?php
echo 5 <=> 3; // result: 1
echo -7 <=> -7; // result: 0
echo 9 <=> 15; // result: -1

Pretty simple but very useful.

This gets more interesting when you realize that the spaceship operator can compare other things as well:

<?php
// String
echo 'c' <=> 'b'; // result: -1

// String case
echo 'A' <=> 'a'; // result: 1

// Array
echo [5, 6] <=> [2, 7]; // result: 1

Arrow functions

If you have ever programmed a JavaScript application especially using recent versions of it you should be familiar with arrow functions. An arrow function is a shorter way of defining functions that they have no scope.

<?php
$pi = 3.14;
$sphere_volume = function($r) {
    return 4 / 3 * $pi * ($r ** 3);
};

echo $sphere_volume(5);

The code above will throw an error since the $pi variable is not defined in this particular function's scope. If we wanted to use it we should change our function a bit:

<?php
$pi = 3.14;
$sphere_volume = function($r) use ($pi) {
    return 4 / 3 * $pi * ($r ** 3);
};

echo $sphere_volume(5);

So now our function can use the $pi variable defined in the global scope.
But a shorter way of doing all this stuff is by using the arrow functions.

<?php
$pi = 3.14;
$sphere_volume = fn($r) => 4 / 3 * $pi * ($r ** 3);

echo $sphere_volume(5);

As you can see it is pretty simple and neat and has access to global scope by default.


I hope you enjoyed this article, and I'm also planning on continuing this article and make it a series.

Tell me if I missed something or any other idea you have in the comments section below.

Posted on by:

adnanbabakan profile

Adnan Babakan (he/him)

@adnanbabakan

I'm Adnan Babakan and I'm from Iran. I started programming since I was 8 and now I'm 19. I love programming!

Discussion

markdown guide
 

I never use arrow function. If I wanted to use javascript, I would use it not php. Arrow function destoys the readabilty of the code.
I don't like using everything if it's new, you need to think about it if it's worth or not.

 

Hi Erhan
PHP and JavaScript are different and I don't think only just because you want to use arrow functions you would switch to JavaScript.
On the opposite hand, I think arrow functions increase the readability.

 

Well, If you work on your own project alone it can be ok but real world isn't like that. You can work with a team on a big project and it can be really really messy with arrow function.
I know it because I worked on a big javascript project with a big team and arrow function makes it really mess in my opinion.
Right now my php team doesn't allow using arrow function and I'm happy about it.

I respect your opinion but really disagree about being messy since arrow functions are made to make code more clear if your function is not that much complicated. If you wanted to use a global variable in PHP you should GLOBAL or $_GLOBAL which is not needed in arrow functions.

 

For functions that perform simple operations, I'll rather a bunch of arrow functions instead.
IMO, It makes such functions more readable 😁

 

It would have been much more useful if the arrow syntax could be used for multiline function.

I actually like that it closes over the value of the enclosing scope. It would have been much more useful when creating an anonymous function that uses data from the enclosing scope.

<?php
function create($name,$age) {
    $this->em->transactional(fn() {
        $person = new Person($name,$age);
        $this->em->persist($person);
        $this->em->flush();
    });
}
 

Yes, it would have been awesome. Maybe in the later version, they will add such a feature.

 

It would be helpful if you can add the PHP version from which each feature is available. I think most features you mentioned only available in PHP 7.4

 

New in 7.4 are the arrow functions and the $foo ??= 'bar; assignment. 7.2 brought class-based type hinting and return types, and everything else was included in 7.0 - including $too = $foo ?? 'bar'; and scalar type hinting.

 

I love that a

✨Spaceship operator 🚀

exists.

 
 

Doesn't Laravel automatically trim the values of the request?

 

For some reason sometimes there is an inconsistency. That's why I added another layer or triming. LOL

 
 
 

Don't forget you can also assign values in the assignment part:
$type = ($age >= 18) ? 'adult' : 'no adult';
is the same as
($age >= 18) ? $type = 'adult' : $type = 'no adult';

 

The single question that i have, cuz i m lazy at the moment, is this a 7.x feature? Or is it possible on 5.6.x , too?

 

Hi
I believe they are 7.x features.

 

$base_url = $url ? $url : 'localhost';

shouldn't that be

$base_url === $url ? $url : 'localhost';

otherwise the condition will always be true because you assign a variable..

 

Hi Dan
Not it is not a condition, it is an assignment statement.