What will you be able to do? Goal: Write safer, faster and more robust PHP code
Agenda 1. Coding Style 2. Coding Practices 3. Security 4. Errors and Exceptions
Coding Style - Namespaces • Huge PHP community = lots of code • If 2 libraries share same class name = oh oh, troubles… • Namespaces are similar to “OS directories”, – 2 files with same name can co-exist in separate directories – 2 classes with same name can co-exist in separate PHP namespaces
Coding Style - Namespaces - Ex Code example
Coding Style - PSR-X • PSR = PHP Standards Recommendations • Coding style followed by most frameworks and latest libraries. • Ex PSR-2 https://github.com/php-fig/fig- standards/blob/master/accepted/PSR-2-coding-style- guide.md
Coding Practices • DRY code ( Don’t Repeat Yourself) – Create functions and reuse them whenever you have code very similar in different parts of your applications • Use Object Oriented Programming whenever possible – Create classes to run your business logic (1 class per file if possible)
Coding Practices • Separate template code from business logic – Your template files should only load and display data, no processing – Your class files should not start/run themselves and should not directly display content (your methods can)
Security • Input Validation • SQL Injection
Security - Input Validation • Never trust user input • Always test if an input or variable exist – isset($variable) = test if variable is not NULL – empty($array) = test if array is empty • Then filter that input to make sure you receive what you expected – filter_var (for any kind of variables) – filter_input (for form inputs)
Security - Input Validation
Security - Input Validation
Security - SQL Injection
Security - SQL Injection • Use PDO prepare statements (Laravel Eloquent uses it by default and Wordpress has its own prepare statements
Errors & Exceptions - Errors • PHP is an “exception-light” programming language. • Unless a “fatal error” occurs, most of PHP will try to keep processing • 3 types of error severity: • E_ERROR,E_NOTICE, and E_WARNING
Errors & Exception - ErrorException Class • Throw your “errors” as “exceptions” using the ErrorException class, which extends the Exception class. • Common practice for several frameworks (Laravel, Symphony, etc.) • Allow to handle errors better than the usual result by “catching” exceptions
Errors & Exceptions - Exceptions • Exceptions are often overlooked by PHP programmers. • Some old PHP frameworks returns “false” or “Warning” when something goes wrong. – You have to dig in the doc and reread the code to find what’s wrong
Errors & Exceptions - Exceptions
You Do Each of you will apply the techniques we learned today to optimize/secure/clean your previous projects. Make sure to version your previous code before making any changes so I can see the progression
Resources • http://www.phptherightway.com/
Programming best practices (PHP)

Programming best practices (PHP)

  • 2.
    What will yoube able to do? Goal: Write safer, faster and more robust PHP code
  • 3.
    Agenda 1. Coding Style 2.Coding Practices 3. Security 4. Errors and Exceptions
  • 4.
    Coding Style -Namespaces • Huge PHP community = lots of code • If 2 libraries share same class name = oh oh, troubles… • Namespaces are similar to “OS directories”, – 2 files with same name can co-exist in separate directories – 2 classes with same name can co-exist in separate PHP namespaces
  • 5.
    Coding Style -Namespaces - Ex Code example
  • 6.
    Coding Style -PSR-X • PSR = PHP Standards Recommendations • Coding style followed by most frameworks and latest libraries. • Ex PSR-2 https://github.com/php-fig/fig- standards/blob/master/accepted/PSR-2-coding-style- guide.md
  • 7.
    Coding Practices • DRYcode ( Don’t Repeat Yourself) – Create functions and reuse them whenever you have code very similar in different parts of your applications • Use Object Oriented Programming whenever possible – Create classes to run your business logic (1 class per file if possible)
  • 8.
    Coding Practices • Separatetemplate code from business logic – Your template files should only load and display data, no processing – Your class files should not start/run themselves and should not directly display content (your methods can)
  • 9.
  • 10.
    Security - InputValidation • Never trust user input • Always test if an input or variable exist – isset($variable) = test if variable is not NULL – empty($array) = test if array is empty • Then filter that input to make sure you receive what you expected – filter_var (for any kind of variables) – filter_input (for form inputs)
  • 11.
    Security - InputValidation
  • 12.
    Security - InputValidation
  • 13.
    Security - SQLInjection
  • 14.
    Security - SQLInjection • Use PDO prepare statements (Laravel Eloquent uses it by default and Wordpress has its own prepare statements
  • 15.
    Errors & Exceptions- Errors • PHP is an “exception-light” programming language. • Unless a “fatal error” occurs, most of PHP will try to keep processing • 3 types of error severity: • E_ERROR,E_NOTICE, and E_WARNING
  • 16.
    Errors & Exception- ErrorException Class • Throw your “errors” as “exceptions” using the ErrorException class, which extends the Exception class. • Common practice for several frameworks (Laravel, Symphony, etc.) • Allow to handle errors better than the usual result by “catching” exceptions
  • 17.
    Errors & Exceptions- Exceptions • Exceptions are often overlooked by PHP programmers. • Some old PHP frameworks returns “false” or “Warning” when something goes wrong. – You have to dig in the doc and reread the code to find what’s wrong
  • 18.
    Errors & Exceptions- Exceptions
  • 19.
    You Do Each ofyou will apply the techniques we learned today to optimize/secure/clean your previous projects. Make sure to version your previous code before making any changes so I can see the progression
  • 20.

Editor's Notes

  • #3 Outcomes example
  • #4 Your agenda should reflect your learning progression.
  • #5 the PHP community has a lot of developers creating lots of code. This means that one library’s PHP code may use the same class name as another library. When both libraries are used in the same namespace, they collide and cause trouble. Namespaces solve this problem. As described in the PHP reference manual, namespaces may be compared to operating system directories that namespace files; two files with the same name may co-exist in separate directories. Likewise, two PHP classes with the same name may co-exist in separate PHP namespaces. It’s as simple as that. It is important for you to namespace your code so that it may be used by other developers without fear of colliding with other libraries.
  • #7 The PHP community is large and diverse, composed of innumerable libraries, frameworks, and components. It is common for PHP developers to choose several of these and combine them into a single project. It is important that PHP code adhere (as close as possible) to a common code style to make it easy for developers to mix and match various libraries for their projects. The Framework Interop Group has proposed and approved a series of style recommendations. Not all of them related to code-style, but those that do are PSR-0,PSR-1, PSR-2 and PSR-4. These recommendations are merely a set of rules that some projects like Drupal, Zend, Symfony, CakePHP, phpBB, AWS SDK, FuelPHP, Lithium, etc are starting to adopt. You can use them for your own projects, or continue to use your own personal style. Ideally you should write PHP code that adheres to a known standard. This could be any combination of PSR’s, or one of the coding standards made by PEAR or Zend. This means other developers can easily read and work with your code, and applications that implement the components can have consistency even when working with lots of third-party code.
  • #11 Never ever (ever) trust foreign input introduced to your PHP code. Always sanitize and validate foreign input before using it in code. The filter_var() andfilter_input() functions can sanitize text and validate text formats (e.g. email addresses). Foreign input can be anything: $_GET and $_POST form input data, some values in the$_SERVER superglobal, and the HTTP request body via fopen('php://input', 'r'). Remember, foreign input is not limited to form data submitted by the user. Uploaded and downloaded files, session values, cookie data, and data from third-party web services are foreign input, too. While foreign data can be stored, combined, and accessed later, it is still foreign input. Every time you process, output, concatenate, or include data in your code, ask yourself if the data is filtered properly and can it be trusted.
  • #12 Input validation is both the most fundamental defense that a web application relies upon and the most unreliable. A significant majority of web application vulnerabilities arise from a validation failure, so getting this part of our defenses right is essential. Even where we do appear to have gotten it down, we’ll need to be concious of the following considerations.
  • #13 Input validation is both the most fundamental defense that a web application relies upon and the most unreliable. A significant majority of web application vulnerabilities arise from a validation failure, so getting this part of our defenses right is essential. Even where we do appear to have gotten it down, we’ll need to be concious of the following considerations.
  • #14 By far the most common form of Injection Attack is the infamous SQL Injection attack. SQL Injections are not only extremely common but also very deadly. I cannot emphasise enough the importance of understanding this attack, the conditions under which it can be successfully accomplished and the steps required to defend against it. SQL Injections operate by injecting data into a web appplication which is then used in SQL queries. The data usually comes from untrusted input such as a web form. However, it’s also possible that the data comes from another source including the database itself. Programmers will often trust data from their own database believing it to be completely safe without realising that being safe for one particular usage does not mean it is safe for all other subsequent usages. Data from a database should be treated as untrusted unless proven otherwise, e.g. through validation processes. --------------------- The above has a number of things wrong with it. First of all, we haven’t validated the contents of the POST data to ensure it is a valid user_id. Secondly, we are allowing an untrusted source to tell us which user_id to use - an attacker could set any valid user_id they wanted to. Perhaps the user_id was contained in a hidden form field that we believed safe because the web form would not let it be edited (forgetting that attackers can submit anything). Thirdly, we have not escaped the user_id or passed it to the query as a bound parameter which also allows the attacker to inject arbitrary strings that can manipulate the SQL query given we failed to validate it in the first place.
  • #15 By far the most common form of Injection Attack is the infamous SQL Injection attack. SQL Injections are not only extremely common but also very deadly. I cannot emphasise enough the importance of understanding this attack, the conditions under which it can be successfully accomplished and the steps required to defend against it. SQL Injections operate by injecting data into a web appplication which is then used in SQL queries. The data usually comes from untrusted input such as a web form. However, it’s also possible that the data comes from another source including the database itself. Programmers will often trust data from their own database believing it to be completely safe without realising that being safe for one particular usage does not mean it is safe for all other subsequent usages. Data from a database should be treated as untrusted unless proven otherwise, e.g. through validation processes. --------------------- The above has a number of things wrong with it. First of all, we haven’t validated the contents of the POST data to ensure it is a valid user_id. Secondly, we are allowing an untrusted source to tell us which user_id to use - an attacker could set any valid user_id they wanted to. Perhaps the user_id was contained in a hidden form field that we believed safe because the web form would not let it be edited (forgetting that attackers can submit anything). Thirdly, we have not escaped the user_id or passed it to the query as a bound parameter which also allows the attacker to inject arbitrary strings that can manipulate the SQL query given we failed to validate it in the first place.
  • #16 In many “exception-heavy” programming languages, whenever anything goes wrong an exception will be thrown. This is certainly a viable way to do things, but PHP is an “exception-light” programming language. While it does have exceptions and more of the core is starting to use them when working with objects, most of PHP itself will try to keep processing regardless of what happens, unless a fatal error occurs. Errors are fatal run-time errors and are usually caused by faults in your code and need to be fixed as they’ll cause PHP to stop executing. Notices are advisory messages caused by code that may or may not cause problems during the execution of the script, execution is not halted. Warnings are non-fatal errors, execution of the script will not be halted.
  • #17 PHP is perfectly capable of being an “exception-heavy” programming language, and only requires a few lines of code to make the switch. Basically you can throw your “errors” as “exceptions” using the ErrorException class, which extends theException class. This is a common practice implemented by a large number of modern frameworks such as Symfony and Laravel. By default Laravel will display all errors as exceptions using the Whoops! package if the app.debug switch is turned on, then hide them if the switch is turned off. By throwing errors as exceptions in development you can handle them better than the usual result, and if you see an exception during development you can wrap it in a catch statement with specific instructions on how to handle the situation. Each exception you catch instantly makes your application that little bit more robust.
  • #18 Exceptions are a standard part of most popular programming languages, but they are often overlooked by PHP programmers. Languages like Ruby are extremely Exception heavy, so whenever something goes wrong such as a HTTP request failing, or a DB query goes wrong, or even if an image asset could not be found, Ruby (or the gems being used) will throw an exception to the screen meaning you instantly know there is a mistake. PHP itself is fairly lax with this, and a call to file_get_contents() will usually just get you a FALSE and a warning. Many older PHP frameworks like CodeIgniter will just return a false, log a message to their proprietary logs and maybe let you use a method like $this->upload->get_error() to see what went wrong. The problem here is that you have to go looking for a mistake and check the docs to see what the error method is for this class, instead of having it made extremely obvious. Another problem is when classes automatically throw an error to the screen and exit the process. When you do this you stop another developer from being able to dynamically handle that error. Exceptions should be thrown to make a developer aware of an error; they then can choose how to handle this. E.g.: