Coding Standard PHP

General Points

  1. Write permission must be only given to those directories which require that permission. For example: A directory which contains the user uploaded files or the generated csv etc.
  2. The files which are not required on the git should be added into the .gitignore file e.g. vendor directory of Laravel, upload directory. 
  3. The files which contains the sensitive information like configuration file should be added in the .gitignore file. 
  4. Allow use of stable versions of PHP, Nodejs, MySQL, MongoDB, or framework, etc.
  5. The naming conventions must be taken care of. For example saving the file names with the proper name, using the appropriate variable names, etc.
    1. ClassName
    2. methodName
    3. propertyName
    4. function_name (meant for global functions)
    5. $variable_name
    6. CONSTANT
    7. file_name.extension
  1. Never share login credentials on chat messages for any environment. Always send the username and password separately in two separate emails. 
  2. The response must have the proper HTTP Status Code. For example, An successful response is detected by the 200 status code, a bad request is represented by the 400 status code, 401 is the proper response code to send when a failed login has happened, and similarly 403 forbidden requests if access is not provided even after successful login, etc.
  3. All Web applications must have the proper error page. For example, 404 not found page, 400 bad request page, 500 internal server error page, etc
  4. All the web applications which are in the production environment must have the debug mode off.
  5. All the logs which are being written must be cleared after a specific time span say 7 days.
  6. When the project is in production then debug mode should be ON for only critical level errors.
  7. All the web application labels, and error messages must be coded in the multilingual way even if the web application is in one language. This means all user messages, alert messages and error messages have to be taken from the language files even though your project is not multilingual.

For example: Use the laravel function __(“Message”) to return the message. In future when we need to make it multilingual then we just need to make a json file in resources/lang/xx.json having the key as an English message and value as Translated Message:

“Message” : “Translated message”.

  1. All the web applications must have to gzip compression enabled from the .htaccess. This can be done by enabling the “deflate” mode of apache.

<IfModule mod_deflate.c>
  # Compress HTML, CSS, JavaScript, Text, XML and fonts
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
  AddOutputFilterByType DEFLATE application/x-font
  AddOutputFilterByType DEFLATE application/x-font-opentype
  AddOutputFilterByType DEFLATE application/x-font-otf
  AddOutputFilterByType DEFLATE application/x-font-truetype
  AddOutputFilterByType DEFLATE application/x-font-ttf
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE font/opentype
  AddOutputFilterByType DEFLATE font/otf
  AddOutputFilterByType DEFLATE font/ttf
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE image/x-icon
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/xml

  # Remove browser bugs (only needed for really old browsers)
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4\.0[678] no-gzip
  BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
  Header append Vary User-Agent
</IfModule>

  1. All web applications must have compressed images, minified javascript, and minified CSS.
  2. The web application should achieve an A grade on the GT METRIX.
  3. Variables should be of proper data type like int, float, bool, array, etc.
  4. The classes and the functions must have proper comments. For example: http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_phpDocumentor.quickstart.pkg.html
  5. Do not use the name in the comments.
  6. Package usage: 

1. If you need to log in to the 3rd party sites, then do not use personal credentials.

2. When going live, then use the client credentials.

3. Before usage of any 3rd party tool, then consult with the team first. 

  1. Do not directly make the changes in the 3rd party core files. If required, then extend it.
  2. Use a common function to render the dates.
  3. All the transactions which are related to the payments must have been logged.
  4. Front-end validations should be implemented but server-side validations must be implemented.
  5. Use the latest Admin WEB portal provided by the team.
  6. If we are using PHP 7 then the code should be written in PHP 7 standard.
  7. Without proper analysis, do not publish the build.
  8. .git folder should not be accessible through the browser.
  9. Testing and development environments should not be crawled over search engines.
  10. Important:- Time in the application should be saved in UTC and show on the application according to user timezone.

Standards Reference

  1. http://pear.php.net/manual/en/standards.php
  2. https://framework.zend.com/manual/1.12/en/coding-standard.coding-style.html

Laravel Installation

  1. After installing Laravel, you may need to configure some permissions. Directories within the storage and the bootstrap/cache directories should be writable only.
  2. All the configurations like database, mail, queue, etc must be done in the env file.
  3. Do not move the index.php and .htaccess outside of the public directory, instead of doing that point to the web server document root public directory.
  4. If we have some common code then we can must include that in separate files i.e Repositories.

Routing

  1. All the routes should be placed in the proper files i.e API routes in the routes/api.php and web routes in the routes/web.php.

routes/api.php

<?php

Route::group([‘namespace’ => ‘Api’], function() {

// Auth routes

Route::post(‘login’,  ‘AuthController@Login);

});

?>

routes/web.php

<?php

Route::group([‘namespace’ =>’Auth’], function() {

// Auth routes

Route::post(‘login’,  ‘AuthController@Login)->name(‘user.login’);

});

?>

  1. When defining the routes, use the proper request method. For example, when the record(s) is fetched then the method should be getting, when the record(s) is saved then the post method should be used, when the record(s) are updated then put method must be used and when the record(s) is being deleted then delete method should be used.
  2. Try to avoid using the patch method, because it gives errors on some firewall networks.
  3. If our method only returns a view, then we can use the view route option.
  4. If we are performing a CRUD operation, then we must define a resource route for it.
  5. We can group the routes under the same namespace instead of giving the full name of the controller with the namespace.
  6. We must give a name to the route and use that name whenever we need to use that route. 

Migrations

  1. Use the migrations to make the tables and all the other changes to the tables.

For example: php artisan make:migration create_users_table

  1. Give the proper name to the tables.
  2. Use the foreign key constraints between the related tables.
  3. Give the proper data type for the fields, assign default value as required and mark the integers as unsigned if they do not contain the negative values.
  4. Direct changes in the database are not allowed by using the phpMyAdmin or any other tool.

Seeding

  1. Admin entry must be created using the Database seeder.

For example: php artisan make:seed User

  1. All the master data which is required by the app, must have an seed.

Models

  1. Create Models for the tables and store them in the Models directory.

For example: php artisan make:model Models/User

  1. Use the Model scopes to specify the common where conditions, so that we can easily update them if any change is required.

For example:

public function scopePopular($query)

{

return $query->where(‘votes’, ‘>’, 100);

}

Using the scopes:

$posts = Post::Popular()->get();

  1. Use the Eager loading (with() method) to fetch the related table.

For example: We are listing the posts created by the different users then to load the posts with the user.

Way 1: $posts = Post::with(‘users’)->get();

Instead of using

Way 2: $posts = Post::get();

And then display the post with user:

foreach($posts as $post) {

echo $post->user->name;

}

If we use the Way 1, then there will be only two database queries but in Way 2 there will be n+1 database queries where n is number of posts.

  1. Do not use the Model relationship dynamic properties as they make a database query whenever they are used.
  2. Use the mutator/accessor as required.
  3. Define all the date columns in the Model $dates property.
  4. If you have already fetched the data and want to fetch its related data then use the lazy Eager loading (load() method).
  5. Select only those fields which are used in the results to increase the performance.
  6. Please return the value from the database with proper typecasting.
  7. Pagination must be used when fetching the data.
  8. When using the raw queries, pass the value in the parameters. Do not pass the value directly.

Middleware

  1. Use the middleware only when required and group the middleware based on the user roles and place them in separate directories.
  2. Use the default middleware for the guest users instead of making a new middleware for the same purpose. 
  3. Use the command to create the middleware instead of copy paste the file.

Controllers

  1. Use the command to create the controller.
  2. Store the controller to separate directories as per the portal.

For example: php artisan make:controller Admin/Auth

  1. Use the resource controller when making an CRUD operation.
  2. Controller names must be suffixed Controller.
  3. First letter of the controller must be Capital letter.
  4. Dependency injection must be used instead of creating the object in the controller methods.

Views

  1. Create the views in the directory which they belong.
  2. Use the blade directives in the views such as @if, @else.
  3. Stop using the the PHP blocks in the blade like <?php …. ?>.
  4. Add the css and js section in the header and footer blade respectively.
  5. Use the Form collective package to make the form and its inputs.
  6. If displaying the data inputted from the user, then it must be escaped to prevent form the XSS attack. Always use the {{ }} blade directives.

Requests

  1. When retrieving the input from the request, use the input() method.
  2. Instead of using the isset() & empty() function to check value in the input, use the filled() method of the request object.
  3. Do not use the request object dynamic properties.

Use $request->input(‘name’) instead of $request->name. When using the $request->name may throw an exception, if the name is not present in the request.

Response

  1. Use the response() helper function to return the response if we are not returning the view in the response.
  2. If the file is being returned, then proper header must be there.

Session

  1. Use the memcached as session/cache driver to increase the performance.

Validations

  1. Use the form requests to add the validations for the inputs.

For example: php artisan make:request Admin/Posts/Add

public function rules()

  {

return [

 ‘id’ => [‘bail’,’integer’,’required’,Rule::exists(‘users’)->where(function($query) {

$query->where(‘role’, 2)->where(‘status’, 1);

})]

];

  }

  1. If we need an custom validation rule, then create the rules from the command instead of making own custom class and extending the validator

For example: php artisan make:rule Admin/Posts/XX

  1. Use the bail rule to stop the rule checking for other rules if the first rule fails.
  2. Create the form request from the command only and store them properly according to the needs.

Errors and Logging

  1. Turn off the debugging mode when the system is in production environment.
  2. Change the log setting to log the errors on daily basis and specify the number of days for how many days we need to keep the logs.
  3. Change the log level to error.
  4. Use the app/Exceptions/Handler.php to handle the exceptions instead of using the try and catch blocks in every method.

Queues

  1. Use the queues to send mails, and notifications and to perform tasks which takes time and does not need user interaction.
  2. Create the jobs using the command and use them as required.

For example: php artisan make:job SendPushNotiifcationJob

  1. All the queue jobs/mails classes must have an public property name $tries with an integer value.
  2. Use the supervisor to initiate the queue:listen command instead of using the nohup or any other way to run it in the background.

Mail

  1. Create the mails using the artisan command and store the emails to the related directory.

For example: php artisan make:mail User/WelcomeMail

  1. All the mails must implement the ShouldQueue interface to send them in the background.
  2. All the emails or the classes which implement the ShouldQueue interface must have a public property name $tries with an integer value.

Task Scheduling (Cron-job)

  1. We must use the Laravel scheduler to schedule the tasks. To start the scheduler, add the following cron job:

    * * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
  1. We can use the scheduler to perform all the tasks which are done by the cron job.

API

  1. Specify your all APIs with standard endpoints(URL).
  2. The action have to be identified by the method you are making a request to any endpoint.
  3. Use the request method as per the action done by the API.
  4. Use the HTTP Status codes to return the success or failures of the API response.
  5. Use the JWT AUTH for the API authentication.
  6. Specify the token lifetime to 2-3 years or as per the requirement/type of the project.
  7. Do not send the extra data in the API, it will slow down the API.
  8. Get only those parameters/input which need to be updated in the database.
  9. When updating the user’s table or any other table which contains sensitive information and we are using the $request->all() method then except those fields from the request which stores the sensitive information.
  10. All the API’s must have the proper server side validations.

Security

  1. Never use direct <?php to print any value from database.always use blade directives {{}}.
  2. Your file source code should not be downloadable in any possible way.
  3. Use the .htaccess Option -Index option to make files non indexable.
  4. Add the Allowed FileHandler in the .htaccess and place it in the directory where the user files are being uploaded.

<Files .htaccess>

order allow,deny

deny from all

</Files>

AddType application/octet-stream .csv

AddType application/octet-stream .xls

AddType application/octet-stream .doc

AddType application/octet-stream .avi

AddType application/octet-stream .mpg

AddType application/octet-stream .mov

AddType application/octet-stream .pdf

AddType application/octet-stream .jpg

AddType application/octet-stream .jpeg

AddType application/octet-stream .gif

AddType application/octet-stream .3gp

AddType application/octet-stream .mp4

AddType application/octet-stream .txt

RemoveType .pl .cgi .php .php3 .php4 .php5 .xml .phtml .phtm .html .htm .wml .shtm .shtml .asp

RemoveHandler .pl .cgi .php .php3 .php4 .php5 .xml .phtml .phtm .html .htm .wml .shtm .shtml .asp

php_flag engine off

Options -Indexes

  1. A good rule of thumb is to set your permissions as follows:
    1. Folders and directories = 755
    2. Individual files = 644
  2. All the versions must be up to date.
  3. The files which contain sensitive information, must not be directly accessed.
  4. When the beta version is released, then make it password protected.
  5. All the Forms which are being submitted by the guest users should have a captcha field with them.

By admin

I'm Software developers who build web applications and convert your idea into the world wide web.

Leave a Reply