• Stars
    star
    102
  • Rank 335,584 (Top 7 %)
  • Language
    PHP
  • License
    MIT License
  • Created over 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Functional programming paradigms in laravel to avoid run-time errors.

Laravel Nullable

Do not let "null" to impersonate your objects.

StyleCI Quality Score Code Coverage Latest Stable Version PHP from Packagist License

Functional programming paradigm in laravel

Built with ❀️ for every smart laravel developer

Null is usually used to represent a missing value (for ex when we can't find a row with a partcular Id we return null) And that is the BAD IDEA, we are going to kill off !!!

πŸ”₯ Installation:

composer require imanghafoori/laravel-nullable

This package exposes a nullable() global helper function with which you can wrap variables which sometimes are object and sometimes null.

Consider this:

$email = TwitterApi::find(1)->email;

Now this code is working fine But...

What if the user with ID of 1 gets deleted in future ?!

null->email and crap ! 😧

So if you forget to handle the null with an if statement, you will have errors.

You need something to FORCE you and the users of your class methods to handle the null cases.

To prevent such errors, you should code like this:

$user = $twitterApi->find($id);

if ($user === null) {
    return redirect()->route('page_not_found');
}

▢️ Nullables to rescue !!!

To refactor the code above, first

You have to change your repo class :

// the old way:

/**
* @return User|null            <---- consider here. We are returning two types !!!
*/
public function find ($id) {
     $user = TwitterApi::search($id);
     
     if (!$user) {
         return null;
     }
     return new User($user);   
}

The above code returns 2 types, and That is the source of confusion for method callers. They get ready for one type, and forget about the other.

Let's do a small change to it:

/**
 * @return Nullable        <---- we now have only one consistent type. Not two.
 */
public function find ($id) {
     $user = TwitterApi::search($id);
     
     if (!$user) {
         return new Nullable(null);   //  <----  instead of pure null;
     }
     $user = new User($user);   
     
     $message = 'Model Not Found with Id : '. $id;

     return new Nullable($user, [$message]);   //  <----  instead of User;
}

πŸ”” Now our method consistently returns Nullable objects, no matter what :)

After this change, no one can have access to the real meat of your repo (in this case User object) unless he/she gives a way to handle the null case. No if(is_null()) is required, No exception handling is required.

Remember PHP does not force us to write that if, and we as humen always tend to forget it.

And that makes a differnce ! Before it was easy to forget, but it is impossible to continue if you forget !!!

$userObj = $userRepo->find($id)->getOrSend(function ($message) {

  return redirect()->route('page_not_found')->with('error', $message);
});

// Call a static method.
$userObj = $twitterApi->find($id)->getOrSend([Response::class, 'pageNotFound']);

// or a get default value
$userObj = $twitterApi->find($id)->getOr(new User());

Now we are sure $user is not null and we can sleep better at night !

▢️ Testing:

An other advantage is that, if you use nullable and you forget to write a test that simulates the situations where null values are returned, phpunit code coverage highlights the closure you have passed to the ->getOrDo() (or similar methods) as none-covered, indicating that there is a missing test.

but if you return the object directly, you can get 100% code coverage without having a test covering nully situations, hence hidden errors may still lurk you at 100% coverage.

▢️ Q & A :

Why throwing exceptions is not always the best idea?!

When you throw an exception you should always ask your self. Is there any body out there to catch it ?? What if they forget to catch and handle the exception ?! It is the same issue as the null. It cases error.

The point is to give no way to continue, if they forget to handle the failures.

More from the author:

Laravel middlewarize (new*)

πŸ’Ž You can put middleware on any method calls.


Laravel Hey Man

πŸ’Ž It allows to write expressive code to authorize, validate and authenticate.


Laravel Terminator

πŸ’Ž A minimal yet powerful package to give you opportunity to refactor your controllers.


Laravel AnyPass

πŸ’Ž It allows you login with any password in local environment only.


Eloquent Relativity

πŸ’Ž It allows you to decouple your eloquent models to reach a modular structure


More Repositories

1

laravel-microscope

Fearless refactoring, it does a lot of smart checks to find certain errors.
PHP
1,307
star
2

laravel-widgetize

A minimal package to help you make your laravel application cleaner and faster.
PHP
902
star
3

laravel-heyman

Declarative style of authorization and validation in laravel.
PHP
880
star
4

laravel-MasterPass

Helps you securely setup a master password and login into user accounts with it.
PHP
354
star
5

laravel-terminator

A package to help you clean up your controllers in laravel
PHP
246
star
6

laravel-video

A laravel package to stream video content.
PHP
232
star
7

laravel-anypass

A minimal package that helps you login with any password on local environments
PHP
211
star
8

eloquent-relativity

Allows you to decouple your eloquent models from one another.
PHP
147
star
9

laravel-decorator

Easily decorate your method calls with laravel-decorator package
PHP
129
star
10

eloquent-mockery

Mock your eloquent queries without the repository pattern
PHP
123
star
11

laravel-middlewarize

Use middleware to decorate method calls within your application code.
PHP
105
star
12

laravel-temp-tag

Temporarily and Transparently, tag your eloquent models
PHP
100
star
13

laravel-smart-facades

Strategy design pattern in laravel, the easiest way.
PHP
87
star
14

laravel-password-history

Keep a password history of your users to prevent them from reusing the same password.
PHP
64
star
15

iranian-laravel-contributors

The list of people from Iran who have contributed to the laravel framework
40
star
16

laravel-tokenized-login

Two factor authentication in Laravel
PHP
36
star
17

eloquent-history

PHP
31
star
18

smart-realtime-facades

PHP
30
star
19

php-smart-search-replace

Smart search/replace functionality for PHP code
PHP
27
star
20

gilded_rose

Based on a tutorial for code refactoring
PHP
25
star
21

why_github_is_not_open_source

Why github.com is NOT open-source???
25
star
22

laravel-makesure

Readable syntax to write tests in laravel
PHP
21
star
23

eloquent-rating

5 star rating for eloquent models
PHP
18
star
24

laravel-file-cache-cleaner

Delete the obsolete cache files in the storage directory
PHP
15
star
25

php_token_analyzer

PHP
11
star
26

laravel-db-freeze

A package that allows you to bypass any insert, edit, delete into your database in demo mode through .env variables
10
star
27

laravel-anytoken

A minimal development package that helps you fake any api token as a valid one during development
10
star
28

composer-json

A utility class for read composer.json data and use it in PHP
PHP
9
star
29

crudbooster-statistics

Statistics module for Crudbooster CMS
HTML
8
star
30

imanghafoori1

8
star
31

laravel-microscope-ui

8
star
32

laravel-tik8

Simple modular ticketing system by laravel
8
star
33

crudbooster-logs

A plug-in for CrudBooster CMS to add log functionality
PHP
8
star
34

chat

node chat application
HTML
7
star
35

crudbooster-notifications

Adds notification functionality to crudbooster
PHP
7
star
36

laravel-nice-middlewares

This is a plug-in for laravel-middlewarize package.
PHP
6
star
37

questionist

Advanced event/listener system
PHP
6
star
38

abstract_php_filesystem

PHP
3
star
39

example_query

PHP
2
star
40

test-bin

1
star
41

laravel-endpoints

Define your endpoints as classes
1
star
42

git_toturial

1
star