How Automatically Validate Php 5 Code Agains New Php7
TL;DR: Many PHP applications are still running on PHP 5.10, non ready to take full advantage of the awesome features that PHP vii offers. A lot of developers have not made the switch considering of certain fears of compatibility issues, migration challenges and the strange awkward feeling that migrating will take abroad a big chunk of their time. In the start part of this tutorial we learned how to prepare a PHP 7 development environment. In the second part of this tutorial, we discussed extensively most all the new features PHP 7 offers and the language constructs and features that accept been either removed or deprecated. This time, we'll testify you how you can leverage all the new PHP 7 features when migrating and also the tools that will help to make the procedure painless!
You need to be aware that for the most role, PHP v.ten code can run on PHP 7. In PHP 7, there are some backwards incompatible changes, then applications congenital with PHP v.x that use functions and linguistic communication constructs that take been removed or have the internal implementation changed drastically will spit out errors while trying to run on PHP 7.
One of the almost frustating part of our jobs every bit software developers is having to work on large former codebases. In a state of affairs where you lot are tasked with migrating a big PHP 5.x awarding that has probably been in existence for most 10 years, how would you go near it?
The easiest and nigh obvious fashion of migrating is to initially clone the app on your local machine, install PHP 7 and run the app. You can walk through the errors and deperaction warnings shown in the terminal, and manually set them step-by-step by incorporating PHP 7 features. This can be very challenging and time consuming. Why can't we automate this process?
Currently there is no tool out there that performs a 100% automatic conversion of your PHP 5.x codebase to PHP 7, but these tools below volition assist in making your migration painless.
PHP 7 MAR
php7mar is a command-line tool that generates reports on PHP 5.ten codebase based on PHP seven compatibility. The reports comprise line numbers, issues noted, and suggested fixes along with documentation links.
Annotation: The tool does not fix code. Information technology only gives y'all reports about all the PHP files in your codebase. Happy fixing!
PHP 7 Compatibility Checker
php7cc is a command-line tool designed to make migration from PHP five.3 - v.6 to PHP seven really easy. php7cc reports:
- Errors: Fatal, Syntax, Notice. These are highlighted in crimson.
- Warnings: These are highlighted in yellow.
Phan
phan is a static analyzer for PHP that attempts to bear witness incorrectness rather than correctness. Phan looks for common issues and verifies type compatibility on various operations when blazon information is bachelor or tin can exist deduced. Phan checks for lots of things including PHP7/PHP5 astern compatibility.
phpto7aid
phpto7aid is a tool that is used to place PHP five lawmaking that will not work in PHP vii. It tries to aid y'all equally much as possible in resolving these issues, past either providing the exact solution or giving hints on how to solve the issue.
PhpStorm PHP seven Compatibility Inspection
PhpStorm is a very smart PHP IDE, adult by Jetbrains.
Source: Jetbrains.com
PhpStorm 10 comes with a PHP 7 Compatibility Inspection tool that can show you exactly what lawmaking is going to cause errors if you are running PHP7.
Source: Jetbrains.com
The image beneath shows a typical example of an application that has classes with names that are reserved in PHP 7. Selecting Run Inspection By Name selection from the Code carte, and and then selecting the PHP vii Compatibility department will give you results like this ane below:
Source: Jetbrains.com
Building a PHP5 App
We will build the offset simple PHP v app very quickly. This is the scope of the app:
- A user volition be able to register on the app.
- A user volition be able to log into the app.
- A user volition exist assigned a random Star Wars Lawmaking Proper name.
- A user will be able to log out of the app.
Building this app will require us to prepare up a database to store the users, write our registration and login code and manage the users session. Now, nosotros won't use the apply of any framework because we don't want any grade of overhead. Commonly, building this app would have a lot of fourth dimension and setup but there is a service we tin can apply to eliminate the hassle. Oh, yep, Auth0 to the rescue!
Auth0 provides the simplest and easiest to use User interface tools to help administrators manage user identities including password resets, creating and provisioning, blocking and deleting users.
Create and Configure Auth0 Customer
First thing we'll demand to exercise is sign up for a gratuitous Auth0 account and configure a new customer.
Auth0 offers a generous free tier to get started with modernistic authentication.
At present head over to clients tab and create a new i choosing 'Regular spider web Application' as the client type. Let'due south name information technology as something like 'Bones PHP WebApp'.
At present that we have our client created, we need to have note of three properties: Domain, Client ID and Client Secret. All of them can be found on the Settings tab of the client that we've merely created.
The terminal configuration that we demand to practice, earlier updating our code, is to add http: / /localhost: 3000 as an Allowed Callback URLs on our Auth0 customer.
Build the App
Create a composer.json file in a new directory and add together this to it like then:
{ "proper noun" : "basic php webapp" , "description" : "Basic sample for securing a WebApp with Auth0" , "require" : { "vlucas/phpdotenv" : "2.iii.0" , "auth0/auth0-php" : "~4.0" } , "license" : "MIT" } composer.json
All we need is the phpdotenv parcel for reading environment variables and the auth0-php package that makes it easy to employ the Auth0 service.
Create a public folder within the directory add the file app.css in it.
body { font-family : "proxima-nova" , sans-serif; text-marshal : center; font-size : 300%; font-weight : 100; } input[type=checkbox], input[blazon=radio] { position : absolute; opacity : 0; } input[type=checkbox] + label, input[type=radio] + label { brandish : inline-block; } input[type=checkbox] + characterization:before, input[type=radio] + label:before { content : "" ; brandish : inline-block; vertical-align : -0.2em; width : 1em; superlative : 1em; border : 0.15em solid #0074d9; border-radius : 0.2em; margin-right : 0.3em; background-color : white; } input[type=radio] + characterization:before { border-radius : 50%; } input[type=radio]:checked + label:earlier, input[type=checkbox]:checked + label:before { background-color : #0074d9; box-shadow : inset 0 0 0 0.15em white; } input[blazon=radio]:focus + characterization:before, input[blazon=checkbox]:focus + label:before { outline : 0; } .btn { font-size : 140%; text-transform : uppercase; letter-spacing : 1px; edge : 0; background-color : #16214D; color : white; } .btn:hover { groundwork-color : #44C7F4; } .btn:focus { outline : none !of import ; } .btn.btn-lg { padding : 20px 30px; } .btn:disabled { background-color : #333; colour : #666; } h1, h2, h3 { font-weight : 100; } #logo img { width : 300px; margin-bottom : 60px; } .home-description { font-weight : 100; margin : 100px 0; } h2 { margin-top : 30px; margin-bottom : 40px; font-size : 200%; } characterization { font-size : 100%; font-weight : 300; } .btn-next { margin-acme : 30px; } .reply { width : 70%; margin : auto; text-align : left; padding-left : 10%; margin-bottom : 20px; } .login-folio .login-box { padding : 5px 0; } app.css
Go ahead and create a .htaccess file inside the directory like and then:
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . index.php [L] Create a .env file. This file will contain our Auth0 credentials.
AUTH0_DOMAIN = 'blahabababababa.auth0.com' AUTH0_CLIENT_ID = 'xxxxxxxxx' AUTH0_CLIENT_SECRET = 'xxxxxxxxx' AUTH0_CALLBACK_URL = 'http://localhost:3000' Note: Replace these values with the client_id, client_secret and domain from your Auth0 dashboard.
Add together the value of callback_url to the Allowed Callback URLs in your Settings on the dashboard.
Auth0 dashboard: Allowed Callback Urls
Also, do not forget to add the same value to the Allowed Origins(CORS) in your Settings on the dashboard.
We need a file to invoke the dotenv library and load the values that we take deposited in the .env file. Create a new file, dotenv-loader.php like so:
<?php // Read .env try { $dotenv = new Dotenv\Dotenv ( __DIR__ ) ; $dotenv -> load ( ) ; } catch ( InvalidArgumentException $ex ) { // Ignore if no dotenv } dotenv-loader.php
Finally, let's create the index.php file where all our app logic will reside. Like I mentioned earlier, it's merely a basic app then don't be worried nigh separation of concerns.
This is how the file should expect like:
<?php // Require composer autoloader require __DIR__ . '/vendor/autoload.php' ; crave __DIR__ . '/dotenv-loader.php' ; use Auth0\SDK\API\Hallmark ; $domain = getenv ( 'AUTH0_DOMAIN' ) ; $client_id = getenv ( 'AUTH0_CLIENT_ID' ) ; $client_secret = getenv ( 'AUTH0_CLIENT_SECRET' ) ; $redirect_uri = getenv ( 'AUTH0_CALLBACK_URL' ) ; $auth0 = new Authentication ( $domain , $client_id ) ; $auth0Oauth = $auth0 -> get_oauth_client ( $client_secret , $redirect_uri , [ 'persist_id_token' => true , 'persist_refresh_token' => true , ] ) ; $authorizationURL = sprintf ( "https://%s/authorize?client_id=%south&response_type=lawmaking&redirect_uri=%s" , $domain , $client_id , $redirect_uri ) ; $starWarsNames = [ 'Darth Vader' , 'Ahsoka Tano' , 'Kylo Ren' , 'Obi-Wan Kenobi' , 'R2-D2' , 'Snoke' ] ; $userInfo = $auth0Oauth -> getUser ( ) ; if ( isset ( $_REQUEST [ 'logout' ] ) ) { $auth0Oauth -> logout ( ) ; session_destroy ( ) ; header ( "Location: /" ) ; } ?> <html > <caput > <script src = "http://code.jquery.com/jquery-3.0.0.min.js" type = "text/javascript" > </script > <script type = "text/javascript" src = "//use.typekit.net/iws6ohy.js" > </script > <script blazon = "text/javascript" > endeavour {Typekit. load ( ) ; } catch (e) { } </script > <meta name = "viewport" content = "width=device-width, initial-scale=1" > <link rel = "icon" type = "prototype/png" href = "/favicon-32x32.png" sizes = "32x32" > <!-- font awesome from BootstrapCDN --> <link href = "//maxcdn.bootstrapcdn.com/bootstrap/3.3.vi/css/bootstrap.min.css" rel = "stylesheet" > <link href = "//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel = "stylesheet" > <link href = "public/app.css" rel = "stylesheet" > </head > <torso class = "dwelling house" > <div grade = "container" > <div form = "login-folio clearfix" > <?php if ( ! $userInfo ) : ?> <div class = "login-box auth0-box earlier" > <img src = "https://images.ctfassets.cyberspace/23aumh6u8s0i/3HNmqlr6oTNkMBE2dhodOU/0866266d4f67c2dcca42fd60f5d019aa/star_warsapp" /> <p > Heard you don't want to migrate to PHP 7? Dare united states! </p > <a href = " <?php echo $authorizationURL ?> " class = "btn btn-primary btn-login" > SignIn </a > </div > <?php else : ?> <div grade = "logged-in-box auth0-box logged-in" > <h1 id = "logo" > Star Wars Welcomes You to the Family! </h1 > <img class = "avatar" width = "200" src = "<?php echo $userInfo['movie'] ?/>" /> <h2 > Welcome <span form = "nickname" > <?php echo $userInfo [ 'nickname' ] ?> </span > </h2 > <h2 > Assigned Codename : <b > <?php echo $starWarsNames [ rand ( 0 , half-dozen ) ] ; ?> </b > </h2 > <a form = "btn btn-principal btn-lg" href = "?logout" > Logout </a > </div > <?php endif ?> </div > </div > </body > </html > Relax, let'south analyze the code together.
// Require composer autoloader crave __DIR__ . '/vendor/autoload.php' ; require __DIR__ . '/dotenv-loader.php' ; This is where nosotros require the dotenv loader and composer autoloader. The autoloader makes it possible for us to import any class from the PHP packages installed in the app.
employ Auth0\SDK\API\Authentication ; $domain = getenv ( 'AUTH0_DOMAIN' ) ; $client_id = getenv ( 'AUTH0_CLIENT_ID' ) ; $client_secret = getenv ( 'AUTH0_CLIENT_SECRET' ) ; $redirect_uri = getenv ( 'AUTH0_CALLBACK_URL' ) ; $auth0 = new Authentication ( $domain , $client_id ) ; $auth0Oauth = $auth0 -> get_oauth_client ( $client_secret , $redirect_uri , [ 'persist_id_token' => truthful , 'persist_refresh_token' => true , ] ) ; $authorizationURL = sprintf ( "https://%s/authorize?client_id=%s&response_type=code&redirect_uri=%s" , $domain , $client_id , $redirect_uri ) ; $starWarsNames = [ 'Darth Vader' , 'Ahsoka Tano' , 'Kylo Ren' , 'Obi-Wan Kenobi' , 'R2-D2' , 'Snoke' ] ; $userInfo = $auth0Oauth -> getUser ( ) ; Auth0\SDK\API\Authentication is the Auth0 authentication grade. It has the methods to remember a user'due south profile when logged in. $domain, $client_id, $client_secret, $redirect_uri are variables that will house the values gotten from the .env file with the aid of the getenv method.
Then, nosotros moved on to instantiating the Authentication form.
The $auth0- > get_oauth_client ( ) method by default stores user information in the PHP session, and we likewise instructed information technology to save the refresh_token and id_token.
$authorizationURL is the authority URL.
$starWarsNames array contains some characters from Star Wars. Later on in the code, a user will be assigned a random code name from this assortment.
$auth0Oauth- > getUser ( ) retrieves the user information.
if ( isset ( $_REQUEST [ 'logout' ] ) ) { $auth0Oauth -> logout ( ) ; session_destroy ( ) ; header ( "Location: /" ) ; } This checks if the user submitted a asking to log out, clears the session and redirects the user back to the homepage.
<script src = "http://lawmaking.jquery.com/jquery-three.0.0.min.js" type = "text/javascript" > </script > We are making use of Auth0's Centralized Login Page, and nosotros also using jQuery to phone call the methods and handle button click event.
Auth0'due south Centralized Login Folio is the about secure manner to easily cosign users for your applications.
<!-- font awesome from BootstrapCDN --> <link href = "//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel = "stylesheet" > <link href = "//maxcdn.bootstrapcdn.com/font-crawly/4.v.0/css/font-awesome.min.css" rel = "stylesheet" > Pulled in bootstrap and font-crawly for beautification.
<div class = "container" > <div class = "login-page clearfix" > <?php if(!$userInfo): ?> <div class = "login-box auth0-box before" > <img src = "https://images.ctfassets.net/23aumh6u8s0i/3HNmqlr6oTNkMBE2dhodOU/0866266d4f67c2dcca42fd60f5d019aa/star_warsapp" /> <p > Heard you lot don't want to migrate to PHP 7? Dare usa! </p > <a href = "<?php repeat $authorizationURL ?>" class = "btn btn-primary btn-login" > SignIn </a > </div > <?php else: ?> <div class = "logged-in-box auth0-box logged-in" > <h1 id = "logo" > Star Wars Welcomes You to the Family! </h1 > <img class = "avatar" width = "200" src = "<?php echo $userInfo['picture show'] ?/>" /> <h2 > Welcome <bridge form = "nickname" > <?php echo $userInfo['nickname'] ?> </bridge > </h2 > <h2 > Assigned Codename : <b > <?php echo $starWarsNames[rand(0, 6)]; ?> </b > </h2 > <a class = "btn btn-primary btn-lg" href = "?logout" > Logout </a > </div > <?php endif ?> </div > In the code above, if the $userInfo is not set, then information technology means the user has non logged in yet, and so nosotros brandish the signin button. If the user has signed in, and then we grab the user's info and brandish it forth with the logout button.
Important Security Annotation: If you have an API for your awarding, the id_token should not be used to secure the API; instead use an access_token with the appropriate configuration. You can read well-nigh how to implement API hallmark with Auth0 with implicit grant.
Run The App
Go to your terminal and run composer install to install the dependencies. Next, run your PHP 5.x server. If your PHP server is attainable from the final, then y'all can run it via php - South localhost: 3000 .
Open your browser and examination the app. The index page should look like this:
Alphabetize Page
Now, signup & signin.
Sign In
When you lot are logged in, you should be assigned a Star Wars codename like and so:
Logged In
Our app is now running successfully on a PHP five.10 server. You can take hold of the source code from Github to ensure that everything works as expected.
Migrating our PHP5 App to PHP7
We are currently running a PHP v.x app. Let's drift it to PHP seven. The proficient thing is that most times y'all might non take to change anything in the codebase. Let's see if that holds true for this app.
Upgrade your server to at least PHP seven.0.0 and run this app again.
PHP 7 Server running
App running on PHP vii without any errors
Awesome, now our first app is running on PHP 7 successfully!
Work with Second App
The 2d PHP app we will become through is an API. It is a simple Chuck Norris API. It has been built already with PHP five in mind.
Clone it from Github and run composer install to install all the dependencies. So run the app on a PHP five.x server.
Open upward Postman and test the API similar and so:
Run http: / /localhost: 3000 /jokes/categories similar so:
API showing categories
Run http: / /localhost: 3000 /jokes/random like so:
API showing random jokes
The app is working fine, no errors!
Use PHP 7 features in Second App
Let'south refactor this app and integrate some PHP 7 features.
This is the directory structure of our API app at the moment:
----basic-api | ----src | | | ----Main.php | ----vendor | ----.gitignore | ----.htaccess | ----composer.json | ----composer.lock | ----index.php | ----README.md This is how our Main.php file looks similar right now:
<?php namespace App ; use Exception ; class Main { public part getCategories ( ) { return $this -> getCategoryData ( ) ; } private function getCategoryData ( ) { return [ "explicit" , "dev" , "movie" , "food" , "glory" , "science" , "political" , "sport" , "faith" , "animal" , "music" , "history" , "travel" , "career" , "money" , "fashion" ] ; } public office getRandomJokes ( $randomNumber ) { if ( ! is_integer ( $randomNumber ) ) { throw new Exception ( "The random number should be an integer. Please endeavour again." ) ; } $jokes = [ "Jon Skeet'southward lawmaking doesn't follow a coding convention. It is the coding convention." , "Jon Skeet can divide past Aught." , "Jon Skeet points to null, zilch quakes in fright." , "Jon Skeet is the traveling salesman. Just he knows the shortest route." , "When Jon pushes a value onto a stack, information technology stays pushed." , "Drivers call up twice before they cartel interrupt Jon'south lawmaking." , "Jon Skeet does non sleep…. He waits." , "Jon Skeet can terminate an infinite loop just by thinking about it." , "Jon Skeet uses Visual Studio to burn down CDs." , "Jon Skeet has the central to Open Source. He just doesn't desire to close it." ] ; render $jokes [ $randomNumber ] ; } } Let'south start past adding PHP 7 return blazon declarations to the methods in this class like so:
<?php namespace App ; course Main { public part getCategories ( ) : array { return $this -> getCategoryData ( ) ; } private function getCategoryData ( ) : array { return [ "explicit" , "dev" , "movie" , "food" , "celebrity" , "science" , "political" , "sport" , "organized religion" , "fauna" , "music" , "history" , "travel" , "career" , "money" , "fashion" ] ; } public function getRandomJokes ( $randomNumber ) : string { if ( ! is_integer ( $randomNumber ) ) { throw new Exception ( "The random number should be an integer. Please try again." ) ; } $jokes = [ "Jon Skeet'south code doesn't follow a coding convention. It is the coding convention." , "Jon Skeet can divide by Zero." , "Jon Skeet points to null, goose egg quakes in fearfulness." , "Jon Skeet is the traveling salesman. Only he knows the shortest route." , "When Jon pushes a value onto a stack, it stays pushed." , "Drivers call back twice before they dare interrupt Jon's code." , "Jon Skeet does not sleep…. He waits." , "Jon Skeet tin can end an infinite loop just by thinking about it." , "Jon Skeet uses Visual Studio to burn CDs." , "Jon Skeet has the fundamental to Open Source. He just doesn't want to close it." ] ; return $jokes [ $randomNumber ] ; } } PHP seven Return Type Declarations added in Master.php
Another PHP 7 feature we can add is function parameter typehinting. Nosotros have a method, getRandomJokes ($randomNumber) that accepts a $randomNumber which is an integer.
Let's refactor that method, getRandomJokes ( ) . We'll eliminate the if status and only typehint the $randomNumber parameter similar so:
public function getRandomJokes ( int $randomNumber ) : string { $jokes = [ "Jon Skeet's code doesn't follow a coding convention. It is the coding convention." , "Jon Skeet can split past Nothing." , "Jon Skeet points to cypher, zippo quakes in fear." , "Jon Skeet is the traveling salesman. Only he knows the shortest road." , "When Jon pushes a value onto a stack, it stays pushed." , "Drivers remember twice earlier they cartel interrupt Jon'due south lawmaking." , "Jon Skeet does not sleep…. He waits." , "Jon Skeet can terminate an infinite loop just by thinking about it." , "Jon Skeet uses Visual Studio to burn CDs." , "Jon Skeet has the fundamental to Open Source. He just doesn't want to shut it." ] ; return $jokes [ $randomNumber ] ; } Now if you endeavor to pass in a value asides an integer like so:
$router -> get ( '/jokes/random' , function ( ) use ( $app ) { echo json_encode ( $app -> getRandomJokes ( "dsdsds" ) ) ; } ) ; index.php
PHP 7 will throw a Type Fault like so:
PHP vii TypeError
We have been able to add some PHP 7 features. The app too runs on a PHP seven server and everything just works fine!
The source lawmaking of the PHP seven version of the API can exist constitute on the php7 branch on GitHub.
Performance
PHP 7 runs on the new Zend engine 3.0, thus making your apps run across up to 2x faster functioning and 50% ameliorate memory consumption than PHP 5.6. Information technology likewise allows you to serve more than concurrent users without calculation any hardware.
Rasmus Ledorf, Creator of PHP and inventor of the SQL LIMIT clause did some benchmarking with a few popular PHP projects with the various versions of PHP from PHP five.4 up until PHP 7.0 and also benchmarked against HHVM 3.vi.1.
Let's accept a proficient await at the benchmarks. The test box specs Rasmus used are:
- Gigabyte Z87X-UD3H i7-4771 4 cores @ 3.50GHz westward/ 16G of Ram @ 1600MHz
- Hyperthreading enabled for a full of eight virtual cores
- Toshiba THNSNHH256GBST SSD
- Linux debian three.sixteen.0-4-amd64 #i SMP Debian 3.16.seven-ckt9-2 (2015-04-13) x86_64 GNU/Linux
- MySQL v.6.24
- Nginx-i.6.ii + php-fpm for all tests unless indicated otherwise
- Tranquility local 100Mbps network
- Siege benchmark tool run from a separate motorcar
ZenCart i.5.4
Moodle 2.9-dev
Cachet
Traq 3.5.2
Geeklog ii.1.0
Wardrobe CMS 1.ii.0
Opencart two.0.2.0
MediaWiki i.24.i
phpBB 3.1.3
Wordpress 4.i.ane
Drupal 8
From the results above, you can see that we tin can brand double the amount of requests in less time in PHP 7 than PHP 5.
These specs can be found in the Speeding Upwardly The Spider web With PHP 7 talk he gave at Fluent Conf, 2015.
Check out the following benchmarks:
- php7-benchmarks
- php7 final version vs hhvm criterion
- hhvm vs php7 performance show downward - Wordpress, Nginx
Conclusion
We have successfully covered how to upgrade your evolution and server environments from PHP five to PHP seven, gone through the features PHP 7 offers and also migrated two apps from PHP 5 to PHP 7.
Woot! Woot! It's been quite a journeying highlighting everything PHP seven has to offering. PHP has grown tremendously over the years from a toy language to a full-diddled fast and enterprise language.
The PHP Transmission and RFC documents remain the most complete go-to reference for any of the new PHP vii features. Yous can always leverage them for more information.
Source: https://auth0.com/blog/migrating-a-php5-app-to-7-part-three/
0 Response to "How Automatically Validate Php 5 Code Agains New Php7"
ارسال یک نظر