Beruflich Dokumente
Kultur Dokumente
PHP.earth
Generated on 2017-08-06
Contents
What is PHP? Where should I start? 18
Where to start? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Where to go next? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
PHP evolution 19
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Which hosting service should I use for PHP? Are there any free
hosting providers? 24
Types of web hosting . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Shared hosting . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
VPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Dedicated server . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1
Collocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Cloud hosting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Free PHP hosting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
PHP basics 25
PHP in a nutshell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Basic syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Hello world . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Control structures . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Built-in types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
PHP errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
What is next? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
PHP 7 33
Why PHP 7 and not PHP 6? . . . . . . . . . . . . . . . . . . . . 33
Major changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Uniform variable syntax . . . . . . . . . . . . . . . . . . . . . . . 34
Exceptions in the engine . . . . . . . . . . . . . . . . . . . . . . . 35
Scalar type declarations . . . . . . . . . . . . . . . . . . . . . . . 35
Combined comparison (spaceship) operator . . . . . . . . . . . . 36
Easy user-land CSPRNG . . . . . . . . . . . . . . . . . . . . . . 36
Null coalescing operator . . . . . . . . . . . . . . . . . . . . . . . 37
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2
Constructor methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Destructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Methods overriding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Public members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Private members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Protected members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Class constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
The static keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
The final keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Calling parent constructors . . . . . . . . . . . . . . . . . . . . . . . . 50
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4
Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
What is an anti-pattern? 83
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5
What is a database and how to access databases from PHP? 83
Application examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Database access from PHP . . . . . . . . . . . . . . . . . . . . . . . . 84
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
What is PDO? 91
Why PDO over others? . . . . . . . . . . . . . . . . . . . . . . . . . . 91
Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Allow exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Retrieving data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Prepared statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Specify how to fetch . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
CRUD examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Insert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Update . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Delete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
6
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
How to work with users’ passwords and how to securely hash pass-
words in PHP? 111
Right way of hashing passwords in PHP . . . . . . . . . . . . . . . . . 112
Password hashing in older PHP versions (5.5 and below) . . . . . . . . 114
Password hashing in open source projects . . . . . . . . . . . . . . . . 114
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
7
Client side validation . . . . . . . . . . . . . . . . . . . . . . . . . 119
Full example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Server configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Apache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
Nginx . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
8
What is a PHP framework and which one should I learn and use?141
Which framework should you learn? . . . . . . . . . . . . . . . . . . . 143
Component frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Full stack frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Micro-frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Miscellaneous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Other resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Related FAQs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
9
SpecBDD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
10
How to add pagination? 165
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Which editor and IDE to choose for writing PHP code? 170
IDE vs editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
How to choose IDE/editor? . . . . . . . . . . . . . . . . . . . . . . . . 170
IDEs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
Client side development . . . . . . . . . . . . . . . . . . . . . . . 172
11
Atom installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Themes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
Code style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Atom beautify . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Editorconfig . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
PHP Integrator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
PHP Debug . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
PHP Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Minimap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Highlight Selected . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Atom Minify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
Todo Show . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Color Picker and Pigments . . . . . . . . . . . . . . . . . . . . . 181
Ctrl-dir-scroll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Project Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Emmet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Docblockr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
File Icons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Framework specific packages . . . . . . . . . . . . . . . . . . . . . 181
Docker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
Shortcuts and useful features . . . . . . . . . . . . . . . . . . . . . . . 182
Caveats and final thoughts . . . . . . . . . . . . . . . . . . . . . . . . 182
Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
Learning curve . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
Nopaste list and services to share and run code online 188
What is a nopaste? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
List of nopaste services . . . . . . . . . . . . . . . . . . . . . . . . 188
Run and execute code online . . . . . . . . . . . . . . . . . . . . 188
Online editors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Screenshot sites . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
12
Vagrant tutorial 189
What is Vagrant? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
Project setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
Boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
What is PuPHPet? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
How to save your changes on a box? . . . . . . . . . . . . . . . . . . . 191
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
What are PHP conferences and where can I attend one? 196
Highlighted PHP conferences . . . . . . . . . . . . . . . . . . . . . . . 197
13
PHP 7 ElePHPant . . . . . . . . . . . . . . . . . . . . . . . . . . 204
Symfony ElePHPant . . . . . . . . . . . . . . . . . . . . . . . . . 204
TrueNorth PHP Woolly Mammoth . . . . . . . . . . . . . . . . . 204
PHP Classes ElePHPant . . . . . . . . . . . . . . . . . . . . . . . 204
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
What is web crawling and how to crawl websites with PHP? 216
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
14
How to deploy PHP application? 219
What does the deployment include? . . . . . . . . . . . . . . . . . . . 220
Quality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
Application life cycle management (ALM) . . . . . . . . . . . . . . . . 220
How to choose the right deployment strategy? . . . . . . . . . . . . . . 220
FTP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
Moving on . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
GIT + SSH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Deployer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Fabric . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Docker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Jenkins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Other deployment options . . . . . . . . . . . . . . . . . . . . . . . . . 223
Paid services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
PaaS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
15
How to get client’s IP address in PHP? 233
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
16
What is web scraping and how to scrape data in PHP? 246
See also . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
17
Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
Secured configuration files . . . . . . . . . . . . . . . . . . . . . . 258
Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
Development environment . . . . . . . . . . . . . . . . . . . . . . . . . 259
Where to start?
If you want to learn PHP and web development as properly and as “right way” as
possible, it is very important to gain basic knowledge of mathematics, computer
science, programming in general and similar tech fields before learning PHP or
other languages.
PHP is located and best described by the official website PHP.net, with an up-
to-date and in-depth manual located here. Reading it is highly recommended
to get to know PHP in detail. As you read through the manual, your knowledge
will progress. You can start with the “Simple PHP Tutorial” to get PHP up
and running fast.
Use Google for the more obvious issues that you’re likely to find or ask on
forums.
Where to go next?
18
See also
Recommended, quality and modern guides, videos and tutorials for starting
with development and PHP in particular:
• Basics of programming for beginners
• Codecademy - Free course for learning to program in PHP; 4 hours.
• Codecourse - Free videos for learning PHP; 2.5 hours.
• CS50x - Harvard University’s introduction course to computer science.
• Devcasts - PHP video tutorials.
• Hacking with PHP - PHP book from beginning to advanced.
• Nomad PHP - What to learn first in PHP?; 16 minutes video.
• OverAPI PHP - PHP cheat sheet.
• PHP School - Interactive open source learning for PHP through command
line.
• PHP: The Right Way - An easy-to-read, quick reference for PHP best
practices, accepted coding standards, and links to authoritative tutorials
around the web.
• thenewboston - Free videos for learning PHP; 200 videos.
• w3clan PHP - Free PHP tutorials.
• Devscreencast - Free introduction to programming with PHP Course.
PHP evolution
Knowing something about PHP history and about who initially created the PHP
language and started the PHP project is interesting information that might help
inspire you for developing something of your own. It might also help you to
better understand the current state of PHP functionality.
PHP was initially written by Rasmus Lerdorf. It all started in 1994 when
Rasmus started working on the very first incarnation of PHP which was a simple
set of Common Gateway Interface (CGI) binaries written in the C programming
language.
See also
19
How to install PHP? Which version of PHP to
use?
PHP installation might not be so obvious at first. Included here is a quick
overview of how to get PHP up and running fast.
PHP versions
Make sure to use the latest stable version PHP 7.1. Versions on some online
production servers can be few versions behind the latest PHP releases because
of hosting policies and backwards compatibility. Don’t let this stop you from
using the latest PHP with all its shiny new features.
PHP installation
You can download and use PHP binaries and sources for Windows and other
systems from the official site. Building PHP from source on your own has its
benefits in that you can configure your build according to your specific require-
ments. Refer to the PHP manual for learning how to build PHP from source.
PHP has a useful built-in web server for local development. Inside your project
folder you can run it from the command line:
$ php -S localhost:8000
Visit http://localhost:8000/index.php in your browser to access it.
To successfully develop and run PHP applications you will eventually need a
more advanced web server such as Apache or Nginx, a database such as MySQL
or MariaDB, and other useful tools such as Xdebug, Adminer, phpMyAdmin, etc.
Whether you’re using Windows, OS X or Linux, you can simplify installation
by using one of these all-in-one packages:
• AMPPS
• XAMPP
• Zend Server
Windows installation
Aside from the above, on Windows, you can also use one of the following useful
all-in-one packages:
• Easy PHP
• WPN XM
20
OS X
By default, OS X includes a slightly outdated PHP. To install and use the latest
PHP on OS X, aside from by using one of the aforementioned packages, you
can also use one of the following solutions:
• Homebrew PHP repository for Homebrew package manager.
• Liip’s PHP binary package.
• MacPorts - Package management system provided by an open source com-
munity initiative.
• MAMP - All-in-one package for OS X (and Windows).
Linux installation
Linux and Unix based operating systems are a bit more complex and diverse.
Learning to use these environments is recommended for developers. After all,
there’s a high chance that your web application will be hosted on such servers.
PHP installation can be done with package managers, that distribution uses
(apt-get, pacman, zypper or yum, with its successor dnf).
A simplified example of apt usage for Debian based distributions (Debian,
Ubuntu…):
$ sudo apt-get install php
and yum (or newer dnf) for Fedora based distributions (Fedora, RHEL, Cen-
tOS…):
$ sudo dnf install php
Keep in mind that there are many other packages such as php-curl,
lamp-server, php-mysql and others, to be explored with your distribution.
Most of the time the default PHP version provided by the distribution will be a
few versions behind the latest stable release from PHP.net. This is where some
useful third-party repositories can come in handy:
• deb.sury.org - For Debian and Ubuntu.
• REMI repository - For Fedora, CentOS and RHEL.
• Webtatic - For Fedora, CentOS and RHEL.
Virtualization
21
Docker. These help you reduce friction between development and production
environments. With virtual environments, you can make your development
(software versions, configuration…) the same as what your production is.
Docker
See also
If you’re still not convinced just yet, please also check some of these other
resources on this topic:
• Why choose PHP over alternatives - Why should a developer choose PHP
for new projects, rather than an alternative language?
22
in mind that writing a very good programming book can take several thousand
hours, so supporting their authors is nice way of saying thank you.
• Official PHP manual - Offical PHP manual is also available for offline
usage.
• PHP: The Right Way - An easy to read, quick reference for PHP best
practices, accepted coding standards, and links to authoritative PHP tu-
torials around the web. “PHP: The Right Way” is also available as a PDF
book.
• PHP 5 Power Programming
• PHP Best Practices - A short, practical guide for common and confusing
PHP tasks.
• PHP Essentials
• PHP Internals Book
• PHP Pandas - Aims to teach everyone how to be a web developer.
• PHP Programming
• PHP Security Guide
• Practical PHP Programming
• Practical PHP Testing
• Survive The Deep End: PHP Security - PHP Security
• Wikibooks PHP Programming - A PHP programming book on Wikibooks.
• Using Libsodium in PHP Projects - A guide to using the libsodium PHP
extension for modern, secure, and fast cryptography.
23
Which hosting service should I use for PHP? Are
there any free hosting providers?
In order for a web application to be able to run on the web (production envi-
ronment), you usually choose a hosting service provider with a web server.
Shared hosting
A shared web hosting service or virtual hosting service is a service where many
websites are hosted on the same webserver, and the server’s resources (RAM,
disk, and processor) are shared among the users. PHP settings and installed
extensions are usually the same for all websites. It might be a good option if
you want to get started quickly and painlessly, but still leave the maintaining
and server upgrading to your preferred hosting service.
VPS
Dedicated server
A dedicated server means an entire server machine, dedicated for your needs.
More resources and disk quota is available for you when choosing to use a ded-
icated server. The price can be high, but flexibility and customization is at its
best. Choose this option if you’re an advanced user with system administration
knowledge.
Collocation
Collocated hosting means that you bring your own hardware to your data center
service provider, and they plug it onto their high speed and availability network.
Cloud hosting
24
Free PHP hosting
One of the most frequently asked questions is whether there any good, free
providers for hosting PHP applications.
In short, yes, there are, but keep in mind that sooner or later you’ll meet
limitations with this approach. Almost nothing is completely free, and the
same is true for web hosting.
Some of the limitations to be aware of:
• Traffic quota limit.
• Server resources quota limit.
• PHP extensions and functionality limitations.
• Forcibly injected advertising.
A quick list of some free hosting providers to check out:
• Amazon AWS Free Tier
• Heroku
• Zeit now
• …
Do yourself and your application’s audience a favor and invest a bit into your
hosting infrastructure. Stability and availability of your application will depend
on a lot on this.
See also
PHP basics
1. PHP in a nutshell
2. Basic syntax
1. Hello world
2. Operators
• Arithmetic operators
• Comparison operators
• Logical operators
• Assignment operators
3. Declarations
4. Functions
• Anonymous functions (closures)
25
• Variadic functions
5. Control structures
• If
• Loops
• Switch
6. Arrays
• Operations on arrays
7. Built in types
3. Errors
1. PHP Errors
2. What is next?
This tutorial will show you basic PHP syntax and its features. If you’re new to
PHP, read the most basic PHP tutorial to get started as quickly and painlessly
as possible. For becoming a modern PHP developer, read and follow PHP: The
Right Way. Seriously.
PHP in a nutshell
• Scripting language
• Procedural and object oriented language
• Dynamically (weakly) typed
• Syntax similar to C, C++, C#, Java and Perl
• Imperative language
• PHP has closures
Basic syntax
Hello world
File hello.php:
<?php
Operators
Arithmetic operators
26
Operator Name Result
$a + $b addition Sum of $a and $b.
$a - $b Subtraction Difference of $a and $b.
$a * $b Multiplication Product of $a and $b.
$a / $b division Quotient of $a and $b.
$a % $b modulus Remainder of $a divided by $b.
$a ** $b Exponentiation Result of raising $a to the $b’th power.
Comparison operators
27
Operator Name Result
$a > $b GreaterTRUE if $a
than is strictly
greater
than $b.
$a <= Less TRUE if $a
$b than is less than
or or equal to
equal $b.
to
$a >= GreaterTRUE if $a
$b than is greater
or than or
equal equal to $b.
to
Logical operators
Assignment operators
Operator Description
= Set a value to variable
+= Addition of numeric value to variable
.= Add string to variable
Declarations
28
Functions
// A simple function
function functionName() {}
// Inherit
$message = 'hello';
// Inherit $message
$example = function () use ($message) {
var_dump($message);
};
echo $example();
Variadic functions
<?php
function sum(...$nums)
{
return array_sum($nums);
}
29
Control structures
If
if $x > 0 {
return $x;
} else {
return -$x;
}
Loops
// for
for ($i = 1; $i<10; $i++) {}
// while
while ($i < 10) {}
// do while
$i = 0;
do {
echo $i;
} while ($i > 0);
// foreach
foreach ($array as $key => $value) {}
Switch
// switch statement
switch ($operatingSystem) {
case 'darwin':
echo 'Mac OS Hipster';
break;
case 'linux':
echo 'Linux Geek';
break;
default:
// Windows, BSD, ...
echo 'Other';
}
30
Arrays
$array = [
"foo" => "bar",
"bar" => "foo",
];
Operations on arrays
31
Operator Name Result
$a <> Inequality
TRUE
$b if $a is
not
equal
to $b.
$a !== Non- TRUE
$b identityif $a is
not
identi-
cal to
$b.
Built-in types
Type
boolean
integer
float
string
array
object
resource
NULL
Errors
PHP errors
<?php
// Turn off all error reporting
error_reporting(0);
32
// Report all PHP errors (see changelog)
error_reporting(E_ALL);
// Same as error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
Exceptions
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
return 1/$x;
}
try {
echo inverse(5) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "This is always executed.\n";
}
What is next?
Use php.net. It has a great and detailed manual for your PHP adventures.
PHP 7
PHP 7 is the next major version of the PHP language. You really should check
it out and upgrade.
Choosing the version 7 (instead of 6) was chosen because a lot of existing books
were mentioning PHP 6 long before the development of the next major version
after PHP 5 started. Andi Gutmans said “We’re going to skip version 6 because
33
Figure 1: PHP 7
years ago, we had plans for a 6 but those plans were very different from what
we’re doing now,” so the name PHP 7 was chosen.
Major changes
Thanks to AST (Abstract Syntax Tree) implemented in PHP7 now you can
write expressions in the more predictable ways.
34
$obj->someMethod()()()()();
In previous versions you couldn’t catch fatal errors. Now you can do this:
<?php
function doSomething($obj)
{
$obj->nope();
}
try {
doSomething(null)
} catch (\Error $e) {
echo "Error: {$e->getMessage()}\n";
}
Now you can enforce parameter types as strings (string), integers (int), floating-
point numbers (float), and booleans (bool). Type declarations (previously
known as type hints) in PHP 5 were class names, interfaces, array and callable.
<?php
// Coercive mode
function sum (int ...$numbers)
{
return array_sum($numbers);
}
35
var_dump(sum(2, '3', 4.1)); // outputs 9
Besides coercive mode there is also strict mode which can be enabled per file
basis with:
<?php
declare(strict_types=1);
Read more about type declarations in the PHP manual.
$items = [
['title' => 'Mouse'],
['title' => 'Computer'],
['title' => 'LCD Screen'],
];
PHP 7 has two new functions random_bytes() and random_int() for generat-
ing cryptographically secure integers and strings in a cross platform way.
Before PHP 7 you had to use the generator on the platform. For example,
CryptGenRandom on Windows and /dev/urandom on Linux. If you’re building
modules that must work on all platforms, this might be an issue. In PHP 7 you
can simply use the built-in generator.
36
Null coalescing operator
It turned out that often you needed to use ternary operator with isset() func-
tion.
An example where you need to check if the GET data has been sent and set the
$username based on that. In PHP 5 you could do something like this:
<?php
$user = isset($_GET['user']) ? $_GET['user'] : 'Guest';
Now you can simplify this a lot:
<?php
$user = $_GET['user'] ?? 'Guest';
See also
37
Figure 2: PHP version usage, october 2014
PHP 5.6.0 currently has active support, but that will expire in December 2017.
Having wide availability of the software is important for open source projects.
Increasing minimum version requirement is in many cases a delicate issue, but
more and more projects are requiring more or less the latest versions already.
Enforcing later versions is a good thing to encourage users to upgrade the PHP
used on their servers.
38
of developer’s code is important).
What to do?
• Ask for better environment: A server with the latest stable PHP version
installed and operable.
• Upgrade to the latest PHP version and refactor old code.
• Push the miniminum version of PHP in composer.json files to newer
PHP versions.
• Create a maintainability strategy for your projects to upgrade server soft-
ware together with PHP on a regular basis.
See also
• PHP minimal version in Symfony 3.0 - Symfony 3.0 roadmap and minimal
PHP version.
• Jordi Boggiano - PHP versions stats on packagist.org.
• schmengler-se.de - Dropping PHP 5.3 support.
• ircmaxell’s blog post on install statistics - PHP install statistics.
$name = "World";
echo "Hello, $name";
Where as in languages without sigil usage (for example, Python), you must
either concatenate strings:
39
name = "World"
print "Hello, " + name
or use special interpolation syntax if the language provides it. For example,
Ruby:
name = "World"
puts "Hello #{name}"
Many people used to other languages might find the sigil usage odd, but you
can get used to it in no time and discover the its benefits.
See also
Before we get into details, let’s define some important OOP terms.
• Class: This is a programmer-defined datatype, which includes local func-
tions and local data. You can think of a class as a template for making
many instances of the same kind (or class) of object.
• Object: An individual instance of the data structure defined by a class.
You define a class once and then make many objects that belong to it.
Objects are also known as instances.
40
• Member variable: These are the variables defined inside a class. This
data will be invisible to the outside of the class and can be accessed via
member functions. These variables are called attributes of the object once
it’s created.
• Member function: These are the functions defined inside a class and
are used to access object data.
• Inheritance: When a class is defined by inheriting existing function of a
parent class, it is called inheritance. Here, a child class inherits some or
all member functions and variables of its parent class.
• Parent class: A class that is inherited from by another class, also referred
to as a base class or super class.
• Child class: A class inherits from another class (the parent class), also
referred to as a subclass or derived class.
• Polymorphism: This is an object oriented concept where the same func-
tion can be used for different purposes. For example, the name of a func-
tion remaining the same but taking a different number of arguments and
performing a different task.
• Overloading: A type of polymorphism in which some or all operators
have different implementations depending on the types of their arguments.
Similarly, functions can also be overloaded with different implementations.
• Data abstraction: Any representation of data in which the implementa-
tion details are hidden (abstracted).
• Encapsulation: Refers to a concept whereby data is encapsulated to-
gether with member functions to form an object.
• Constructor: Refers to a special type of function to be called automati-
cally whenever an object is formed from a class.
• Destructor: Refers to a special type of function to be called automati-
cally whenever an object is deleted or goes out of scope.
Defining classes
class PhpClass
{
public $var1;
public $var2 = 'string value';
41
public function myfunction($arg1, $arg2)
{
// ...
}
// ...
}
Explanations of keywords used in the above class definition:
• Keyword class, followed by the name of the class, PhpClass.
• Opening and closing braces {}, which include any number of properties
and methods.
• Property declaration can start with the keyword public, which is then
followed by a conventional $variableName. It may also have an initial
assignment of values.
• Method definitions look much like stand-alone PHP functions but are local
to the class and can used to set and access object data.
Example
class Book
{
public $price;
public $title;
42
{
return $this->title;
}
}
Special variable $this refers to the current object (i.e. itself).
Once you define your class, you can create as many objects as you like of that
class type. With the new keyword, you create an object (a class instance):
$physics = new Book();
$maths = new Book();
$chemistry = new Book();
Here we have created three new objects which are independent of each other.
Let’s check how to call methods and process class properties. After creating
your objects, you will be able to call class methods related to that object. One
class method will be able to process class properties of the related object only.
The following example shows how to set titles and prices for these three books
by calling class methods.
$physics->setTitle('Physics for High School');
$physics->setPrice(10);
$maths->setTitle('Algebra');
$maths->setPrice(7);
$chemistry->setTitle('Advanced Chemistry');
$chemistry->setPrice(15);
Now you call another methods to get the values from above example:
echo $physics->getTitle();
echo $physics->getPrice();
echo $maths->getTitle();
echo $maths->getPrice();
echo $chemistry->getTitle();
echo $chemistry->getPrice();
This will produce the following result:
43
Physics for High School
10
Algebra
7
Advanced Chemistry
15
Constructor methods
echo $maths->getTitle();
echo $maths->getPrice();
echo $chemistry->getTitle();
echo $chemistry->getPrice();
The above will produce the same result as in the previous example.
44
Destructor
Like with the constructor method, you can also define a destructor by using
the special method __destruct(). A destructor is called automatically as soon
as there are no more references to a particular object or during the shutdown
sequence. Within a destructor you can release all resources.
From the Books class example above, let’s add the following destructor.
public function __destruct()
{
echo "A book ({$this->title}) is destroyed.\n";
}
$physics = new Book('Physics for High School', 10);
$maths = new Book('Advanced Chemistry', 15);
$chemistry = new Book('Algebra', 7);
$mathsCopy = $maths;
Output
Inheritance
PHP class definitions can optionally inherit from a parent class definition by
using the extends keyword:
class Child extends Parent
{
// Definition body
}
The effect of inheritance is that the child class (or subclass, or derived class)
has the following characteristics:
45
• It automatically has all the member variable declarations of the parent
class.
• It automatically has all the same member functions as the parent, which
will work the same way as those functions do in the parent by default.
The following example inherits the Book class and adds additional functionality
compared to the parent class.
class Novel extends Book
{
public $publisher;
Methods overriding
Methods defined in child classes override methods with the same name in parent
classes. In a child class, we can modify the definition of a method inherited from
parent class.
In the following example, the getPrice() method is overriden to return a price
number with currency.
public function getPrice()
{
return $this->price . " EUR";
}
Public members
Unless you specify otherwise, properties and methods of a class are public by
default. This means that they may be accessed in three possible situations:
• From outside the class in which it is declared.
• From within the class in which it is declared.
• From within another class that implements the class in which it is declared.
46
Until now, we have seen all members as public members. If you wish to limit
the accessibility of the members of a class, you define class members as private
or protected.
Private members
By setting a member as private, you limit its accessibility to only the class
where it is defined. The private member can not be used in inherited classes
nor outside the class.
A class member can be made private by using the private keyword in front of
the member.
class Car
{
private $model = 'skoda';
$driver = 'SRK';
Protected members
47
two contexts. A class member can be made protected by using the protected
keyword in front of the member.
Here is a different version of the class Car:
class Car
{
protected $car = 'skoda';
$driver = 'SRK';
Interfaces
48
}
}
Class constants
A class constant is an immutable value. Once you declare a constant, it can not
be changed:
class MyClass
{
const MARGIN = 1.7;
Declaring class members or methods as static makes them accessible without the
need for class instantiation. A member declared as static can not be accessed
with an instantiated class object (although a static method can).
Try out the following example:
class Foo
{
public static $myStatic = 'foo';
49
The final keyword
The final keyword prevents child classes from overriding a method by adding
final to the definition. If the class itself is being defined final then it can not
be extended.
The following example results in “Fatal error: can not override final method
BaseClass::moreTesting()”
class BaseClass
{
public function test()
{
echo "BaseClass::test() called<br>";
}
Instead of writing a new constructor for the subclass, you can call the parent’s
constructor explicitly and then do whatever is necessary in addition for instan-
tiation of the subclass. Here’s a simple example:
class Person
{
private $firstName;
private $lastName;
50
public function getFullName()
{
return $this->firstName.' '.$this->lastName;
}
}
See also
• PHP.net: Classes and Objects - A must read PHP OOP manual chapter.
• Learn OOP in PHP - A collection of resources to learn object-oriented
programming and related concepts for PHP developers.
• When to declare classes final
51
{
public function myImplementedMethod()
{
echo 'Hello World!';
}
}
Abstract classes can also contain abstract methods. Abstract methods are meth-
ods without body (implementation).
<?php
52
It is not legal to have abstract function definitions inside a non-abstract class.
Any class that contains at least one abstract method, must be declared abstract.
In PHP, abstract classes cannot be declared final.
See also
53
interface Iterator extends Traversable
{
public function current();
public function key();
public function next();
public function rewind();
public function valid();
}
While the IteratorAggregate interface has only 1 method.
interface IteratorAggregate extends Traversable
{
public function getIterator();
}
54
}
if ($this->value === $this->end) {
$this->value = null;
return;
}
if ($this->start < $this->end) {
$this->value++;
} else {
$this->value--;
}
$this->key++;
}
Output
0:10
1:9
2:8
3:7
4:6
5:5
6:4
7:3
8:2
9:1
55
Using IteratorAggregate interface
<?php
class IntegerRangeIterator implements IteratorAggregate
{
private $start;
private $end;
Output
0:1
1:2
2:3
3:4
4:5
5:6
6:7
7:8
8:9
9:10
People often forget about the underused, built-in iterators in PHP’s standard
PHP library.
56
Resources
See also
57
• Single Responsibility Principle
According to the Gang of Four book we can categorize design patterns into three
main categories:
• Abstract Factory
• Builder
• Prototype
• Singleton
• Adapter
• Bridge
• Composite
• Decorator
• Facade
• Flyweight
• Proxy
• Chain of responsibility
• Command
• Intepreter
• Iterator
• Mediator
• Memento
• Observer
• State
• Strategy
• Template method
• Visitor
Other design patterns that are important to know for complex applications:
58
• Dependency injection
• Lazy loading
• Mock object
• Null object
• Object pool
• Servant
• Type tunnel
See also
See also
See also
See also
59
Figure 3: Adapter Design Pattern UML Diagram
See also
See also
60
Command design pattern in PHP
See also
See also
See also
class Author
{
/**
* @var string
*/
private $firstName;
/**
* @var string
*/
private $lastName;
61
/**
* Constructor.
*
* @param string $firstName
* @param string $lastName
*/
public function __construct($firstName, $lastName)
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
class Book
{
/**
* @var string
*/
private $title;
/**
* @var string
*/
private $author;
/**
* Constructor.
*
* @param string $firstName
* @param string $lastName
* @param string $title
*/
public function __construct($firstName, $lastName, $title)
{
$this->title = $title;
$this->author = new Author($firstName, $lastName);
}
}
As you can see, we have a class Author with $firstName and $lastName prop-
erties, and in the class Book constructor, we inject the properties of the Author
class along with the Book class properties and create an object of the Author
class and store it. You may think it is great code, but it is not.
Why?
• You are violating the single responsibility principle. The Book class does
62
more than representing a Book.
• You are tightly coupling the code. If you ever had to add a new property
to the Author class constructor, then you will break the Book class.
Therefore, to solve this issue, we use dependency injection, and this is how you
use it:
<?php
class Author
{
/**
* @var string
*/
private $firstName;
/**
* @var string
*/
private $lastName;
/**
* Constructor.
*
* @param string $firstName
* @param string $lastName
*/
public function __construct($firstName, $lastName)
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
class Book
{
/**
* @var string
*/
private $title;
/**
* @var Author
*/
private $author;
/**
63
* Constructor.
*
* @param string $title
* @param Author $author
*/
public function __construct($title, Author $author)
{
$this->title = $title;
$this->author = $author;
}
}
Constructor injection
Setter injection
class Author
{
/**
* @var string
*/
64
private $firstName;
/**
* @var string
*/
private $lastName;
/**
* Constructor.
*
* @param string $firstName
* @param string $lastName
*/
public function __construct($firstName, $lastName)
{
$this->firstName = $firstName;
$this->lastName = $lastName;
}
}
class Book
{
/**
* @var string
*/
private $title;
/**
* @var Author
*/
private $author;
/**
* Set book author.
*
* @param Author $author
*/
public function setAuthor(Author $author)
{
$this->author = $author;
}
/**
* Set book title.
*
* @param string $title
65
*/
public function setTitle($title)
{
$this->title = $title;
}
}
Interface injection
See also
See also
66
Flyweight design pattern in PHP
See also
See also
PHP implementations
• PHP offers Iterator interface out of the box. Its SPL library has also a wide
variety of useful iterators. After understanding the basics of the iterator
pattern using these instead of reinventing the wheel is more convenient.
See also
67
The opposite of lazy loading is so called eager loading where the data, resource,
and object is created in the time of the initialization.
A practical example is reading data from the database, where each query is
expensive in terms of performance. When the data is requested via the getter
method, it is retrieved at that time and not before.
In the following example, the bar property is lazy loaded to preserve resources:
<?php
class Foo
{
/** @var mixed Reference property */
private $bar = null;
/**
* Get reference and assign it via some resource expensive method call only
* once.
*
* @return mixed
*/
public function getBar()
{
if ($this->bar == null) {
$this->bar = $this->expensiveCall();
}
return $this->bar;
}
/**
* This method makes something resource intense and calling it multiple
* times inside a single request can be avoided with above lazy loading.
*/
private function expensiveCall()
{
// ...
}
68
}
/**
* User model which calls an resource intense repository method to get posts.
*/
class User
{
/** @var array Post items */
private $posts;
/**
* Set reference to a user repository method with Closure.
*
* @param Closure
*/
public function setReference(Closure $reference)
{
$this->reference = $reference;
}
/**
* Get array of items retrieved from the database with the method call of
* the repository. The retrieval from the database happens only once with
* the help of lazy loading and therefore improves performance.
*
* @return array
*/
public function getPosts()
{
if (!isset($this->posts)) {
$reference = $this->reference;
69
$this->posts = $reference();
}
return $this->posts;
}
}
/**
* Repository of users from the database.
*/
class UserRepository
{
/** @var mixed Reference to a database or ORM database manager object. */
private $database;
/**
* Get user and set the reference to call when requiring posts from the
* database by the given ID.
*
* @param int $id
*
* @return User
*/
public function findOneById($id)
{
$database = $this->database;
$query = $database->query('SELECT * FROM user WHERE id = :id')
$query->setParameter('id', $id);
$posts = [];
foreach ($userData as $data) {
$posts[] = new Post($data);
}
return $posts;
};
70
$user->setReference($reference);
return $user;
}
}
PHP implementations
See also
See also
UML diagram
See also
71
Figure 5: Memento design pattern UML diagram
Implementations
• PHPUnit
See also
interface CommandInterface
{
public function execute();
72
Figure 6: Null object design pattern UML diagram
class Application
{
public function run(CommandInterface $command = null)
{
$executableCommand = $command ?? new NullCommand();
73
return $executableCommand->execute();
}
}
Usage is then the following:
<?php
// ...
// Do nothing
$application->run();
If we run the application without providing it the command, it does nothing,
because in that case it uses the null object NullCommand. Without the null
object, we would have to check that in the client code which becomes messy as
more commands are added or in more complex situations.
Some examples of the null object design pattern implementations in open source:
• NullOutput in Symfony Console
• NullHandler in Monolog
See also
74
Object pool design pattern in PHP
Object pool pattern is a software creational design pattern which is used in
situations where the cost of initializing a class instance is high. It can offer a
significant performance boost.
Object pool (resource pool) manages instantiated classes. Client code has access
to the pool and can then use it to avoid creating new objects by going through
the pool to find the one that has already been instantiated. When the pool
is empty it will create new objects. Depending on the wanted implementation
and functionality, the pool can also be set to limit the number of instantiated
classes.
<?php
class ObjectPool
{
/** @var array Instances of reusable objects */
private $instances = [];
/**
* Get object from instances.
*
* @param string $key Key for retrieving the instance.
75
*
* @return ReusableObject
*/
public function get($key)
{
return $this->instances[$key];
}
/**
* Add object to list of instances.
*
* @param ReusableObject
*/
public function add($object, $key)
{
$this->instances[$key] = $object;
}
}
class ReusableObject
{
/**
* Do something.
*/
public function doSomething()
{
// ...
}
}
// Client code
$pool = new ObjectPool();
$reusableObject = new ReusableObject();
$pool->add($reusableObject, 'reusable_object_key')
$reusableObject = $pool->get('reusable_object_key');
$reusableObject->doSomething();
A practical example could also be managing a conference with call for papers.
When the call for paper is issued, speakers propose their talks and the managers
decide which speakers to invite. Speakers get assigned to talk sessions. If a
speaker cancels the talk, the talk session becomes available for the next speaker.
76
Most of the time, keep all reusable objects that are not currently in use in
the same object pool so that they can be managed by one coherent policy. To
achieve this, the reusable pool class is designed to be a singleton class.
• Pool in pthreads
• PSR-6 compatible cache libraries
Dependency injection container can also use object pool together with some
other design patterns.
See also
See also
See also
See also
77
Figure 8: Proxy design pattern UML diagram
78
See also
class Singleton
{
/** @var Singleton Reference to singleton class instance. */
private static $instance;
/**
* Private constructor ensures the class can be initialized only from
* itself.
*/
private function __construct() {}
79
/**
* Get a singleton class instance with lazy initialization only on first
* call. Client code can therefore use only this accessor method to
* manipulate the singleton.
*
* @return Singleton
*/
public static function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* @throws Exception to prevent cloning object.
*/
public function __clone()
{
throw new Exception('You cannot clone singleton object');
}
}
The singleton pattern can be extended to support access to an application-
specific number of instances.
Inheritance of the singleton class is not possible when using a static accessor
method. Also, deleting an instance of a singleton class is a non-trivial design
problem.
A singleton should be considered only if all of the following criteria are met:
• Ownership of the single instance cannot be reasonably assigned.
• Lazy initialization is desirable.
• Global access is not otherwise provided (in case of legacy applications).
If the above criteria does not present implementation issues in the application
code, then in most cases, the dependency injection should be used for better
testability and flexible maintainability.
When accessing the global scope, the advantage of the singleton pattern over
global variables is that it ensures the number of instances which can be changed
to any required number any time.
80
The same as using global variables inside classes, the singleton pattern imple-
mented on class level is considered an anti-pattern because it reduces testability
and maintainability of the code. To replace global variables with a singleton is
a wrong approach to solve access of global scope from a class.
A singleton can be used when it is simpler to pass an object resource as a
reference to the objects that need it instead of letting objects access the resource
globally. It might be useful and handy to use a singleton, but the appropriate
visibility of an object must be thought through.
The singleton pattern implemented on factory, incubator, or service container
level is not an anti-pattern. Abstract factory, builder, and prototype can use
a singleton in their implementation. Facade and state objects are also often a
singleton, because only one class instance is required.
See also
See also
See also
See also
81
Type tunnel design pattern in PHP
The type tunnel pattern is not exactly a recognized software design pattern by
GoF (Gang of Four book). Type tunnel is used in cases where multiple unrelated
types are passed (tunneled) through adaptation layer and converted to the type
the underlying layer expects.
Type tunnel also has side effects that compensate its benefits, because in a
dynamically typed language such as PHP, the types can be solved differently.
It can be used best in statically typed programming languages such as C++,
but in case of PHP, implementing type tunnel isn’t really applicable.
See also
• Type Tunnel
• Generalized String Manipulation: Access Shims and Type Tunneling
• PHP Types
See also
82
What is an anti-pattern?
An anti-pattern is a common response to a recurring problem that
is usually ineffective and risks being highly counterproductive. The
term, coined in 1995 by Andrew Koenig, was inspired by a book,
“Design Patterns”, which highlights a number of design patterns in
software development that its authors considered to be highly reli-
able and effective.
• Wikipedia
See also
• AntiPatterns eBook
Application examples
83
• Credit card transactions: For purchases on credit cards and generation of
monthly statements.
• Telecommunication: For keeping records of calls made, generating monthly
bills, maintaining balances on prepaid calling cards, and storing informa-
tion about the communication networks.
• Finance: For storing information about holdings, sales, and purchases of
financial instruments such as stocks and bonds.
• Sales: For customer, product, and purchase information.
• Manufacturing: Management of supply chain, tracking factory production,
inventories of items in warehouses, and orders for items.
• Human resources: Information about employees, salaries, payroll taxes
and benefits, and paychecks generation.
PHP has in its core multiple extensions for accessing different types of databases.
Before accessing database from PHP learn SQL (Structured Query Language).
SQL is a language designed to manage data stored in relational databases.
After getting a grip with basics many applications abstract the database layer,
customize SQL for more advanced, efficient and better ways to access databases.
For more information about this check PHP ORMs.
See also
84
How to fix it?
In PHP there are multiple ways to access database (PDO, ORMs, or mysqli for
MySQL and MariaDB databases). Fixing legacy and old code is recommended
and shouldn’t be very difficult and time consuming task by refactoring it to
PDO_MySQL extension or mysqli.
Here is an example of writing code in the old way by using mysql_* functions:
$link = mysql_connect('localhost', 'db_user', 'db_password');
if (!$link) {
die('Connection failed: ' . mysql_error());
}
$database = mysql_select_db('db_name', $link);
$result = mysql_query($query);
$sth = $pdo->prepare('
SELECT username FROM friends
WHERE first_name = :firstName');
$sth->bindParam(':firstName', $firstName, PDO::PARAM_STR);
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach ($result as $row) {
echo $row['username'];
}
85
MySQL improved extension - MySQLi
if (mysqli_connect_errno()) {
die('Connect failed: ' . mysqli_connect_error());
}
// fetch values
while (mysqli_stmt_fetch($stmt)) {
echo $username;
}
// close statement
mysqli_stmt_close($stmt);
}
Let’s refactor above code into mysqli object oriented way:
$mysqli = new mysqli('localhost', 'db_user', 'db_password', 'db_name');
if ($mysqli->connect_error) {
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
86
}
MySQL extension has been in PHP core from the very early 2.0 version - it
was over 15 years old. One of the main reasons for removal was difficult
and complicated maintenance in the PHP core. MySQL extension also doesn’t
provide all the latest features and benefits of the MySQL database.
See also
• PDO tutorial
• PDO Tutorial for MySQL Developers
• Related FAQ: What is ORM? - Advanced ways to access databases in
PHP.
• Supercharging PHP MySQL applications using the best API - Blog post
explaining why upgrading from ext/mysql is a good idea.
87
Feature PDO MySQLi
Prepared statements Yes Yes
Non-blocking, asynchronous queries with mysqlnd support No Yes
Multiple Statements support Most Yes
MySQL 5.1+ functionality support Most All
Database connection
// PDO
$pdo = new PDO("mysql:host=localhost;dbname=database;charset=utf8", 'username', 'password');
Databases support
The core advantage of PDO over MySQLi is in its database driver support. At
the time of this writing, PDO supports 12 different drivers, opposed to MySQLi,
which supports only MySQL and MariaDB databases.
Named parameters
$pdo->prepare('
SELECT * FROM users
WHERE username = :username
AND email = :email
AND last_login > :last_login');
$pdo->execute($params);
MySQLi provides question mark parameter binding and doesn’t support named
parameters:
$query = $mysqli->prepare('
SELECT * FROM users
88
WHERE username = ?
AND email = ?
AND last_login > ?');
Object mapping
Both PDO and MySQLi can map results to objects. This comes in handy if you
don’t want to use a custom database abstraction layer, but still want ORM-like
behavior. Let’s imagine that we have a User class with some properties, which
match field names from a database.
class User
{
public $id;
public $first_name;
public $last_name;
// PDO
$result = $pdo->query($query);
$result->setFetchMode(PDO::FETCH_CLASS, 'User');
89
if ($result = mysqli_query($mysqli, $query)) {
while ($user = mysqli_fetch_object($result, 'User')) {
echo $user->info()."\n";
}
}
Security
Let’s say a hacker is trying to inject some malicious SQL through the username
HTTP query parameter (GET):
$_GET['username'] = "'; DELETE FROM users; /*"
If we fail to escape this, it will be included in the query “as is” - deleting all
rows from the users table (both PDO and mysqli support multiple queries).
// PDO, "manual" escaping
$username = PDO::quote($_GET['username']);
90
Performance
While both PDO and MySQLi are quite fast, MySQLi performs insignificantly
faster in benchmarks - ~2.5% for non-prepared statements, and ~6.5% for pre-
pared ones. The MySQL extension was even faster.
See also
What is PDO?
PDO stands for “PHP Data Object”, which is one of the many ways available
for accessing databases in PHP. You can think of it as an alternative to using
MySQLi or mysql_ functions (deprecated). However, it’s not specific to MySQL
databases, it can be used with many different types of databases. So with PDO
you can access your database very easily.
You might think, why would I prefer to use it over others? Well, there are many
reasons, but the main one is because it uses the same API regardless of which
database driver you’re using. For example, if you were using SQLite database,
you can switch to MySQL very easily; you have to change only the type of the
driver PDO uses (which you specify in the DSN string), the rest are dependent
on compatibility of SQL/features you used.
PDO currently supports 12 different databases:
• Cubrid
• FreeTDS / Microsoft SQL Server / Sybase
• Firebird
• IBM DB2
• IBM Informix Dynamic Server
• MySQL 3.x/4.x/5.x
• Oracle Call Interface
• ODBC v3 (IBM DB2, unixODBC and win32 ODBC)
• PostgreSQL
• SQLite 3 and SQLite 2
• Microsoft SQL Server / SQL Azure
• 4D
91
PDO also supports named parameters in prepared statements over other exten-
sions.
Connection
try {
$pdo = new PDO('mysql:host=localhost;dbname=your_database_name', $username, $password);
} catch (PDOException $e) {
echo $e->getMessage();
}
Allow exceptions
What would happened if an error occurred while dealing with the database? For
example table we’re retrieving data from doesn’t exist. With default settings,
we would have to use $pdo->errorCode() and $pdo->errorInfo() to fetch the
errors. A better way is to convert all the errors to exceptions:
<?php
try {
$pdo = new PDO('mysql:host=localhost;dbname=your_database_name', $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo $e->getMessage();
}
So we can specify our configurations by using the $pdo->setAttribute()
method. The default value for PDO::ATTR_ERRMODE is PDO::ERRMODE_SILENT.
92
Another option is to convert errors to PHP warnings using PDO::ERRMODE_WARNING.
Having said that, it’s better to stick with exceptions.
Retrieving data
To retrieve data with PDO, use the PDO::query() method. It takes the query
string you want to execute (the normal SQL query) and returns PDOStatement
object. PDOStatement object has various methods for dealing with results.
To retrieve data from PDOStatement you can use PDOStatement::fetch()
or PDOStatement::fetchAll(). PDOStatement::fetch() returns single row
while PDOStatement::fetchAll() returns all rows. Both methods return data
as array by default.
<?php
try {
$pdo = new PDO('mysql:host=localhost;dbname=your_database_name', $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$pdo = new PDO('mysql:host=localhost;dbname=your_database_name', $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
93
As you may know, when executing a query that requires external data from the
user (like id), we should escape it before executing it. For this we can use the
$pdo->quote() method:
<?php
try {
$pdo = new PDO('mysql:host=localhost;dbname=your_database_name', $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Prepared statements
Using PDO::query() is great when the user’s data is hardcoded (no external
data). However, most of our queries use data from outside ($_GET or $_POST).
In these cases we have to be careful of SQL injections. Although we can escape
those data manually, PDO provides a better way by using prepared statements.
Think of prepared statements as a way to prepare your query before executing
it. There are lots of benefits we can get from this. First we have the ability to
execute the same statements multiple time with different data. Also it provides
a safer way to use user’s data in our queries (by binding values).
Here’s an example of how to retrieve data with it:
<?php
try {
$pdo = new PDO('mysql:host=localhost;dbname=your_database_name', $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
94
} catch (PDOException $e) {
echo $e->getMessage();
}
The PDO::prepare() method takes a normal SQL statement and replaces the
user’s data with a placeholder (in this case :id). Then we execute the statement
using the PDOStatement::execute() method, which takes an array that con-
tains the data that should be bound to the placeholders. With this approach,
we make sure that SQL injection is impossible.
We get a PDOStatement object when executing PDO::prepare(). We use this
object to retrieve data related to our executed statement. For example, we
use PDOStatement::fetchAll() or PDOStatement::fetch() to fetch the data
from database. To get the number of rows affected by the last SQL statement
we can use PDOStatement::rowCount().
Notice we represent the placeholder by a colon followed by any name we want.
This is what we call a named parameter. Alternatively, we can represent the
placeholder with a question mark (?), which then we have to bind them accord-
ing to their positions. As a rule of thumb, always use the named parameter
because it’s easier and more readable.
In case you’re wondering what’s the difference between PDOStatement::fetch()
and PDOStatement::fetchAll(), where former is used to fetch only the first
row that matches the query, and the latter is used to fetch all rows and return
them as an array. With PDOStatement::fetch() we can only access the
results by looping over them row by row. PDOStatement::fetchAll() on the
other hand, returns an array which we can deal with it as we want. This is
useful for operations that depend on the overall result.
95
• PDO::FETCH_ASSOC
• PDO::FETCH_BOUND
• PDO::FETCH_CLASS
• PDO::FETCH_OBJ
We’re most concerned with the second and last one. We use PDO::FETCH_ASSOC
to fetch the result in form of an array with string (column names) keys. And
PDO::FETCH_OBJ returns an object of class stdClass with column names as
property names.
Here’s an example of PDO::FETCH_ASSOC:
<?php
try {
$pdo = new PDO('mysql:host=localhost;dbname=your_database_name', $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
CRUD examples
Above examples were only for reading data from database. Let’s review other
CRUD (Create, Read, Update and Delete) operations.
96
Insert
<?php
Update
<?php
Delete
<?php
See also
• PDO tutorial
• PDO Tutorial for MySQL Developers
97
• File System - A collection of individual files accessed by applications pro-
grams.
Advantages of a DBMS
98
• Concurrent, multi-user access to data is not required.
• Need a quick prototype to demonstrate feasibility
• Need an easy way to see the data without having to write a program
• Customers don’t want to install a DBMS and want to get online quickly
MySQL
MySQL is the popular database which has been around since 1995. The
database was released under the GNU GPL License, which made the source
code available. MySQL was issued by MySQL AB, a Swedish company.
MySQL gains popularity as the top database for web application due to the
LAMP and others software stack with AMP acronym. LAMP is an acronym
for Linux-Apache-MySQL-PHP, a software stack which implemented in large
numbers of web application.
Due to the popularity of MySQL, Sun Microsystem, a company that sells com-
puters and the inventor of Java Programming language, acquired MySQL AB
as one of their subsidiary in 2008. Sun made the move in order to strengthen its
position in the Open Source software landscape. Previously, they had acquired
StarOffice in 1999, a German company that produces office suite that became
OpenOffice.
In 2010, Oracle the database giant bought Sun Microsystem and therefore be-
come the owner of MySQL. This made Oracle has the cutting edge in the
database industry. With the ownership of MySQL through the acquisition of
Sun Microsystem, Oracle has two database product offered to their customers,
99
Oracle database for a big corporate customers and MySQL for private use. What
is the different between Oracle Database and MySQL? There are some differ-
ences in terms of their system management and details.
However, there is one downside of SQL to deal with the real life data. In the
business world, most data we have today is a non-structured data, meaning as
the data that cannot be stored in a traditional SQL tabular model, known as
structured data. Structured data is data which have a predefined data model
that can be stored in SQL row and column format. Unstructured data refers to
text-extensive data which may have numbers and structured data in the text,
but it cannot be stored in the traditional SQL database. This unstructured data
is the most of data we deal in daily life. Merril Lynch in 1998 made estimation
that 80% to 90% of business data is originated from unstructured form.
Therefore, most of the data in our life cannot be stored in SQL format.
100
The popularity of MongoDB gains when users love to use MongoDB for it de-
livers its promise as a document-oriented database. The prominent MongoDB
user are Craigslist that has 2 billion of its records stored in MongoDB; Forbes
and New York Times that use it to store their articles and photos; Shutterfly for
its photo database that contained about 18 billion of photos; and Foursquare.
The emergence of web-oriented data has shifted the database landscape with the
arrival of Big Data. As Gartner, a prominent information technology research
and advisory firm has coined the term Big Data in 2001. Big Data is the
data which due to its nature can not be stored in a tabular model of relational
database management system as exist today with the SQL syntax to manipulate
the data.
Big data has grown and the 3-V that Gartner mentioned regarding the data
growth challenges and opportunities were three-dimensional, which are increas-
ing volume (the amount of data), velocity (the speed of data transfer), and
variety (the range of data types and sources) has come to our everyday life. We
are now dealing with that kind of data daily.
Just imagine, we are now dealing with terabyte of data every day in data transfer,
things we hardly found in 5-10 years ago. We also deal with the rapid increasing
speed of data transfer through the advancement of computing technology which
happens real fast. We also deal with the various source of data. The data we
are analyzing is from multiple source in a multiple forms. We have a streaming
video, image and audio video beside text. We practically can tap data anywhere
we want it and anytime we want to in a various format, with multiple size and
multiple source.
This kind of unstructured data with its massive size in a single file hence the
name Big Data is given to them, require a different approach to handle. We need
more than just traditional SQL which is extremely good to manage structured
data in its tabular format of row and column. However the unstructured data
which take up to 90% of data we manage requires a non-tabular storage. We
simply cannot rely on the SQL and traditional relational database management
system to store and manage the data in form of multimedia file, image, blog
and articles. We need a document oriented data which is MongoDB came from
instead of MySQL to manage different kind of data: unstructured rather than
structured data.
Conclusion
101
database, which store document and treat the document as data. It has very
different approach than MySQL. Choose the one that works best for you!
What is ORM?
ORM (Object-relational mapping), also known as O/RM, and O/R mapping is a
programming approach for converting data between incompatible type systems.
Many full stack frameworks provide their own database abstraction approaches
or ORMs.
Standalone database abstraction layers and ORMs to check out:
• Aura SQL - Extension to the native PDO along with a profiler and con-
nection locator.
• DataMonkey - Database ORM for PHP build on top of Doctrine.
• Doctrine - Home to several PHP libraries primarily focused on database
storage and object mapping. The core projects are a Object Relational
Mapper (ORM) and the Database Abstraction Layer (DBAL) it is built
upon.
• Eloquent - Illuminate Database component, used in Laravel framework
but also a standalone component.
• Medoo - Light PHP database framework to accelerate development.
• Propel - A highly customizable and blazing fast ORM library.
• ProxyManager - Library that aims at providing abstraction for generating
various kinds of proxy classes.
• RedBeanPHP - Easy to use ORM for PHP.
• safemysql - A real safe and convenient way to handle MySQL queries.
• Spot ORM - simple and efficient DataMapper built on Doctrine Database
Abstraction Layer.
• Zend\Db - Zend Database Component.
Design patterns
There are mainly two main design patterns used in ORMs - Active Record and
Data Mapper.
As some articles have pointed out (1, 2, 3), ORM is anti-pattern that violates
principles of object-oriented programming.
As an alternative to ORM, there is Pomm. It does not propose an abstrac-
tion layer and is dedicated to Postgres making developpers able to code directly
102
in SQL to fetch entities. It matches object/relational impedance by using the
projection relational operation in order to hydrate flexible instances. It is par-
ticulariry suited to build in-house transactional or reporting applications.
See also
Here are some other useful and updated resources to read or check as well:
• ActiveRecord and the Beauty Lost in Translation
• Lessql - Lightweight and efficient alternative to ORM for PHP.
103
sends the last bit of the stored binary data. This can be an issue because of the
max_connection limit of the database. It should be considered when building
the database platform if the database is intended to be used for file storage.
Caching frequently requested files can be a good solution.
So, using the database as a file storage is possible and performant. It is an
option to consider and depends on your infrastructure. A database that holds all
(binary) data that’s referenced inside the database is a totally synced database.
If this is a must for your project and backup plans, you have to depend on it.
Databases are good for one thing: holding data. They do not care, regardless
of whether it’s 1 byte or 10 gigabytes.
Make sure you have these items sorted out when deploying your application into
production environment:
1. � Cross site scripting (XSS)
2. � Injections
• � SQL injection
• � Directory traversal (path injection)
• � Command injection
• � Code injection
3. � Cross site request forgery (XSRF/CSRF)
4. � Public files
5. � Passwords
6. � Uploading files
7. � Session hijacking
8. � Remote file inclusion
9. � PHP configuration
• � Error reporting
• � Exposing PHP Version
• � Remote files
• � open_basedir
• � Session settings
10. � Use HTTPS
11. � Things not listed
104
Cross site scripting (XSS)
XSS attack happens where client side code (usually JavaScript) gets injected
into the output of your PHP script. This can be through the URL, but can also
be done via a stored technique such as the database.
// GET data is sent through URL: http://example.com/search.php?search=<script>alert('test')<
$search = $_GET['search'] ?? null;
echo 'Search results for '.$search;
Injections
SQL injection
When accessing databases from your application, SQL injection attack can hap-
pen by injecting malicious SQL parts into your existing SQL statement.
• More details available in “What is SQL injection and how to prevent it?”
FAQ.
Directory traversal attack is also known as ../ (dot, dot, slash) attack. It
happens where user supplies input file names and can traverse to parent direc-
tory. Data can be set as index.php?page=../secret or /var/www/secret or
something more catastrophic:
$page = $_GET['page'] ?? 'home';
require $page;
// or something like this
echo file_get_contents('../pages/'.$page.'.php');
In such cases you must check if there are attempts to access parent or some
remote folder:
// Checking if the string contains parent directory
if (strstr($_GET['page'], '../') !== false) {
105
throw new \Exception("Directory traversal attempt!");
}
// Using whitelists of pages that are allowed to be included in the first place
$allowed = ['home', 'blog', 'gallery', 'catalog'];
$page = (in_array($page, $allowed)) ? $page : 'home';
echo file_get_contents('../pages/'.$page.'.php');
Command injection
Be careful when dealing with commands executing functions and data you don’t
trust.
exec('rm -rf '.$GET['path']);
Code injection
Code injection happens when malicious code can be injected in eval() function,
so sanitize your data when using it:
eval('include '.$_GET['path']);
Cross site request forgery or one click attack or session riding is an exploit where
user executes unwanted actions on web applications.
Public files
Make sure to move all your application files, configuration files and similar parts
of your web application in a folder that is not publicly accessible when you visit
URL of web application. Some file types (for example, .yml files) might not be
processed by your web server and user can view them online.
Example of good folder structure:
app/
config/
parameters.yml
106
src/
public/
index.php
style.css
javascript.js
logo.png
Configure web server to serve files from public folder instead of your application
root folder. Public folder contains the front controller (index.php). In case web
server gets misconfigured and fails to serve PHP files properly only source code
of index.php will be visible to public.
• More details is available in the dedicated FAQ: How to Use Configuration
in PHP Applications?
Passwords
When working with user’s passwords hash them properly with password_hash()
function.
• More details is available in “How to work with users’ passwords and how
to securely hash passwords in PHP?” FAQ.
Uploading files
A lot of security breaches happen where users can upload a file on server. Make
sure you go through all the vulnerabilities of uploading files such as renaming
uploaded file, moving it to publicly unaccessible folder, checking file type and
similar. Since there are a lot of issues to check here, more information is located
in the separate FAQ:
• How to securely upload files with PHP? FAQ.
Session hijacking
Remote file inclusion attack (RFI) means that attacker can include custom
scripts:
107
$page = $_GET['page'] ?? 'home'
PHP configuration
Always keep installed PHP version updated. You can use versionscan to check
for possible vulnerabilities of your PHP version. Update open source libraries
and applications and maintain web server.
Here are some of the important settings from php.ini that you should check out.
You can also use iniscan to scan your php.ini files for best security practices.
Error reporting
In your production environment you must always turn off displaying errors
to screen. If errors occur in your application and they are visible to the
outside world, attacker can get valuable data for attacking your application.
display_errors and log_errors directives in php.ini file:
; Disable displaying errors to screen
display_errors = off
; Enable writing errors to server logs
log_errors = on
• More information in the How to show errors in PHP FAQ.
PHP version is visible in HTML headers. You might want to consider hiding
PHP version by turning off expose_php directive and prevent web server to
send back header X-Powered-By:
expose_php = off
108
Remote files
open_basedir
Session settings
109
• session.cookie_secure
For HTTPS sites this accepts only cookies sent over HTTPS. If you’re still
not using HTTPS, you should consider it.
session.cookie_secure = 1
Use HTTPS
What is next?
Above we’ve introduced many security issues. Security, attacks and vulnerabil-
ities are continuously evolving. Take time and check some good resources to
learn more about security and turn this check list into a habit:
• General:
– Awesome AppSec - A curated list of resources for learning about
application security.
– OWASP - The Open Web Application Security Project, organization
focused on improving security of software.
– Security Guide for Developers
– The Basics of Web Application Security, by Martin Fowler.
• PHP focused:
– PHP Manual - A must read security chapter in official documenta-
tion.
– Codecourse videos - Demos and advice on the most common PHP
security areas.
– DVWA, Damn Vulnerable Web Application - Example of unsecure
web application to test your skills and tools.
– OWASP PHP Security Cheat Sheet - Basic PHP security tips for
developers and administrators.
– Securing PHP - Website and books with basic topics and specific
cases in authentication/authorization and exploit prevention.
– SensioLabs Security - SensioLabs Security Advisories Checker for
checking your PHP project for known security issues
– The most forgotten web vulnerabilities - Recommended PDF article.
– websec.io - Dedicated to educating developers about security with
topics relating to general security fundamentals, emerging technolo-
gies and PHP-specific information.
• Tools:
– iniscan - A php.ini scanner for best security practices.
110
– Kali Linux - Penetration testing Linux distribution.
– Observatory by Mozilla - Online security checker.
– versionscan - PHP version scanner for reporting possible vulnerabili-
ties.
– Roave Security Advisories - This package ensures that your applica-
tion doesn’t have installed dependencies with known security vulner-
abilities.
– WebSecTools - List of useful web security related tools.
– OWASP Zed Attack Proxy - Free security tool, available also on
GitHub.
111
$password = 'secretcode';
Right way of hashing passwords is currently using latest PHP version and its
native passwords hashing API which provides an easy to use wrapper around
crypt function.
Example of PHP native password hashing API usage:
<?php
112
// this is the hash of the password in above example
$hash = '$2y$12$VD3vCfuHcxU0zcgDvArQSOlQmPv3tXW0TWoteV4QvBYL66khev0oq';
if (password_verify('secretcode', $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
Another useful function is password_needs_rehash() - which checks if given
hash matches given options. This comes handy in case of server hardware up-
grade and therefore increasing the cost option.
The hash string returned by password_hash() consists of the following parts:
$2y$10$VCbjoi9DnyQyVxf4/RRoFeyOCeMPnCitAG07ZRpivwglmpbP0jOdW
| | | |
| | | |_ password (length depends on algorithm)
| | |
| | |_ salt (22 characters)
| |
| |_ cost (2 characters)
|
|_ algorithm (length depends on algorithm)
So, you can extract raw password hash components like this:
$hash = '$2y$10$VCbjoi9DnyQyVxf4/RRoFeyOCeMPnCitAG07ZRpivwglmpbP0jOdW';
list(, $algo, $cost, $salt_and_password) = explode('$', $hash);
$salt = substr($salt_and_password, 0, 22);
$password = substr($salt_and_password, 22);
Or simply use password_get_info() to get more readable information.
$hash = '$2y$10$VCbjoi9DnyQyVxf4/RRoFeyOCeMPnCitAG07ZRpivwglmpbP0jOdW';
print_r(password_get_info($hash));
Output
Array
(
[algo] => 1
[algoName] => bcrypt
[options] => Array
(
[cost] => 10
)
113
Password hashing in older PHP versions (5.5 and below)
In case you’re still using some older PHP version, there is a way to secure
passwords securely. Since PHP version > 5.3.7 you can use PHP library pass-
word_compat. PHP library password_compat works exactly the same way as
does the native PHP password hashing API, so when you upgrade to latest PHP
you will not need to refactor your code.
For PHP version below 5.3.6 phpass might be a good solution, but try to avoid
these and use the native password hashing API.
Some of the widely used PHP open source projects use different hashing al-
gorithms for passwords because they either support older PHP versions where
password_hash() wasn’t available yet or they already use the latest security
recommendations by PHP security experts:
See also
114
Figure 12: SQL injection
SQL query into the input data you’re using in your SQL queries and instead
unwanted behavior happens.
115
"'DELETE FROM users */"
How to avoid SQL injection in above example? Use prepared statements:
$sql = "SELECT username, email FROM users WHERE id = :id";
mysqli example
When using MySQL database quite you can also use mysqli with prepared state-
ments, or mysqli_real_escape_string() function, however you can just use
more advanced PDO.
// get data is sent through url for example, http://example.com/get-user.php?id=1 OR id=2;
$id = $_GET['id'] ?? null;
if ($mysqli->connect_error) {
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}
// bump! sql injected code gets inserted here. Be careful to avoid such coding
// and use prepared statements instead
$query = "SELECT username, email FROM users WHERE id = " . $id;
if ($result = $mysqli->query($query)) {
// fetch object array
while ($row = $result->fetch_row()) {
printf ("%s (%s)\n", $row[0], $row[1]);
}
116
// in your code you are executing your application as usual
$mysqli = new mysqli('localhost', 'db_user', 'db_password', 'db_name');
if ($mysqli->connect_error) {
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}
// bump! sql injected code gets inserted here. Be careful to avoid such coding
// and use prepared statements instead
$query = "SELECT username, email FROM users WHERE id = ?";
$stmt = $mysqli->stmt_init();
if ($stmt->prepare($query)) {
$stmt->bind_param("i", $id);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_array(MYSQLI_NUM)) {
printf ("%s (%s)\n", $row[0], $row[1]);
}
}
See also
117
<?php
Validation
Always make sure to implement all the server side validations for security mea-
sures and understand the security vulnerabilities behind them.
Directory traversal
To avoid the directory traversal (a.k.a. path traversal) attack use basename()
like shown above or even better rename the file completely like in the next step.
Renaming file avoids duplicate names in the uploaded folder and also avoids di-
rectory traversal attacks. In case you might need the original file name, you can
store the file name in database. For example, renaming file with microtime()
and some random number:
$uploadedName = $_FILES['upload']['name'];
$ext = strtolower(substr($uploadedName, strripos($uploadedName, '.')+1));
$filename = round(microtime(true)).mt_rand().'.'.$ext;
You can also use hashing functions like hash_file(), sha1_file() to build file
name. This method can save some storage spaces when different users upload
the same file.
$uploadedName = $_FILES['upload']['name'];
$ext = strtolower(substr($uploadedName, strripos($uploadedName, '.')+1));
118
$filename = hash_file('sha256', $uploadedName) . '.' . $ext;
Instead of relying on file extension, you can get a mime type of a file with
finfo_file():
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type extension
echo finfo_file($finfo, $filename);
finfo_close($finfo);
For images more reliable but still not good enough check in PHP is with
getimagesize() function:
$size = @getimagesize($filename);
if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) {
throw new \Exception('Image size is not set.');
}
To limit or check the uploaded file size you can check the $_FILES['files']['size']
and the errors UPLOAD_ERR_INI_SIZE and UPLOAD_ERR_FORM_SIZE:
if ($_FILES['pictures']['size'] > 1000000) {
throw new RuntimeException('Exceeded filesize limit.');
}
For better user experience HTML offers accept attribute to limit the file types by
the extension or mime type in the HTML, so user can see the validation errors
on the fly and selects only allowed types of files in their browser. However
browser support is limited at the time of this writing. Keep in mind that client
side validation can be bypassed by hackers in no time. Server side validation
steps explained in previous steps is the more important validation to use.
119
Full example
Let’s take all of the above into consideration and look at some very simple
example:
// check if we have file upload
if (isset($_FILES['upload']) && $_FILES['upload']['error'] == UPLOAD_ERR_OK) {
// Be sure we're dealing with an upload
if (is_uploaded_file($_FILES['upload']['tmp_file']) === false) {
throw new \Exception('Error on upload: invalid file definition');
}
move_uploaded_file($_FILES['upload']['tmp_file'], __DIR__.'../uploads/'.$filename);
// Insert it into our tracking along with the original name
}
Server configuration
Apache
Make sure Apache is not configured to interpret multiple files as same. For
example, images being interpreted as PHP files. Use the ForceType directive to
force the type on the uploaded files.
<FilesMatch "\.(?i:pdf)$">
ForceType application/octet-stream
Header set Content-Disposition attachment
</FilesMatch>
or in case of images:
ForceType application/octet-stream
<FilesMatch "(?i).jpe?g$">
ForceType image/jpeg
</FilesMatch>
120
<FilesMatch "(?i).gif$">
ForceType image/gif
</FilesMatch>
<FilesMatch "(?i).png$">
ForceType image/png
</FilesMatch>
Nginx
On Nginx you can use the rewrite rules, or use the mime.types configurations
file provided by default.
location ~* (.*\.pdf) {
types { application/octet-stream .pdf; }
default_type application/octet-stream;
}
See also
What is configuration?
Applications require a centralized place where settings are stored. All the values
stored here are required to configure the behavior of the application and to define
the resources for other entities of the application. These include usernames,
passwords, database access info, API keys, email settings and similar.
121
The main purpose of configuration is the integrity of the stored values, the
reachability of values for a certain domain, and the static behavior.
Configuration is the domain-aware orchestration of static settings, which
shouldn’t change between a request and a response.
Distribution (mandatory)
Zero-Configuration (optional)
122
With these default values in mind, defining hostname or port is not needed in
common cases, when the targeted service is located at localhost and listening
on port 3306.
Caching (recommended)
Formats
Application configuration can be defined in all sorts of formats and places. From
the regular PHP files, to other file formats such as YAML, INI, XML, JSON,
NEON and similar. It can be defined even in the database.
The format of the defined application depends on the complexity of what must
be configured and the wanted complexity of the configuration definition. Some
configuration formats are limited to a specific set of definition utilities, other
formats are open side effects to the user land that may have an impact to the
configuration integrity.
Choose the configuration format based on these suggestions and what is suitable
for your project case or better readability for you.
PHP files
<?php
// config/config.php
$configuration = [
'database' => [
'hostname' => 'localhost',
'port' => 3306
'name' => 'db_name',
'username' => 'db_username',
'password' => 'db_secret_password',
]
];
PHP files are actually scripts that define an object, array or a mixture of both.
The major benefit of this format is the validity of the file format which is directly
enforced by the PHP parser. If opcode caching is available, this format will be
also pretty fast.
123
The major downside of this format is the abuse possibility. You can quickly
invalidate the static state of a configuration definition by utilizing conditions
or other stuff that might change the returning value which is sensitive to the
environment or request.
YAML
# config/config.yml
database:
hostname: 'localhost'
port: 3306
name: 'db_name'
username: 'db_username'
password: 'db_secret_password'
YAML is a format that unifies the benefits of JSON and XML into a single
but different format. YAML is both, a format that is intended to act as a data
notation and as a file format to define documents. YAML has also a lot of
different features that are not common to documents or object notations (entity
linking). YAML supports widely the same syntax as JSON does.
To parse YAML files there are available 3rd party libraries such as Symfony
Yaml Component, or the Yaml PHP Extension, which isn’t bundled with PHP.
INI
; config/config.ini
[database]
database_hostname=localhost
database_port=3306
database_name=db_name
database_username=db_username
database_password=db_secret_password
INI files define data in a simple way. The INI format is less complex than other
formats. Whatever you want to assign to a field would be associated as it would
be associated in PHP. INI files can have groups as well, but does not support
higher structs (arrays, objects).
Parsing of INI files can be done with PHP parse_ini_file() and pase_ini_string()
functions.
XML
124
<database default="true">
<server hostname="localhost" port="3306">
<environment dbname="db_name">
<auth username="db_username" password="db_secret_password" />
</environment>
</server>
</database>
</configuration>
XML documents relay on specific entities and have a Document Object Model
that requires a lot of knowledge to define proper documents. XML files are
prone to failure due to its high efforts to define the document.
The major benefit of XML documents is they can easily transported to other
formats or structures using XSLT or traditional scripts. XML is the most flexible
format because of the descriptive nature of XML.
The major downside of XML is, it is not intended to be human readable as other
formats are.
There are multiple ways to parse XML format. For example, there is XML
Parser extension enabled by default.
JSON
{
"database": {
"hostname": "localhost",
"port": "3306",
"name": "db_name",
"username": "db_username",
"password": "db_secret_password"
}
}
JSON is actually an Object Notation not a real file format. Since composer
enters the PHP universe, JSON is the considered data structure for statically
applied configuration in files with the file extension: .json.
The major benefit of JSON is, it remains always to the same syntax and
does restrict the configuration definition context to strings, integers, floats and
booleans.
The major downside of JSON is, it is an object notation. No inline documen-
tation allowed and you actually configure your application with a format that
was intended to be used as to transport data from end-point to end-point.
To parse JSON format, there is available json_decode().
125
NEON
# config/config.neon
database: mysql(
hostname=localhost,
port=3306,
name=db_name,
username=db_username,
password=db_secret_password
)
NEON is a YAML derivate invented by the guys of the Nette Framework, that
adds entities to the definition model of YAML.
Package nette/neon can parse NEON files.
Performance
Active caching
Active caching observes always configuration files each time your application is
bootstrapped. Once a configuration file has changed, the configuration cache
invalidates and a rebuild process for the cache will be executed.
Active caching raised performance peeks to your application whenever the con-
figuration cache invalidates a segment (domain) of your configuration. Active
caching is the caching mechanism to choose when performance peaks do not
deal damage to the overall application performance (small applications with
less traffic).
126
Passive caching
Passive caching relays on maintainer actions to enforce the cache building for
the application after changes are made to the configuration files.
Passive caching ensures that no performance peeks hit your application. The
built configuration cache is always committed to the server by the maintainer
of the application. Passive caching is the caching mechanism to choose when
aiming for a very balanced application performance (applications with high
traffic).
Environments
Types of configuration
127
• Application configuration
These define the behavior of the application and depend on the environ-
ment where the application is running. For example, the debugging turned
on or off, database type (for example, you can use different database type
in testing), locale settings and similar.
– Fixed application configuration
These don’t change very often during the certain application version.
For example database type, number of items shown per page etc.
– Variable application configuration
These change more frequently in certain application version. For
example user settings (showing/hiding signature in forum topics, de-
fault currency used in e-store for signed in users), settings meant
to be changed by non-developers (contact emails, Google sitemap
settings) etc.
Bad practices
Using PHP constants to define configuration values might seem like a good
choice because of the global state:
<?php
// config/config.php
define('DATABASE_NAME', 'db_name');
define('DATABASE_USERNAME', 'db_username');
define('DATABASE_PASSWORD', 'db_password');
However this is not a good practice for the following reasons:
• You are polluting the global namespace and can have compatibility issues
from other libraries or code that might define same constant.
• Their value cannot be changed in the code, which might have issues when
testing code.
• Difficult code refactoring in case they were used in multiple places
• Limited set of types available (only boolean, integer, float, string, array
and resource).
Some of the limitations mentioned above can be avoided by using class constants.
This should be used only for configuration values that never or very rarely change
in certain application version. For example, maximum number of elements
shown per page and similar:
<?php
class Article
128
{
const MAX_ITEMS_PER_PAGE = 10;
//...
}
$limit = Article::MAX_ITEMS_PER_PAGE;
Limitation of this is still difficult changing of these values in testing environment
for example.
Singleton pattern
class Config
{
/**
* @var Config
*/
private static $instance;
/**
* @var array
*/
private static $values = [];
/**
* Instantiation can be done only inside the class itself
*/
private function __construct() {}
/**
* @return Config
*/
public static function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
129
}
/**
* Set configuration value by key.
*
* @param string $key
* @param mixed $value
*/
public static function set($key, $value)
{
self::$values[$key] = $value;
}
/**
* Get configuration value by key.
*
* @param string $key
* @return mixed
*/
public static function get($key)
{
if (isset(self::$values[$key])) {
return self::$values[$key];
}
return null;
}
/**
* Cloning singleton is not possible.
*
* @throws Exception
*/
public function __clone()
{
throw new Exception('You cannot clone singleton object');
}
}
$config = Config::getInstance();
$config->set('database_username', 'db_username');
However using singleton pattern reduces testability as well. Instead, a better
practice is to use the dependency injection, container and repository patterns.
130
Misconception of configurations
Everything that is not static in the moment the configuration is defined should
not be considered as configuration. You should always utilize the format that
allows you to define exempts (like entities in NEON) that provides a structure
that allows the implementation to fit the setting to an environment’s sensitive
state.
A neon example:
# general
debug: whenIn(server=REMOTE_ADDR, [::1, 127.0.0.1], if=true, else=false)
environment: sapi({
php_cli: cli
}, default=www);
Translation data should not be part of the configuration, no matter which kind
of translation distribution format was chosen. Translations always relay on a
non static part.
Security
131
Environment variables
<Directory "/var/www/project/public">
AllowOverride All
Allow from All
</Directory>
</VirtualHost>
On Nginx servers environment variables can be set with fastcgi_param direc-
tive in configuration file where the fastcgi_params is being included:
# /etc/nginx/sites-available/example.com
location ~ \.php$ {
#...
include fastcgi_params;
fastcgi_param APP_DATABASE_USERNAME db_username;
fastcgi_param APP_DATABASE_PASSWORD db_secret_password;
#...
}
When your application is running in PHP CLI (which does not use web server),
environment variables must be set also with export (for Linux servers):
export APP_DATABASE_USERNAME="db_username"
export APP_DATABASE_PASSWORD="db_secret_password"
In PHP environment variables can be than accessed with getenv():
<?php
// config/config.php
$configuration = [
132
'database_username' => getenv('APP_DATABASE_USERNAME'),
'database_password' => getenv('APP_DATABASE_PASSWORD'),
];
PHP dotenv
A very useful PHP library that adds best practices to your application when
working with environment variables for configuration is PHP dotenv.
After installation with Composer:
composer require vlucas/phpdotenv
Add the .env file to the root of your project:
APP_DATABASE_USERNAME="db_username"
APP_DATABASE_PASSWORD="db_secret_password"
In PHP the configuration values can be than accessed like environment variables
explained above:
<?php
require __DIR__.'/../vendor/autoload.php';
$dbUsername = getenv('APP_DATABASE_USERNAME');
Worth noting is that environment variables are still exposed on the system level.
Be careful to not output them. For example, with phpinfo(). Important to
understand is, when the environment variables are useful for your case scenario
and when to use other tools like Vault, Chef or similar.
Git repositories
When committing code to the source control (Git), avoid adding configuration
files to the commits. In case of Git, ignore the configuration files containing
sensitive configuration values with .gitignore:
#.gitignore file which omits committing config.php file to the Git repository
/config/config.php
133
Encapsulation
The infrastructure configuration don’t change during the running of the appli-
cation. In case you don’t have simple access to the production environment
infrastructure configuration values (database credentials) but still need to de-
velop application independently and frequently add more infrastructure related
configuration in the next version of the application, you can use encapsulation:
<?php
// config/database.php
return [
'database_name' => 'db_name',
'database_username' => 'db_username',
'database_password' => 'db_secret_password',
];
And use it in your application configuration with the rest of the infrastructure
configuration:
<?php
// config/config.php
return array_merge([
'fb_app_id' => 123456,
'fb_app_secret' => 'facebook_app_secret',
],
require(__DIR__.'/database.php')
);
134
Serialization is useful for storing values without losing their type and structure.
Above PHP configuration example can be represented in serialized format using
the serialize():
a:3:{s:13:"database_name";s:7:"db_name";s:17:"database_username";s:11:"db_username";s:17:"da
SQLite
Many times you might be tempted to access the configuration values in the
application code directly:
<?php
class Database
{
private $name, $username, $password;
/**
* Constructor.
*/
public function __construct()
{
$this->name = getenv('APP_DATABASE_NAME');
$this->username = getenv('APP_DATABASE_USERNAME');
$this->password = getenv('APP_DATABASE_PASSWORD');
}
//...
}
Issue with such approach is difficult maintaining of the code when scaling and
testing. The other not good enough step is injecting the configuration handler
directly in the needed class:
135
<?php
class Config
{
/**
* @var array
*/
private $values;
/**
* Constructor.
*
* @param array $values
*/
public function __construct($values)
{
$this->values = $values;
}
/**
* Get configuration value by key.
*
* @param string $key
* @return mixed
*/
public function get($key)
{
return $this->values[$key];
}
}
class Database
{
private $name, $username, $password;
/**
* Constructor.
*
* @param Config $config
*/
public function __construct($config)
{
$this->name = $config->get('database_name');
$this->username = $config->get('database_username');
$this->password = $config->get('database_password');
}
136
}
// ...
class DatabaseAdapater
{
protected $inhibitor = null;
protected $instance = null;
private $name;
private $username;
private $password;
private $hostname = '127.0.0.1';
/**
* Constructor.
*/
public function __construct()
{
$this->inhibitor = Closure::bind(
function ($name = null, $username = null, $password = null, $hostname = null): P
return new PDO(
'mysql:dbname='.($name ?? $this->name).';host='.($hostname ?? $this->hos
$username ?? $this->username,
$password ?? $this->password
);
},
$this,
DatabaseAdapter::class
);
}
/**
* Set database name.
*
* @param string $name
*/
public function setName(string $name)
137
{
$this->name = $name;
}
/**
* Set database username.
*
* @param string $username
*/
public function setUsername(string $username)
{
$this->username = $username;
}
/**
* Set database password.
*
* @param string $password
*/
public function setPassword(string $password)
{
$this->password = $password;
}
/**
* Set database hostname.
*
* @param string $hostname
*/
public function setHostname(string $hostname)
{
$this->hostname = $hostname;
}
/**
* Get Database adapter instance.
*
* @return DatabaseAdapter
*/
public function getInstance(): PDO
{
if ($this->instance instanceof PDO) {
return $this->instance;
}
138
}
}
class Database
{
/**
* @var DatabaseAdapter
*/
private $adapter;
/**
* Constructor.
*
* @param DatabaseAdapter $adapter
*/
public function __construct(DatabaseAdapter $adapter)
{
$this->adapter = $adapter;
}
}
Conclusion
See also
139
• Symfony Config component
• Twelve Factor App - Configuration chapter of the Twelve Factor App
book.
• werx/config - Use environment-specific configuration files in your app.
• Zend Config
See also
140
See also
See also
• Paragonie Blog
• How to Work With Users’ Passwords and How to Securely Hash Passwords
in PHP?
• Obfuscation (software)
141
Figure 13: PHP Frameworks
142
structure of a project.
There are many existing, well established and secure open source frameworks
with large communities behind them. Rather than reinventing the wheel, many
developers use them to build web applications. There is NO best and NO
official PHP framework, because different purposes and different projects require
different tools and approaches.
Using established, existing open source frameworks is strongly advised when
working in a team. A framework can provide developers with a common same
set of standards and with better interoperability for when they build applications
together.
Before diving into a PHP framework, get familiar with some advanced concepts
such as OOP, design patterns, ORM, authentication, MVC (model view con-
troller), etc. For bigger projects, using a popular open source framework instead
of a custom framework and instead of procedural programming is advised.
Before understanding modern open source PHP frameworks, check out Com-
poser; A dependency manager for PHP.
In your career path, you will not need to know all of them, but you should learn
how to use few of the frameworks that are widely used in the industry or that
are important to you. Organizations and companies are always moving towards
modern, popular established frameworks, so predicting which framework will
get you a job in the PHP market today is a task for a prophet or a fortune
teller, and it is therefore almost impossible.
You can check the popularity trends in PHP community and check the most
popular ones (according to the stars on GitHub), but don’t get fooled by such
comparison charts. Each organization can move towards something else sooner
or later.
Learning some complex PHP frameworks can have a steep learning curve.
According to the architecture the framework itself is built upon, there are three
major types of frameworks that we will use to categorize them in this FAQ:
Component frameworks
Component frameworks are built and decoupled into separate components that
you can use in your application independently of other components. You can
just use some components or all of them. Most of component frameworks can
also be a full stack framework (described in the next section) at the same time.
• Aura
143
• Kohana
• Laravel
• Nette
• Symfony
• Zend Framework
Micro-frameworks
144
• Horus
• Kraken - Distributed and async PHP framework.
• Lumen - Micro-framework by Laravel.
• MicroMVC
• Phlyty - Micro-framewok written using ZF2 components.
• Proton - StackPHP-compatible micro-framework.
• Silex - Micro-framework based on Symfony2 components.
• Slim
• Yolo
Miscellaneous
Other resources
Related FAQs
145
• When working in a team, people that already know the open source frame-
work used by a project can join the project faster.
• Better quality and a lot of bugs that have been identified and fixed, that
your custom framework hasn’t been tested for in a many projects yet.
For creating a framework you will have to know OOP, design patterns, ORM,
authentication, MVC (model view controller) and other advanced concepts.
See also
Here are listed some useful resources and tutorials that can also help you create
your own modern and quality PHP framework.
• Building your own framework on top of Symfony components - Build a
modern PHP framework on top of quality Symfony components.
• Frameworkless - Tutorial how to create custom framework with Composer
and PHP packages and components.
• No Framework tutorial
• PHP Frameworking - Introduction to frameworks and how to create your
own framework.
CakePHP framework
CakePHP is a MVC Rapid Development Framework for PHP.
See also
CodeIgniter framework
CodeIgniter is a powerful PHP framework with a very small footprint, built for
developers who need a simple and elegant toolkit to create full-featured web
146
applications.
CodeIgniter has a lean MVC framework, with enough capabilities to improve
productivity, while providing for third-party addons/plugins for additional func-
tionality.
See also
Laravel framework
Laravel is popular and simple to use component based PHP framework.
See also
Some useful resources to check when learning and working with Laravel:
• Awesome Laravel - A curated list of bookmarks, packages, tutorials, videos
and other cool resources from the Laravel ecosystem.
• Laracasts - Laravel video tutorials, free and paid.
• Laravel News
Symfony framework
Symfony is a set of reusable PHP components and a framework.
Best way to get to know Symfony is to go through a quick tour - four chapters,
each 10 minutes long. After that, reading the documentation is advised and is
the best way to learn it thoroughly.
Symfony uses bundles for applications and to extend and reuse functionality
in them. A large and vibrant community that has evolved around Symfony
provides bundles for almost anything. They can be found at KpnBundles.
You can also get certified or meet the community at one of the Symfony events.
147
See also
Yii framework
Yii is a high-performance PHP framework.
Resources
• Documentation
See also
Zend framework
Zend Framework - Enterprise and component based PHP Framework from Zend.
See also
148
Writing quality code and code analysis
Beside writing tests, there are more factors that affect the quality of your code.
Let’s check some tools for PHP that can improve your code quality.
PhpMetrics
PhpMetrics is a very convenient static analysis tool for your code and your PHP
projects.
It can be installed with Composer or by downloading phar:
composer global require 'halleck45/phpmetrics'
149
phpmetrics --report-html=myreport.html /path/of/your/sources
PhpMetrics can even interact with Jenkins and Sonar.
After running PhpMetrics from terminal you get an HTML file that looks some-
thing like this:
See also
150
How to test PHP code?
Testing code is an important part of development and should not be avoided. It
adds extra time to development but it also improves code quality and saves you
more time when you’re adding new features, or refactoring your code without
breaking something.
You’re testing your code already between the development itself without maybe
realizing. When you add some part of code, you either check for the correct
output or response in browser, database etc. However this way not all cases are
considered and it is not repeatable and automated. Soon you need something
more reliable and organized.
In PHP there are available many testing tools and frameworks. Testing can be
categorized based on the approach.
TDD is a software development process in which you repeat very short develop-
ment cycles in which you write code that passes or intentionally fails.
Unit testing
Probably the most used tool and de-facto standard for unit testing in PHP is
the PHPUnit testing framework. It has an awesome manual so do read it and
start using TDD.
Functional testing
By using tools you create automated tests, where application is actually used
instead of just checking certain parts of code.
• Selenium
• Mink
• Codeception
151
Testing spaghetti code
See also
StoryBDD
There are two types of BDD - StoryBDD and SpecBDD. StoryBDD focuses
on business and features. Here is a quick and simplified example of a login
functionality based on Behat framework. By communicating with stackeholders,
developers create login scenario (or an example in BDD):
152
Feature: Login
I want to have access to certain page only if I provide
correct username and secret password
SpecBDD
See also
153
How to debug PHP code? What is debugging?
Debugging is a process to find and reduce number of bugs in your code. An
unavoidable but not particularly fun part of building applications. There are
multiple approaches to debugging available for PHP, but before that, you must
set your development environment up in such a way as to be able to see mean-
ingful errors.
Index
• Prerequisites
• Types of errors
• Syntax errors
• Warnings
• Notices
• Fatal errors
• var_dump/print_r
• Xdebug
• phpdbg
• Symfony VarDumper
• Zend Debugger
• FirePHP
Prerequisites
Turn on error reporting and set the appropriately useful error reporting level,
either in your development code, or better yet, in your php.ini file:
<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL | E_STRICT);
Types of errors
Syntax errors
These are caused by a typo in your code. Examples include missing semicolons,
quotation marks, incorrect variable definitions and so on.
Warnings
Warnings will not break the execution of the script like syntax errors. Warnings
are to notify you when you’ve made a mistake somewhere in your code but when
154
the script can still execute.
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the fu
Notices
Notices will not break the execution of the script (just like with Warnings), but
they are important pieces of information for debugging your application.
Fatal errors
These errors are quite simple to debug, due to the script will cease execution
when a fatal error occurs. Example of fatal errors include undefined functions,
classes and so on.
Fatal error: Call to undefined function bootstrap() in /var/www/project/index.php on line 23
var_dump/print_r
One of the most common and simple techiques for PHP debugging is using
var_dump or print_r functions:
$date = '28. 04. 2015';
$start = DateTime::createFromFormat('d. m. Y', $date);
die(var_dump($start));
That way you can quickly end execution and check the variable when you want
to know more.
Xdebug
phdbg
155
Symfony VarDumper
You can debug better by using the dump() function of Symfony VarDumper
component than is otherwise possible with using var_dump or print_r.
<?php
require __DIR__.'/vendor/autoload.php';
// create a variable, which could be anything!
$someVar = '...';
dump($someVar);
Zend Debugger
The Zend Debugger is a PHP extension that should be installed on your Web
server in order to perform optimal remote debugging and profiling using Zend
Studio.
FirePHP
FirePHP is a debugger that enables you to log to your Firebug Console using a
simple PHP method call.
<?php
FB::log('Log message');
FB::info('Info message');
FB::warn('Warn message');
FB::error('Error message');
156
• Symfony
Many advanced PHP IDEs and editors also offer code refactoring via plugins
and extensions. With predefined common coding styles such as PSR-1 and PSR-
2, with refactoring code, automatic code generation, autocomplete and similar
things, consistently writing standardized PHP code can be done with ease.
The more you write code, the more you will understand the importance in using
common style guides. Especially when working with source code control (eg,
Git, coworkers), or just to be consistent in general.
See also
See also
157
What is Composer?
To not reinvent the wheel you can reuse code in different projects with plugins,
packages, frameworks and similar libraries. Developing and managing release
versions of dependencies in projects on your own can quickly become cumber-
some.
Composer is de-facto standard command line tool for managing dependencies
in PHP.
Packages can be located and developed separately in any public open source
or private proprietary location. Main repository for open source packages is
Packagist.org.
Installation
Download and install composer.phar Phar (PHP Archive) file according to the
documentation. Recommended is to install it globally so you can call composer
from any folder:
$ composer command [options] [arguments]
Usage
Composer will add and use the following files in your project:
• composer.json - Metadata file with information about dependant pack-
ages versions autoloading your PHP classes and more.
• composer.lock - After adding dependencies Composer creates this meta-
data file with locked dependency versions for project. If you’re working
on package, don’t include it in the code repository. If you’re working on
application, add it to code repository.
• vendor/ - Automatically managed folder with installed libraries. Don’t
include it in the code repository.
• vendor/autoload.php - Automatically managed PHP classes autoload
mapping file.
158
composer.json
When starting a new project you can use the interactive init command to
create composer.json file:
$ composer init
composer.json is located in the root folder of your project:
{
"name": "vendor/project-name",
"description": "Demo application",
"type": "project",
"require": {
"php": ">=5.6.0",
"nesbot/carbon": "~1.14"
},
"require-dev": {
"phpunit/phpunit": "5.2.*"
},
"license": "MIT",
"authors": [
{
"name": "John Doe",
"email": "john.doe@domain.tld"
}
],
"minimum-stability": "dev"
}
Managing dependencies
159
Tips
See also
Make sure to read the official documentation to learn Composer in details. Other
useful links to check:
• Climb - Tool that finds newer versions of project dependencies.
• Composer as a service - Give your composer.json, get the corresponding
vendor.zip, fast.
• Melody - One-file Composer scripts.
160
• Composr CMS
• concrete5
• Contao
• Directus
• DokuWiki
• Dotclear
• Drupal
• Exponent CMS
• eZ Platform / eZ Publish
• Geeklog
• GetSimple CMS
• Habari
• ImpressCMS
• ImpressPages
• Jamroom
• Jarves
• Joomla!
• Kajona
• Known
• Magento
• MediaWiki
• Midgard CMS
• MODX
• Moodle
• Novius OS
• Nucleus CMS
• OctoberCMS
• papaya CMS
• pH7CMS
• Phire CMS
• PHP-Nuke
• phpWiki
• pimcore
• PivotX
• Pixie (CMS)
• Pluck
• PmWiki
• Prestashop
• Serendipity
• SilverStripe
• SMW+
• SPIP
• Textpattern
• Tiki Wiki CMS Groupware
• TYPO3
• Wolf CMS
161
• WordPress
• Xaraya
• XOOPS
CMS is usually a complete out of the box solution. Content management frame-
work (CMF) on the other hand is a system, which uses reusable components
and is a level between a framework and a CMS. It enables you to make your
CMS more customized. Many CMSes listed above have characteristics of CMF
as well however the following examples are some more notable content manage-
ment frameworks by the definition:
• Symfony CMF
See also
162
How to work with Excel in PHP?
PHPExcel library can be used to read, create and write spreadsheets. It can be
installed via Composer. Use the provided Composer instructions below.
Simple and recommended way to install PHP library using Composer is with
composer require command.
$ composer require phpoffice/phpexcel
The alternative way is to manually add the code below in composer.json file:
"require": {
...
"phpoffice/phpexcel": "1.8.1"
...
}
After adding above in composer.json, install the newly added library and up-
date all the dependency versions for the current project with composer update:
$ composer update
Once new project’s dependency is installed we can start working with PHPExcel.
Example
// Set properties
echo date('H:i:s') . " Set properties\n";
$objPHPExcel->getProperties()->setCreator("Maarten Balliauw");
$objPHPExcel->getProperties()->setLastModifiedBy("Maarten Balliauw");
163
$objPHPExcel->getProperties()->setTitle("Office 2007 XLSX Test Document");
$objPHPExcel->getProperties()->setSubject("Office 2007 XLSX Test Document");
$objPHPExcel->getProperties()->setDescription("Test document for Office 2007 XLSX, generated
// Rename sheet
echo date('H:i:s') . " Rename sheet\n";
$objPHPExcel->getActiveSheet()->setTitle('Simple');
// Echo done
echo date('H:i:s') . " Done writing file.\r\n";
Refer to the latest version of PHPExcel on Github to learn more.
See also
Learn more:
• Read and Write Microsoft Excel Files in PHP: Part 1, and Part 2.
164
How to add pagination?
See also
165
PHP packages
Here is a collection of some useful libraries, packages and scripts you will find
useful when developing with PHP.
Administration
Images
Pagination
Payment gateways
Excel
• PHPExcel
Authentication
• HybridAuth - OAuth login library for various social network such as Face-
book, Twitter, Google+…
• oauth2-server-php - OAuth 2 login Library to make your own OAuth 2
Appliction
• auth0-PHP - PHP SDK for auth0 service
166
Bitcoin/Altcoin
Serialization
Encryption
• Time lock encryption - This class can encrypt data using key generated
for a time period.
• Fernet - Fernet takes a user-provided message (an arbitrary sequence of
bytes), a key (256 bits), and the current time, and produces a token, which
contains the message in a form that can’t be read or altered without the
key
MySQLi
PDO
ORM
167
PDF
Sanitization
MarkDown
Geometry
What is API?
API, which stands for “Application programming interface”, is a set of routines,
protocols, and tools for building software applications.
Useful tools
Documenting
168
See also
What is REST?
REST stands for “Representational State Transfer.” It was claimed by Roy
Fielding in his doctor dissertation in 2000.
The term RESTful refers to web services implementing such a REST architec-
ture.
See also
169
• Fusio - Fusio is an open source API management platform which helps to
build and manage REST APIs.
• Slim - Slim is a PHP micro framework that helps you quickly write simple
yet powerful web applications and APIs.
• Api Platform - The ultimate PHP framework to build modern web APIs.
See also
IDE vs editor
There are many open-source and proprietary text editors and IDEs available
on the market today. Difference between editor and IDE is in functionalites
and extensions that IDE holds over a plain text editor. Many editors have
capabilities to be extended to a full IDE as well but experience in dedicated
IDEs are better for complex and bigger projects. IDE has more features than
editor but also takes more resources on your computer.
170
Listing tools always leads to flamewars between users using them convincing
each other to “buy” theirs. We’re not trying to start a flamewar here but to
only show some of the good tools you should check out for your development
and pick the right one for you.
Many times you will need both - editor and IDE. IDE for bigger project itself
and editor for quick edits here and there. If you will be working in command
line some text-based editors such as Vim or Emacs will be a must to use.
IDEs
Editors
171
Client side development
Most IDEs listed above also take care of client side development part i.e. HTML,
CSS, JavaScript and web publishing but sometimes some dedicated tools for that
are irreplaceable:
• Dreamweaver - proprietary tool
• KompoZer - free web authoring system that combines web file management
and easy-to-use WYSIWYG web page editing.
• WebStorm - JavaScript IDE also useful for complex complex client-side
development and also backend Node.js development.
Atom is an advanced open source text editor for developers. This article will
explain some useful packages and tricks how to make the most out of it when
developing with PHP.
IDE or editor?
172
One of the recommended ways to develop applications is for example, to use
an IDE for developing the project at large and an editor for quick edits across
different projects or folders. However you can successfully develop PHP projects
also without an IDE. Explore and try different tools to see what suits your
development workflow. Make sure that the tools you use, make you productive.
Atom installation
Installation of Atom is as simple as it gets and works on all widely used operat-
ing systems (Linux, Windows and macOS). Visit the Atom homepage and the
releases on GitHub to download the installation for your system.
Themes
By default, Atom comes with multiple nice themes you can use out of the box.
Additional themes can be obtained from Atom themes repository.
Configuration
173
Figure 18: “Atom Preferences”
The configuration files are saved in your home directory ~/.atom, so you can
backup them to your dotfiles and have a portable configured development envi-
ronment for multiple development machines.
Some of the portable files in that folder are config.cson, keymap.cson,
snippets.cson, and styles.less. The installed packages can also be
exported to a custom list file via command line:
apm list --installed --bare > packages.list
When you will need to reinstall Atom, the saved packages list can be used to
quickly install all your favorite packages:
apm install --packages-file packages.list
Code style
By default, Atom already supports syntax highlighting and snippets for a lot
of languages. For PHP it uses the language-php package. To set your pre-
ferred coding style such as spaces/tabs, line ending, and similar go to Edit >
Preferences > Packages and type language-php and set some default behav-
iors you use. In the following section we’ll check some packages that can improve
and extend managing code style in your PHP project.
Packages
Atom packages extend core editor functionality. They can be obtained from the
Atom packages repository.
174
Packages can be installed via the GUI Edit > Preferences > Install or with
the command line Atom package manager apm:
apm install package-name
By default, Atom provides basic editing capabilities and everything you need
to write PHP code. There are many packages to extend and make writing
PHP code more efficient and provide a much better development experience. If
you are used to some advanced IDE functionality already, you’re familiar with
things such as autocompletion, code inspection, generating code snippets and
more. There are a lot of Atom packages for PHP development, however you
might want to take a look at some of the following highlighted packages for
having PHP development more efficient.
Atom beautify
Did you get a code that is not suited for your coding style? The atom-beautify
package is a must check for having a consistent code style and to beautify the
code on the fly. It cleans the code for multiple languages according to the
predefined code style settings. To successfully beautify PHP code, you must
also separately install either the php-cs-fixer or the PHP Code Sniffer.
175
Editorconfig
To have a consistent code style across different editors for multiple people, you
might want to take a look at Editorconfig initiative. The editorconfig package
adds support for .editorconfig file to Atom.
PHP Integrator
PHP Integrator shows tooltips (e.g. for methods and classes) in your PHP source
code.
PHP Integrator includes call tips with parameter information in your PHP
source code for functions and methods.
With PHP Integrator installed and project prepared, you can check the following
additional packages from PHP Integrator collection:
• PHP Integrator Autocomplete Plus
176
Figure 21: Atom PHP Integrator tooltips
177
The php-integrator-autocomplete-plus package provides autocompletion for
your PHP source code. By indexing project files, autocompletion works also
for classes from project and Composer’s vendor folder. Class is automatically
added to the list of used classes on top of a current PHP file.
• PHP Integrator Navigation
PHP Debug
The php-debug package is PHP code debugging package using the Xdebug ex-
tension.
178
Figure 25: Atom PHP Integrator Refactoring
179
PHP Server
Above we’ve gone through some of the useful packages for PHP. To improve
development experience and add additional functionality you might want to
check these awesome packages.
Minimap
The minimap package adds file preview on the sidebar. Once you get used to
it, it is a must have package in your collection. It is useful for easier overview
of the source code and quicker navigation over the file.
Highlight Selected
The highlight-selected package highlights the current word selected when double
clicking. If you’re using the minimap package there is also minimap-highlight-
selected.
Atom Minify
The atom-minify package minifies JavaScript and CSS files. It is useful when
you come across a need to manually quickly minify a required file on the fly.
180
Todo Show
The todo-show finds all TODO, FIXME, CHANGED and similar comments in your
project and shows them in a nice overview list.
The color-picker package opens color picker for color codes such as HEX by using
right click or pressing CMD-SHIFT-C/CTRL-ALT-C. Pigments displays colors for
color codes in the editor itself.
Ctrl-dir-scroll
The ctrl-dir-scroll package is convenient for users who are used to shortcuts from
some other IDEs and editors. By default, Atom uses Ctrl and up/down keys
to move the line up and down. This package adds scrolling up and down with
keyboard - CTRL and up/down keys.
Project Manager
Emmet
Docblockr
File Icons
The file-icons package adds icons in tree view for recognized file types.
181
• Laravel
• Symfony
• WordPress
Docker
Keyboard shortcuts can make you more productive. These are some of the
keyboard shortcuts you might find useful. On Linux and Windows use the Ctrl
key, and on macOS the Cmd.
• Comments: Ctrl + /
Comments/uncomments selected code.
• Find and open a file: Ctrl + p
• Command Palette: Shift + Ctrl + p
Command palette simplifies access to find and run available commands instead
of going through the menu manually.
• Multiple cursors:
With Ctrl and left mouse click you can add more cursors to the editor which
behave the same as a single cursor. This is useful for changing multiple same
values on different parts of the file.
Performance
Having installed and enabled a lot of packages might also slightly slow down the
performance. When opening very large files (few MB), the editor performance
can decrease and the editor becomes unresponsive. Currently Atom supports
files up to few MB (~10MB), and works a bit better on Linux and macOS
182
Figure 28: Atom Command Pallete
183
systems. This has been already noted on Atom issue tracker, so it might be
fixed in the future.
How to deal with the issue of very large files (for example, log files)?
Many GUI editors and IDEs have same issues when opening and working on
large files. People usually solve this with the command line tools like grep, cat,
head, tail, and sed. For compressed files there are also zless, zmore, zcat,
and zgrep.
Learning curve
At first, Atom might seem a bit overwhelming, specially to fine tune it for your
needs. So, as with every tool, take some extra time and read the documentation
to get to know it in more details.
Multiple community packages can have the same keybindings and in this case
need to be reconfigured manually.
Which packages to install and which not is your choice and preference. For
PHP development in particular, many tasks can be done by using native tools
in the command line instead of using editor plugins. For example, unit testing,
running Docker containers, deployment, running up local development server
and similar.
Atom truly is a magnificent editor worth taking a look. It has a huge community
behind and it is open sourced.
See also
What is GIT?
Git is one of the most popular free and open source distributed version control
system designed to handle everything from small to very large projects with
speed and efficiency.
Working on code requires a version control system and Git is highly recom-
mended for versioning PHP code, whether you work on code alone or in a team.
184
It provides patches, history, rollbacks, code versioning and more for your PHP
project as well.
Installation
Linux
To install Git on Linux operating systems best is to use your package manager,
such as apt-get, yum, dnf, pacman or pip.
For example, Debian based distributions using apt-get:
sudo apt-get install git-all
Or for Fedora based distributions:
sudo yum install git-all
macOS
macOS Sierra and OS X (until El Captain) don’t include an up to date Git. Git
is bundled with macOS, here is how to upgrade it:
If you do not have brew, install it:
• Install Xcode from the App Store and run xcode-select --install after
the successful installation.
• Install brew
Now install Git, brew will delegate a soft link into a higher path’ed directory:
brew install git
You could install Git in other ways (there is an official .dmg-image with an
installer). But this will force you to always handle those updates by yourself.
This will update everything:
brew update && brew upgrade `brew outdated`
Windows
Beside the Windows installation on the main download page there is also Git for
Windows, providing dedicated instructions for installation and adds neat shell
integration.
185
Commit messages
Commit message is the log information about the change made to the code
in the repository. Generally these must be informative and include all the
information needed about the change. For small changes they can be short, for
bigger changes they should be longer.
Some useful rules of a thumb for commit messages:
• Make the title of the commit message 50 characters or less;
• Put more information in the body part of the message (body starts after
two new lines after the title);
• Use imperative for the message title - Add new function not New
function added;
• Wrap body text to 72 characters
A Note About Git Commit Messages, by Tim Pope suggests a model you should
use for writing useful Git commit messages:
Capitalized, short (50 chars or less) summary
Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
or "Fixes bug." This convention matches up with commit messages generated
by commands like git merge and git revert.
Open source
When creating Git repository in public Git hosting services such as GitHub,
best practice is to add also some of the additional files to the repository which
describe the repository and your code with more details:
186
• README.md - introduction file about the project; (art-of-readme).
• CHANGELOG.md - Change log of the tagged versions using semantic versions.
Dedicated site Keep a CHANGELOG describes, why is useful having a
separate change log for your repository and how to format it.
• CONTRIBUTING.md - Open source projects usually add the file describing
how to get involved and send your patches to the repository.
• LICENSE - License of the repository.
• CONDUCT.md - Some open source projects include also their code of conduct
to let the users know what is appropriate and what not. Specially in larger
and diverse communities having such information adds extra value to the
project. Having a welcoming and inclusive environment is important for
people contributing to your project.
See also
187
Nopaste list and services to share and run code
online
What is a nopaste?
The term nopaste is a term used on the internet meaning to paste source code to
a separate, dedicated site, and to then link to that pasted source code in forum
discussions, chats, and so forth, instead of pasting that source code directly.
Many discussion forums and chat rooms don’t have an option of treating code
in messages properly. Nopaste sites usually also offer syntax highlighting, a
history of code changes, commenting on lines of code and similar.
For sharing, reviewing, and quick testing code snippets; the following services
also execute your code online:
• PHP Live Regex - Regular expressions for PHP
• Online PHP Functions Sandbox - PHP
• 3v4l - Run PHP code in multiple PHP versions.
• eval.in - Execute code online, multiple languages.
• Runnable - Run multiple languages using advanced stacks.
• WritePHPOnline - Run PHP Code.
• Ideone - Run multiple languages.
188
• PHPFiddle - Run PHP Code with different Libraries.
Online editors
Useful editors, code hosting services and tools for online collaboration:
• Etherpad
• Cloud9
• GitHub
• GitLab
• Bitbucket
• Orionhub
• Collabedit
Screenshot sites
Vagrant tutorial
1. What is Vagrant?
2. Installation
3. Project setup
4. Boxes
5. What is PuPHPet?
6. How to save your changes on a box?
7. Resources
In this tutorial you will learn how to quickly use Vagrant for PHP development.
What is Vagrant?
189
Installation
Project setup
Boxes
What is PuPHPet?
190
How to save your changes on a box?
When you make some changes on the box you’ve downloaded in previous steps,
you will loose them when you make:
$ vagrant destroy
In order to save the entire box you can make a new box based on the current
running virtual machine. This creates a package named package.box:
$ vagrant package --output package.box
You can than add this package to your base boxes:
$ vagrant box add your_name/distribution package.box
And use it like before:
$ vagrant init your_name/distribution
See also
191
• BowerPHP
• Grunt
• NPM and Gulp
• Robo
• Webpack
Many developers also use approach of developing a project with two separate
repositories - one for back end (PHP application) and one for front end.
The API points in the back end part are connected with the front end. Main-
taining and scaling to application requirements can be much easier.
High traffic and complex sites many times also create a separated CDN for
serving these static files. This can improve the performance since the asset is
downloaded only once from a separate location.
For many open source front end libraries, many times using a publicly available
CDNs is advices since it reduces the required number of requests and traffic for
your application.
See also
• Wikipedia: CDN
• Gulp: Refreshment for Your Frontend Assets
• Sitepoint: A PHP Front End Workflow without Node.js
Authentication
Stage and beta environments can be sometimes closed for public with HTTP
authentication. To pass username and password:
192
ab -c 10 -n 1000 -A username:password http://beta.example.org/
Siege
Siege is an http load testing and benchmarking tool. Its source code is available
on GitHub.
siege -c 10 -r 100 -b -i http://localhost
JMeter
Gatling
HTTP keep-alive
PHP UG concept
PHP User Group (PUG) is virtual or real in-place community consisting of local
people participating and organizing PHP conferences and meetings. You can
find your local user group at official PHP user groups list which is based on the
PHP.ug. In case there is no local PHP User Group near you, find some friends
interested in PHP and start your own local user group.
193
Figure 30: PHP User Grups
194
Many meetup and conference organizers use also Meetup for organizing and
sharing PHP meetings.
PHP community
Many of the popular PHP Content Management Systems (CMSs) have an active
and supportive community, both online and in the real world.
Drupal
• Drupal Forum - Online help and support from the Drupal community.
• Drupal Groups - A place for groups to organize, plan and work on projects,
both online and in real world user groups (sometimes called meetups).
Joomla
• Joomla Forum - Online help and support from the Joomla community.
• Joomla User Groups - Search for a local Joomla User Group. They regu-
larly host meetups with talks, ‘clinics’ and networking.
WordPress
195
• WordPress Forum - Online help and support from the WordPress commu-
nity.
Frameworks
Laravel
• Laravel.io - Online help for laravel related issues also shares laravel based
jobs.
• Laracasts- Official Dissusion forum of Laravel.
CakePHP
CodeIgniter
Symfony
See also
196
PHP.net always updates and announces PHP conferences from all over the world.
You can check the list of current conferences happening in the PHP’s conference
section.
There are some established conferences located in very comfy and easy to visit
locations.
• Bulgaria
• PHP Bulgaria
• http://www.bgphp.org/
• Croatia
• Web Summer Camp 2017
• http://2017.websummercamp.com/
• Germany
• International PHP Conference
• https://phpconference.com/en/
• Italy
• PHP Day
• http://2017.phpday.it/
• Netherlands
• Dutch PHP
• https://www.phpconference.nl/
• LaraCon EU
• https://laracon.eu/2017/
• Romania
• SymfonyCon Romania
• http://live.symfony.com/
• Serbia
• PHPSerbia
• http://www.conf2017.phpsrbija.rs/
• USA
197
• LaraCon US
• http://laracon.us/
• Symfony Live San Francisco
• http://live.symfony.com/
• php[cruise]! - Baltimore
• https://cruise.phparch.com/
• PHPtek
• https://tek.phparch.com/
• Lone Star
• http://lonestarphp.com/
There are a lot more.
198
At that time in France only few sites were talking about PHP. One was Jean-
Pierre Dezelus’ page and he was also a collector of elephants. He asked Vincent
to make an elephant logo for PHP with same style as the original PHP logo - a
blue oval with black outline gradient.
Then the original ElePHPant logo came to birth:
Many PHP projects have also made custom variations of the ElePHPant with
their logo on it.
199
Figure 33: PHP Women ElePHPant
200
PHP Architect’s orange ElePHPant - Archie:
Laravel’s ElePHPant
AmsterdamPHP ElePHPant
201
Figure 35: Laravel ElePHPant
202
Figure 36: AmsterdamPHP ElePHPant
203
Golden Elephpant
For the special occasion of 20 years of PHP, one of a kind golden ElePHPant
was created.
PHP 7 ElePHPant
PHP 7 Elephpant has been created for PHP 7 and as a gift for visitors at
ZendCon 2015.
Symfony ElePHPant
For the 10 years of Symfony project black Symfony ElePHPant has been made.
The great ancestor of the PHP Elephpant, the PHP Woolly Mammoth immor-
talized by the True North PHP conference.
PHP Classes Elephpant given to the Innovation Award Winners each year.
204
Figure 38: ZendCon PHP7 ElePHPant
There are many more to be listed here. Explore the PHP universe to find them
:)
See also
205
Figure 39: Symfony ElePHPant
206
Figure 40: TrueNorth PHP Woolly Mammoth
207
Figure 42: How to Ask Smart Questions
Read up on the problem before you ask for help. You may be able to save
the time of the helper, and even if your research doesn’t answer your questions,
you’ll be better able to convey these questions in a better, more sensible manner.
• Look for tutorials
• Do internet research
• Look at answers to other people’s questions on forums and answer sites
• Find and read documentation
Finding the right channel with the right people is pretty important. Also con-
sider the complexity of the problem and the skill level of the people you wish
to ask.
208
Figure 44: Ask the right people
209
Don’t ask to ask
Ask your questions directly and clearly. Don’t worry about asking whether
it’s ok to ask a question. Any question is welcome, but you may be directed
elsewhere if the question is more appropriate to a different channel.
Ask everyone
It’s not a good idea to address a question to a specific person, even if they’ve
helped you in the past. Directed questions are much less likely to be answered
than open questions.
Group can sometimes be flooded with questions or chatter. Try to find a differ-
ent channel where you can get the attention of people who’ll be able to help.
210
Figure 48: Be clear
Be clear
Make sure you write questions that clearly and concisely communicate the prob-
lems you want solved. This may include program version information and other
details about the system you’re using. For sharing code use nopaste.
Include purpose
Make sure to include the reason for your question and what you want to achieve
with the answer. This allows the person answering your question to provide the
right solution even when it isn’t obvious.
211
Figure 50: Be patient
Be patient
Wait for an answer. Not all group members are available all the time, but they’ll
respond when they can. Saying “thank you” when the question is solved can
give a much better impression about you and help to cultivate warm feelings for
those solving your question.
Keep learning; All experts were once beginners.
See also
Issues with asking questions are not new. Here are some more resources to study
how to ask questions in a smart and efficient way on the internet, specially in
technical communities.
• How to ask questions the smart way
• What have you tried?
• How to ask smart questions?
• StackOverflow: How do I ask a good question?
PHP podcasts
• Lately in PHP
212
• PHP Podcasts
• PHP Roundtable
• PHP Town Hall
• PHPUgly Podcast
General
• /dev/hell
You have some lines to set a variable or get posted data from a form like this:
$my_var = $_POST['myPostData'];
Now PHP does not have $_POST['myPostData'] if there is no POST data being
sent to the Page. This is when these errors come into play.
$my_var = ""; // Or $my_var = 0; for numbers to make sure the Variable is initialised
//now use isset()
$my_var = isset($_POST['myPostData']) ? $_POST['myPostData'] : "";
//or empty()
$my_var = !empty($_POST['myPostData']) ? $_POST['myPostData'] : "";
213
How to fix “Undefined index”?
Output
bool(true)
bool(false)
Since PHP 7 there is also the ?? (or Null Coalescing) Operator available:
$my_var = $_POST['myPostData'] ?? "";
if (preg_match('/MSIE/i', $user_agent)) {
echo "Internet Explorer";
214
} else {
echo "Non-IE Browser";
}
Better alternative would be also to use PHP function get_browser:
<?php
$browser = get_browser(null, true);
print_r($browser);
Libraries to check out when you need some advanced functionalities:
• PHPBrowser
There are also framework specific certifications available for different frameworks
and libraries available from their official vendors:
• Laravel certification - Certification for Laravel framework
• Magento certification - Magento ecommerce specific certification
• Symfony certification - Symfony framework speficic certification
• Twig certification - Certification for Twig template engine
• Zend Framework certification - Zend Framework 1 and 2 specific certifica-
tion
They can be taken online and quite a lot of preparation is required for them. In
case you decide to take any of the certification exams, make sure you prepare
well.
See also
215
What is web crawling and how to crawl websites
with PHP?
Web crawling is automated process where a program is browsing World Wide
Web to index data from websites. Examples of web crawlers or web spiders are
Googlebot, bingbot and others.
See also
Examples
$diff = $arrival->diff($start);
echo $diff->format('%m month, %d days (total: %a days)'); // 1 month, 6 days (total: 37 days
Carbon is simple PHP API extension for DateTime. You will find it extremely
useful.
echo Carbon::now()->subMinutes(2)->diffForHumans(); // 2 minutes ago
216
Comparing dates
if ($now == $arrival) {
echo "Welcome, Marty McFly!";
} else if ($now < $arrival) {
echo "Welcome to the future.";
} else {
echo "Welcome to the past.";
}
Time zone
$date->setTimezone(new DateTimeZone('Pacific/Chatham'));
echo $date->format('Y-m-d H:i:sP'); // 2015-10 07:28:00+13:45
Also don’t forget to set wanted time zone in php.ini files:
date.timezone = "UTC"
Localization
217
setlocale(LC_TIME, "sl_SI");
echo strftime("%c", $now->getTimestamp()); // sre okt 21 07:28:00 2015 CEST
Using IntlDateFormatter:
$now = new DateTime('now');
$fmt = new IntlDateFormatter('en_US', IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'Ame
echo $fmt->format($now); // Wednesday, October 21, 2015 at 07:28:00 AM Eastern Daylight Time
Quirks
Some strange quirks you might want to know and beware when dealing with
the following issues.
Zeroed dates
Zeroed dates (0000-00-00, 0000-00-00 00:00:00) can happen in MySQL for
example as the default value in columns with DateTime types. If you add zeroed
date to DateTime::__construct() they will result in nonsensical date:
$d = new DateTime("0000-00-00");
echo $d->format("Y-m-d"); // "-0001-11-30"
32-bit systems
On 32-bit systems DateTime::getTimestamp() will return false on dates beyond
2038.
DateTimeImmutable
When using setTimezone, setTimestamp, setDate, setTime, modify and some
other DateTime methods be careful because they will modify DateTime and
return $this. In below example you might expect that two objects below are
not the same:
function formatNextMondayFromNow(DateTime $dt) {
return $dt->modify('next monday')->format('Y-m-d');
}
$d = new DateTime();
echo formatNextMondayFromNow($d); // 2015-10-21
echo $d->format('Y-m-d'); // 2015-10-21
But they are because DateTime is mutable.
For that reason PHP 5.5 introduced DateTimeImmutable class which works the
same way as [DateTime] but it never changes itself. Instead it returns a new
object.
218
function formatNextMondayFromNow(DateTimeImmutable $dt) {
return $dt->modify('next monday')->format('Y-m-d');
}
$d = new DateTimeImmutable();
echo formatNextMondayFromNow($d); // 2015-10-26
echo $d->format('Y-m-d'); // 2015-10-21
See also
• Date and Time - PHP Manual - A must read to know more about date
and time in PHP.
• DateTimeImmutable blog post - Issue with some methods changing Date-
Time explained.
219
What does the deployment include?
During deployment, the source code files are transferred with some of the fol-
lowing additional steps:
• Checking out specific version of the application from the code repository
• Dependencies are installed with Composer
• Web assets (JavaScript, CSS, images) are generated, minified, concate-
nated…
• Database schema is migrated
• Cache is cleared
• Web server gets restarted
Modern deployments should be as simple, fast and be able to made often during
the application life time to meet the requirements. For example, if you change
only small portion of your code, only the changed files should be uploaded
and not all others. One of the modern deployment approaches is also atomic
deployment. It provides switching ability between different deployed versions
and web server uses symbolic link to the latest version location.
Quality
When uploading application from the development to production you also want
to ensure that tests pass and that application works as expected. This step adds
deploying application to another step, for example, a stage.
Pick the tools that you and your team find comfortable to work with and inspect
the available infrastructure options. You will not be able to use a single approach
for all of your projects. Many projects have their own edge cases and limits which
you must take into account when picking the build and deployment strategy.
220
FTP
FTP is the most basic file transfer approach you might have started with. It is
the easiest way of transferring application files to a web server by using FTP
protocol with some FTP client such as FileZilla or similar. FTP is simple and
convenient, but has many weaknesses such as security risks, lack of versioning
options and also it can be slow with a lot of files. Most shared hosting options
provide FTP to upload files to production.
The git-ftp provides Git version control system with FTP deployment.
Moving on
Below are listed some more advanced and convenient deployment methods. You
will need some prerequisite knowledge to link the basic deployment such as FTP
and further explained methods:
• Be able to use command line a lot. There is a really nice introduction
available in the art-of-command-line
• Be familiar with some basic DevOps skills.
221
System administration is often a very large chapter of its own and will not be
covered here in details.
GIT + SSH
When working with Git, you can use it to deploy your application as well.
In short the deployment procedure is the following:
• Local application development with Git
• Via SSH access you git pull and checkout possible specific application
version
If using GitHub, Bitbucket, GitLab or similar Git hosting service, you can add
the deployment SSH key in the repository.
Deployer
Deployer is a PHP cli application which can deploy your PHP application over
multiple protocols, SSH being widely used. After installation, a separate project
specific deploy.php file is used to deploy the application from the Git repository
to server via command line.
Pros:
• Completely customizable
• Fast
• Secure
Fabric
Docker
Docker
Pros:
• Very modular
• Easier server management
Cons:
222
• Very high level DevOps knowledge is required to successfully deploy
projects with Docker.
Docker deployment strategy can be used in two ways:
• By building custom images with application code in the images and de-
ploying them to Docker Registry.
This is probably the most convenient way to use Docker in production. However
Docker Registry with custom images needs to be used.
• By using Git on the production server and using volumes for code. Images
can be build on the server itself or downloaded from Docker Registry.
Some useful resources to run Docker in production:
• Rancher
• Kubernetes
Jenkins
Paid services
Some limited free and paid options you might want to check out if you want to
have more elegant and less “hacky” solutions:
• TeamCity - Proprietary deployment tool.
• DeployHQ - Web based GUI deployment service.
• Laravel Forge
223
PaaS
Platform as a Service include 3rd party services such as Heroku, Zeit, Azure
and others.
See also
To explore more about deployments, check also some of the following resources:
• Leanpub: Deploying PHP Applications
• Rasmus Lerdorf: Deploying PHP 7
• Servers for Hackers: Deployment
• Sitepoint: Easy Deployment of PHP Applications with Deployer
• Symfony deployment chapter
• Wikipedia: Continuous integration
• Wikipedia: List of build automation software
See also
224
How to send email with PHP?
Sending emails with PHP can be done with built-in mail function available in
PHP core. Building modern contact forms, customizing headers, sending HTML
emails, SMTP sending, local development, testing emails and other advanced
functionalities are sort of a must these days. That is why using libraries that
can help you get up to speed with emailing in PHP is recommended. There are
many competing open source libraries for sending emails with PHP available:
• PHPMailer
• Swift Mailer
• Zend\Mail
mail()
PHPMailer
require 'PHPMailerAutoload.php';
225
$mail->From = 'from@example.com';
$mail->FromName = 'Mailer';
$mail->addAddress('joe@example.net', 'Joe User'); // Add a recipient
$mail->addAddress('ellen@example.com'); // Name is optional
$mail->addReplyTo('info@example.com', 'Information');
$mail->addCC('cc@example.com');
$mail->addBCC('bcc@example.com');
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
echo 'Message has been sent';
}
Swift Mailer
Let’s take the above example and refactor it to use the Swift Mailer library:
<?php
require_once 'lib/swift_required.php';
/*
You could alternatively use a different transport such as Sendmail or Mail:
// Sendmail
$transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');
// Mail
$transport = Swift_MailTransport::newInstance();
226
*/
// Create a message
$message = Swift_Message::newInstance('Wonderful Subject')
->setFrom(['john@doe.com' => 'John Doe'])
->setTo(['receiver@domain.org', 'other@domain.org' => 'A name'])
->setBody('Here is the message itself')
;
Zend Mail
In the following example we assume you know Zend Framework. Let’s send an
email with Zend Mail:
use Zend\Mail;
See also
Some other useful 3rd party services to check out when sending emails:
• Mandril
• SendGrid
• Mailgun
227
• error_reporting
This sets which errors should be reported. Using E_ALL is a good practice.
• display_errors
This handles displaying errors to the screen.
• log_errors
This controls reporting errors to a log file. Recommended practice is to
always have this enabled.
• error_log
This defines error log file where errors should be written. It only applies
if log_errors is enabled.
Showing errors should depend on the environment your application is present.
Development environment
When developing your application locally, you want to show errors on screen
and in logs.
display_errors = on
log_errors = on
error_reporting = E_ALL
Production environment
See also
• Error Handling and Logging - A must read PHP manual chapter about
configuring the error reporting in PHP.
228
• Error in PHP - PHP manual errors chapter.
• Monolog - Logging library for PHP.
$_GET vs $_POST?
Users often ask what are the differences between the $_GET and $_POST variables
in PHP and GET and POST HTTP methods in general.
First some background on the HTTP methods. GET and POST are two of many
HTTP methods (GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS,
CONNECT and PATCH) used to indicate the desired action to be performed
on the identified resourse.
GET method:
POST method:
In case of POST method query strings are sent in the HTTP message body of
the POST request:
229
POST /test/form.php HTTP/1.1
Host: test.com
name1=value1&name2=value2&name3=value3
Query strings from the POST method can then be processed in PHP like this:
<?php
The difference between using $_GET/$_POST and more verbose functions like
filter_*****() is - $_GET is superglobals variable and because it is a vari-
able it can be set to another value. It cannot be trusted to give actual values
came from HTTP header/body. - While functions like filter_has_var() or
filter_input() will always get the value from original HTTP header/body.
They can be trusted to give original values. - But filter_input() also has a
drawback. Because it rely on real user input, this can make testing/mocking
data harder.
For POST method (or another method like PUT), you can get unprocessed
HTTP body like this:
<?php
$raw_body = file_get_contents('php://input');
This can be useful when you’re going to deal with incoming data which MIME
types is not application/x-www-form-urlencoded, like JSON data.
<?php
230
How to fix Cannot modify header information -
headers already sent by… warning?
Common warning when working with PHP can be:
Warning: Cannot modify header information - headers already sent by (output started at /var/
Functions that send or modify HTTP headers must be called before any output
is made:
• header
• header_remove
• session_regenerate_id
• session_start
• setcookie
• setrawcookie
HTTP specification defines that HTTP headers must always be sent before the
output. PHP scripts mainly generate HTML content, but also pass a set of
HTTP/CGI headers to the webserver.
Usual HTTP response looks like this:
HTTP/1.1 200 OK
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
<html>
<head>
<title>Example</title>
</head>
<body>
<h1>Page title</h1>
<p>After the two linebreaks HTTP response output is defined.</p>
In above case first three lines are HTTP headers and after two line breaks output
is defined. When PHP script receives the first output (html, output from echo
function etc) it will also flush all collected headers so far in the script procedure.
Afterwards it can send all the output it wants however adding other HTTP
headers will be impossible from there on.
231
Checklist of possible causes and how to fix it
• Whitespace or other ouput before the starting <?php tag or after closing
?> tag.
<?php
session_start();
• File where PHP code is used has UTF-8 Byte Order Mark. PHP files
should be encoded with UTF without BOM.
• Some previous error messages or notices are sent to the output.
• echo, print, printf or other printing functions produce output.
• Raw <html> sections prior to <?php code are written.
232
See also
233
// Get client's IP address
if (isset($_SERVER['HTTP_CLIENT_IP']) && array_key_exists('HTTP_CLIENT_IP', $_SERVER)) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && array_key_exists('HTTP_X_FORWARDED_FOR'
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ips = array_map('trim', $ips);
$ip = $ips[0];
} else {
$ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
See also
$hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']);
echo $hostname;
But important for you to know is that relying on this is not always possible
since the client may be logged in through VPN.
234
Open source licenses
What is a license and why should you pick one for your
project?
When open sourcing your code project you should always pick an appropriate
license for it.
There are a lot of open source licenses available that fit a lot of use cases.
• MIT License
• Creative Commons Attribution-ShareAlike 4.0 license
See also
Note
"This action needs the php.ini setting phar.readonly to be set to 0 in order to work for Pha
PHAR (“Php ARchive”) is analogous to the JAR file concept but for PHP. If
you have PHP 5.3 or greater, the Phar extension is built-in and enabled; you
can start using it without any additional requirements. PHAR files are treated
as read-only by default, and you can use any PHAR file without any special
configuration. This is great for deployment. But as you’ll be creating your own
PHARs you’ll need to allow write-access which is done through the php.ini file.
Open php.ini, find the phar.readonly directive, and modify it accordingly:
phar.readonly = 0
Now you’re ready to package your libraries and applications as PHARs.
Below simple code can create phar from folder project or change it to your
project name.
<?php
// create with alias "project.phar"
$phar = new Phar('project.phar', 0, 'project.phar');
// add all files in the project
235
$phar->buildFromDirectory(dirname(__FILE__) . '/project');
$phar->setStub($phar->createDefaultStub('cli/index.php', 'www/index.php'));
See also
236
How to achieve this?
We want our front controller (index.php) to handle all requests that come to a
particular directory, except those that should go to an existing asset file such as
an image, CSS or JavaScript files. Also most PHP frameworks usually use this
single entry point approach for all URLs. First let’s configure web server a bit.
Apache
If you’re using Apache 2.2.16 or greater you can use FallbackResource direc-
tive:
In .htaccess add this:
FallbackResource index.php
If you are using Apache version prior to 2.2.16 or you will be doing a little more
complex stuff. For example, if you need to use RewriteBase, or maybe have
different rewrite conditions, you will have to use mod_rewrite rules. But in
most cases, only the FallbackResource will suffice and you can get also a bit
better performance.
If you still want to enable mod_rewrite and add some special rewrite rules in
.htaccess file, check the example below:
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
#RewriteBase /var/www/project/public
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
</IfModule>
On Linux machines you can activate mod_rewrite with a2enmod in command
line:
$ sudo a2enmod rewrite
Nginx
Here is an Nginx web server example for doing same requests handling as above.
In your Nginx site configuration file /etc/nginx/sites-available/default
enable PHP and requests handling. Here is minimum configuration to achieve
this:
server {
server_name domain.tld www.domain.tld;
237
root /var/www/project/public;
location / {
# try to serve file directly, fallback to app.php
try_files $uri /index.php$is_args$args;
}
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/index.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}
error_log /var/log/nginx/project_error.log;
access_log /var/log/nginx/project_access.log;
}
Now that we have web server set, we must process incoming request and do
the magic to show correct blog post. In this step the usual way of creating
web applications is to use a pattern such as MVC, MVP, MOVE or some other.
Below is a very simple way to parse URL with PHP. At the end we will list
some PHP libraries you should check out if you’re not planning to reinvent the
wheels here.
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
See also
238
What is the difference between a developer and
programmer?
Developer is a person who solves problems and usually aren’t focused deeply
on the code unlike a programmer. They deal more with the project from a
bigger picture point of view. For example, they connect together different tech-
nologies and people involved in the project. They are responsible for organizing
the requirements and specifications of the project and deliver these to a pro-
grammer, who then implements them. Usually developers don’t need so much
programming skills.
Programmer is a person who writes programs based on the requirements or
specification they receive. They write beautiful code and have thorough knowl-
edge about a programming language, algorithms and how to do things really
well and optimized in code. Usually they don’t need people skills much.
Coder can be someone who writes code and deals directly with tasks that are
clearly defined and problems already recognized. For example, they create an
HTML and CSS layout of the website. Many times this title means the same as
programmer.
Architect is someone who looks at the big picture of the project. They need
management, people and general technology skills.
Important thing to understand is that many times these titles are also a matter
of a perspective and can be used interchangeably in the coding world. Sometimes
they are used to differentiate the responsibility, knowledge and skill levels. So
if you’re confused about this terminology, you can just refer to them all as
engineers.
Technology evangelist is someone who promotes particular technology or
product by blogging, conference and meetup talks, writing articles, sharing in-
formation on social networks and similar in order to convince other people to
use it as well.
See also
239
• App Specs - A curated list of applications specifications and implemen-
tations for practicing new technologies, improving your portfolio and
sharpen your skills.
• Project suggestions - A list of practical projects that anyone can solve in
any programming language.
Brief history
Matching
240
string $subject [,
array &$matches [,
int $flags = PREG_PATTERN_ORDER [,
int $offset = 0
]]])
Replacing
For comparison, regular expressions in JavaScript look pretty much the same as
in PHP.
Matching
Replacing
241
Basics of regex patterns
Let’s take a look at example to find email addresses in codebase. Our goal:
/[\w.+-]+@[a-z0-9-]+(\.[a-z0-9-]+)*/i
Sockets analogy
Special characters
Let’s take a look at what special characters do:
• Backslash character \\ can escape other special character in regular ex-
pression:
• The Dot and the \w - .
Matches everything but new lines. If you want to match a dot and only a
dot escape it like \, \w matches letters, numbers, and the underscore
• Square brackets []
Matches characters inside the brackets. Supports ranges. Some examples:
– [abc] - matches any a, b or c.
– [a-z] Lowercase letters
– [0-9] Any single digit
– [a-zA-Z] - matches any lower or uppercase alphabetic character
• Optional ?
The ? matches 0 or 1
• The star *
The star matches 0 or more
• The Plus +
Matches 1 or more
• Curly brackets {}
Min and Max ranges. Some examples:
– {1,} at least 1
242
– {1,3} 1 through 3
– {1,64} 1 through 64
Let’s put all this together to get regex for email addresses:
/[\w.+-]+@[a-z0-9-]+(\.[a-z0-9-]+)*/i
Many cases are better handled with PHP’s filter_var function. For example
validating emails should be done with PHP built-in filters:
filter_var(
'bob@example.com',
FILTER_VALIDATE_EMAIL
)
243
Regex validation
Most common PCRE functions for performing search and replace are
preg_replace() and preg_replace_callback(). But there are also
preg_filter() and preg_replace_callback_array() to do almost the same.
Note that preg_replace_callback_array() is available since PHP7.
Output
I want to eat some fruits.
If you have subpatterns (patterns in parentheses) in your pattern, you can use $N
or \N (where N is an integer >= 1) in replacement, this is called ‘backreference’.
$subject = '7/11';
echo preg_replace('/(\d+)\/(\d+)/', '$2/$1', $subject);
244
Output
11/7
$subject = '2001-09-11';
echo preg_replace('/(\d+)\-(\d+)\-(\d+)/', '$3/$2/$1', $subject);
Output
11/09/2001
Output
Please visit <a href="https://php.earth/doc" target="_blank">php.earth/doc</a> for more arti
Sometimes you may want to perform complex search and replace like filter-
ing/sanitizing before replacing. This is a situation where preg_replace_callback()
may come into play.
In previous example our regex can replace only URLs begin with http or
https and now we want it to be able to replace URLs begin with www. too.
Someone might think we can simply change https?\:// into subpattern like
(?:https?\://|www\.) but this will not work in most browsers because they
will interprete www.domain as a relative path.
So we need to do some works before replacing, by prepending http:// if a URL
begins with www..
function add_protocol_if_begins_with_www($matches)
{
$url = strtolower($matches[1]) === 'www.'
? 'http://' . $matches[0]
: $matches[0];
return "<a href=\"{$url}\">{$matches[2]}</a>";
}
245
$subject = 'Please visit www.php.earth/doc for more articles.';
echo preg_replace_callback(
'#(https?\://|www\.)([^\s\./]+(?>\.[^\s\./]+)*[^\s]*)#i',
'add_protocol_if_begins_with_www',
$subject
);
Output
Please visit <a href="http://www.php.earth/doc" target="_blank">php.earth/doc</a> for more a
Problem: Link @mentions and #tags
Goal: /\B@([\w]{2,})/i
See also
• PHP.net resources:
• Pattern syntax
• Modifiers
• Functions
• Regex online tools:
• Debuggex - Online regex visualization tool.
• PHP Live Regex - Live regular expression tester for PHP.
• regexper - Regular expression visualizer using railroad diagrams.
• RegExr - Learn, build and test Regular Expressions.
• Regex101 - Create, debug, test and have your expressions explained for
PHP, PCRE, JavaScript and Python. The website also features a commu-
nity where you can share useful expressions.
• Tutorials:
• Demystifying RegEx with Practical Examples
• The best regex trick ever
• awesome-regex - A curated collection of awesome regex libraries, tools,
frameworks and software.
• RegexOne - Learn Regular Expressions with simple, interactive exercises.
246
• Document parsing For example, HTML or XML document is converted
to DOM (Document Object Model). PHP offers DOM extension.
• Regular expressions To scrape data from web document also regular
expressions can be used.
Issue with scraping data from 3rd party websites is with copyrights if you don’t
have permissions to use that data. Another disadvantage is keeping up with
changes of the web document. Scraper must be adapted if that document
changes. For these reasons it is better to check and use API of website where
data needs to be scraped.
See also
See also
PHP Strings
247
$variable = 10;
echo 'Value is $variable';
Output:
Value is $variable
Heredoc
248
• You don’t need to escape quotes in this syntax.
Credit
See also
249
Figure 54: Sending SMS with PHP
250
Which PHP template engine to use?
Business logic of an application determines how data are created, displayed,
stored and changed. Presentation layer determines how data are presented to
the user in certain format such as HTML, JSON, XML or some other.
Instead of mixing your application’s business logic and presentation and dupli-
cating code, best practice is to separate that with templates. Template engine
takes care of all that applies the Don’t Repeat Yourself (DRY) principle.
Example of a simple PHP template engine using Closure:
<?php
class Article
{
/**
* @var string
*/
private $title = 'This is an article';
}
class Post
{
/**
* @var string
*/
private $title = 'This is a post';
}
class Template
{
/**
* Renders template with closure.
*
* @param mixed $context
* @param string $template
*
* @return string
*/
public function render($context, $template)
{
$closure = function($template) {
ob_start();
include $template;
return ob_end_flush();
};
251
// Create a closure
$closure = $closure->bindTo($context, $context);
$closure($template);
}
}
$template->render($article, 'template.php');
$template->render($post, 'template.php');
Template file can be reused elsewhere:
<h1><?php echo $this->title;?></h1>
Template engines should also take care of XSS security vulnerability by escaping
data:
<?php echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>
Template engines can also feature template inheritance where child templates
extend parent ones:
layout.php:
<html lang="en">
<head>
<meta charset="utf-8">
<title><?=$title?></title>
</head>
<body>
<?=$this->section('body')?>
</body>
</html>
There is a wide variety of open source PHP templating engines:
• Aura.View (native)
• Blade (compiled, framework specific)
• Brainy (compiled)
• Dwoo (compiled)
• FigDice - compiled template rendering system
• Latte (compiled)
• Mustache (compiled)
• PHPTAL (compiled)
• Plates (native)
• Smarty (compiled)
252
• Transphporm - Innovative template engine which follows “template ani-
mation” approach. Template animation is using HTML/CSS… files as a
resource and manipulates them via the DOM to generate the dynamic
output.
• Twig (compiled)
• Zend\View (native, framework specific)
253
include 'myinclude.php';
while your folder tree view is like this:
/includes/myinclude.php
index.php
Now PHP can not find the file myinclude.php because it is not in the same
directory as the index.php.
A basic fix for this is setting the appropriate directory. For this example:
include 'includes/myinclude.php';
includes/myinclude.php
in this case a simple
include '../includes/myinclude.php';
would do the trick, however the best practice for this case is to use script dir
centric paths:
include __DIR__.'/../includes/myinclude.php';
254
Core PHP
A core PHP describes the main engine of the PHP language itself and doesn’t
mean developing something with the PHP language directly. So a core PHP
developer writes C code and extends the PHP core or develops PHP extensions,
which are written in C programming language. Often times, core PHP is referred
to as PHP internals also.
A vanilla PHP or plain PHP is developing an application using the PHP lan-
guage without any 3rd party libraries or frameworks. So the vanilla developer
actually uses the language used in the name.
Conclusion
As long as you are writing PHP code, you are a vanilla PHP developer if you
are however writing on the PHP core itself, you can be considered a core PHP
developer.
See also
255
– Secured configuration files
• Documentation
• Development environment
Introduction
In this section we will list some of the best PHP practices you should consider
adopting. PHP offers a lot of options and styles of writing your code. However,
as your application grows and becomes more complex, following best practices
is a must if you want modern and maintainable PHP code or simply want to be
a better PHP developer.
PHP setup
PHP version
Use the latest stable PHP version (i.e., PHP 7.1 at the time of writing this). You
will be able to use great new features and overall performance will be improved.
Using old versions can lead to security issues.
PHP extensions
Coding style
Coding standards
Arrays
256
Ternary operator
In cases where you need to make a quick conditional check, there’s a ternary
operator that can make your code cleaner and more readable.
Let’s assume you want to set the $discount based on the value of the $amount.
If the $amount is less than 100, then the discount is 10%, and otherwise, it is
20%.
Say you want to check if the $amount variable equals 10, and if $amount equals
10 you want to set the $total to 1000, and if the $amount is NOT equal to 10
you want to set $total to 200.
You could use an if else statement:
<?php
Composer
In modern PHP, we should write less code, and since many problems have
already been solved, use existing solutions and libraries. Composer is a tool
for managing your dependencies in a PHP project. By using a terminal, you
can add, update, and remove dependent packages from packagist.org and other
repositories. Composer uses a composer.json file, located in your project di-
rectory, for managing dependent packages.
Testing
Always test your code. If you’re not familiar with concept of testing, start with
PHPUnit.
257
Emails
For sending emails there are multiple options in PHP, from using PHP’s default
mail() function, to external third-party libraries such as Swift Mailer and PHP-
Mailer. Try to avoid the default mail() function and instead use Swift Mailer
or PHPMailer. Building modern contact forms, customizing headers, sending
HTML emails, SMTP sending, different setups for sending emails in develop-
ment environments, testing emails and other advanced functionalities are sort
of a must these days, and the mail() function is too basic for that.
Passwords
Storing passwords must be done with PHP’s built-in password hashing API.
Databases
For databases, using PDO or simply just an ORM is very convenient and can
greatly help you handle advanced database manipulation tasks.
<?php
// PDO and MySQL example
$pdo = new PDO('mysql:host=localhost;dbname=database', 'user', 'password');
$statement = $pdo->query("SELECT id FROM friend");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['id']);
Security
258
Direct access to configuration files stored as formats such as JSON or YAML,
for example, should always be restricted by .htaccess:
#Apache 2.4+
Require local
Documentation
Always maintain documentation for your code. It adds extra time to your work,
but will be helpful to others (and also to you) in the future, to understand what
you’ve written. We forget what certain functions, methods and parts of code
do, so please always take extra time to document your work.
For inline PHP documentation, use phpDocumentor:
<?php
/**
* Foo file description.
*/
/**
* I belong to a class
*/
class Foo
{
}
Development environment
259
create and configure lightweight, reproducible, and portable development envi-
ronments. When using virtualization, make sure to create a virtual machine
that resembles the production server (the machine where you deploy). This will
help you catch deployment issues during the development stage. These articles
can help you get started with Vagrant and Docker in PHP development:
• 5 Easy Ways to Get Started with PHP on Vagrant
• Re-introducing Vagrant: The Right Way to Start with PHP
• Docker and dockerfiles made easy
Since the information provided on the article page may be outdated, you should
also refer to the official documentation for vagrant and docker, provided by the
application vendor.
260