mirror of
https://github.com/codeguy/php-the-right-way.git
synced 2025-08-17 03:03:57 +02:00
Merge branch 'gh-pages' of github.com:codeguy/php-the-right-way into aranw-errors-exceptions
This commit is contained in:
@@ -1,19 +1,19 @@
|
||||
# Welcome
|
||||
|
||||
There's a lot of outdated information on the Web that leads new PHP users astray,
|
||||
propagating bad practices and insecure code. _PHP: The Right Way_ is an easy-to-read,
|
||||
quick reference for PHP popular coding standards, links to authoritative tutorials
|
||||
around the Web and what the contributors consider to be best practices at the present
|
||||
There's a lot of outdated information on the Web that leads new PHP users astray,
|
||||
propagating bad practices and insecure code. _PHP: The Right Way_ is an easy-to-read,
|
||||
quick reference for PHP popular coding standards, links to authoritative tutorials
|
||||
around the Web and what the contributors consider to be best practices at the present
|
||||
time.
|
||||
|
||||
_There is no canonical way to use PHP_. This website aims to introduce new PHP
|
||||
developers to some topics which they may not discover until it is too late, and aims
|
||||
to give seasoned pros some fresh ideas on those topics they've been doing for years
|
||||
without ever reconsidering. This website will also not tell you which tools to use, but
|
||||
instead offer suggestions for multiple options, when possible explaining the differences
|
||||
in approach and use-case.
|
||||
_There is no canonical way to use PHP_. This website aims to introduce new PHP
|
||||
developers to some topics which they may not discover until it is too late, and aims
|
||||
to give seasoned pros some fresh ideas on those topics they've been doing for years
|
||||
without ever reconsidering. This website will also not tell you which tools to use, but
|
||||
instead offer suggestions for multiple options, when possible explaining the differences
|
||||
in approach and use-case.
|
||||
|
||||
This is a living document and will continue to be updated with more helpful information
|
||||
This is a living document and will continue to be updated with more helpful information
|
||||
and examples as they become available.
|
||||
|
||||
## Translations
|
||||
@@ -21,15 +21,14 @@ and examples as they become available.
|
||||
_PHP: The Right Way_ is (or soon will be) translated into many different languages:
|
||||
|
||||
* [English](http://www.phptherightway.com)
|
||||
* Catalan (Link broken... we're looking into it)
|
||||
* [Chinese](http://wulijun.github.com/php-the-right-way)
|
||||
* [Chinese (Simplified)](http://wulijun.github.com/php-the-right-way)
|
||||
* [Japanese](http://ja.phptherightway.com)
|
||||
* [Korean](http://wafe.github.io/php-the-right-way/)
|
||||
* Italian (Link broken... we're looking into it)
|
||||
* [Italian](http://it.phptherightway.com/)
|
||||
* [Polish](http://pl.phptherightway.com/)
|
||||
* [Portuguese](http://br.phptherightway.com/)
|
||||
* [Russian](http://getjump.github.io/ru-php-the-right-way)
|
||||
* Spanish (Link broken... we're looking into it)
|
||||
* [Spanish](http://lamaneracorrecta.php.org.ve)
|
||||
* [Ukrainian](http://iflista.github.com/php-the-right-way/)
|
||||
* [Bulgarian](http://bg.phptherightway.com/)
|
||||
* [German](http://rwetzlmayr.github.io/php-the-right-way/)
|
||||
|
@@ -23,7 +23,7 @@
|
||||
_gaq.push(['_trackPageview']);
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'stats.g.doubleclick.net/dc.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
|
@@ -22,7 +22,7 @@
|
||||
_gaq.push(['_trackPageview']);
|
||||
(function() {
|
||||
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
||||
ga.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'stats.g.doubleclick.net/dc.js';
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
||||
})();
|
||||
</script>
|
||||
|
@@ -4,8 +4,8 @@ isChild: true
|
||||
|
||||
## Mac Setup {#mac_setup_title}
|
||||
|
||||
OSX comes prepackaged with PHP but it is normally a little behind the latest stable. Lion comes with PHP 5.3.6 and
|
||||
Mountain Lion has 5.3.10.
|
||||
OSX comes prepackaged with PHP but it is normally a little behind the latest stable. Lion comes with PHP 5.3.6,
|
||||
Mountain Lion has 5.3.10, and Mavericks has 5.4.17.
|
||||
|
||||
To update PHP on OSX you can get it installed through a number of Mac [package managers][mac-package-managers], with
|
||||
[php-osx by Liip][php-osx-downloads] being recommended.
|
||||
|
@@ -21,15 +21,17 @@ create and edit your files on your host machine and then run the code inside you
|
||||
|
||||
### A little help
|
||||
|
||||
If you need a little help to start using Vagrant there are two services that might be useful:
|
||||
If you need a little help to start using Vagrant there are three services that might be useful:
|
||||
|
||||
- [Rove][rove]: service that allows you to pregenerate typical Vagrant builds, PHP among the options. The
|
||||
provisioning is made with Chef.
|
||||
- [Puphpet][puphpet]: simple GUI to set up virtual machines for PHP development. **Heavily focused in PHP**. Besides
|
||||
local VMs, can be used to deploy to cloud services as well. The provisioning is made with Puppet.
|
||||
- [Protobox][protobox]: is a layer on top of vagrant and a web GUI to setup virtual machines for web development. A single YAML document controls everything that is installed on the virtual machine.
|
||||
|
||||
[vagrant]: http://vagrantup.com/
|
||||
[puppet]: http://www.puppetlabs.com/
|
||||
[chef]: http://www.opscode.com/
|
||||
[rove]: http://rove.io/
|
||||
[puphpet]: https://puphpet.com/
|
||||
[protobox]: http://getprotobox.com/
|
||||
|
@@ -5,10 +5,10 @@ PHP developers to choose several of these and combine them into a single project
|
||||
(as close as possible) to a common code style to make it easy for developers to mix and match various libraries for
|
||||
their projects.
|
||||
|
||||
The [Framework Interop Group][fig] has proposed and approved a series of style recommendations, known as [PSR-0][psr0],
|
||||
[PSR-1][psr1] and [PSR-2][psr2]. Don't let the funny names confuse you, these recommendations are merely
|
||||
a set of rules that some projects like Drupal, Zend, Symfony, CakePHP, phpBB, AWS SDK, FuelPHP, Lithium, etc are starting
|
||||
to adopt. You can use them for your own projects, or continue to use your own personal style.
|
||||
The [Framework Interop Group][fig] has proposed and approved a series of style recommendations. Not all of them related
|
||||
to code-style, but those that do are [PSR-0][psr0], [PSR-1][psr1], [PSR-2][psr2] and [PSR-4][psr4]. These recommendations
|
||||
are merely a set of rules that some projects like Drupal, Zend, Symfony, CakePHP, phpBB, AWS SDK, FuelPHP, Lithium,
|
||||
etc are starting to adopt. You can use them for your own projects, or continue to use your own personal style.
|
||||
|
||||
Ideally you should write PHP code that adheres to a known standard. This could be any combination of PSR's, or one
|
||||
of the coding standards made by PEAR or Zend. This means other developers can easily read and work with your code,
|
||||
@@ -17,8 +17,10 @@ and applications that implement the components can have consistency even when wo
|
||||
* [Read about PSR-0][psr0]
|
||||
* [Read about PSR-1][psr1]
|
||||
* [Read about PSR-2][psr2]
|
||||
* [Read about PSR-4][psr4]
|
||||
* [Read about PEAR Coding Standards][pear-cs]
|
||||
* [Read about Zend Coding Standards][zend-cs]
|
||||
* [Read about Symfony Coding Standards][symfony-cs]
|
||||
|
||||
You can use [PHP_CodeSniffer][phpcs] to check code against any one of these recommendations, and plugins for text editors
|
||||
like [Sublime Text 2][st-cs] to be given real time feedback.
|
||||
@@ -33,9 +35,10 @@ by all current and future parties who may be working on the codebase.
|
||||
[psr0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
|
||||
[psr1]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md
|
||||
[psr2]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
|
||||
[psr3]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
|
||||
[psr4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md
|
||||
[pear-cs]: http://pear.php.net/manual/en/standards.php
|
||||
[zend-cs]: http://framework.zend.com/wiki/display/ZFDEV2/Coding+Standards
|
||||
[symfony-cs]: http://symfony.com/doc/current/contributing/code/standards.html
|
||||
[phpcs]: http://pear.php.net/package/PHP_CodeSniffer/
|
||||
[st-cs]: https://github.com/benmatselby/sublime-phpcs
|
||||
[phpcsfixer]: http://cs.sensiolabs.org/
|
||||
|
@@ -4,16 +4,30 @@ isChild: true
|
||||
|
||||
## Namespaces {#namespaces_title}
|
||||
|
||||
As mentioned above, the PHP community has a lot of developers creating lots of code. This means that one library's PHP code may use the same class name as another library. When both libraries are used in the same namespace, they collide and cause trouble.
|
||||
As mentioned above, the PHP community has a lot of developers creating lots of code. This means that
|
||||
one library's PHP code may use the same class name as another library. When both libraries are used
|
||||
in the same namespace, they collide and cause trouble.
|
||||
|
||||
_Namespaces_ solve this problem. As described in the PHP reference manual, namespaces may be compared to operating system directories that _namespace_ files; two files with the same name may co-exist in separate directories. Likewise, two PHP classes with the same name may co-exist in separate PHP namespaces. It's as simple as that.
|
||||
_Namespaces_ solve this problem. As described in the PHP reference manual, namespaces may be compared
|
||||
to operating system directories that _namespace_ files; two files with the same name may co-exist in
|
||||
separate directories. Likewise, two PHP classes with the same name may co-exist in separate PHP
|
||||
namespaces. It's as simple as that.
|
||||
|
||||
It is important for you to namespace your code so that it may be used by other developers without fear of colliding with other libraries.
|
||||
It is important for you to namespace your code so that it may be used by other developers without fear
|
||||
of colliding with other libraries.
|
||||
|
||||
One recommended way to use namespaces is outlined in [PSR-0][psr0], which aims to provide a standard file, class and namespace convention to allow plug-and-play code.
|
||||
One recommended way to use namespaces is outlined in [PSR-0][psr0], which aims to provide a standard file,
|
||||
class and namespace convention to allow plug-and-play code.
|
||||
|
||||
In December 2013 the PHP-FIG created a new autoloading standard: [PSR-4][psr4], which one day will
|
||||
probably replace PSR-0. Currently both are still usable, as PSR-4 requires PHP 5.3 and many PHP 5.2-only
|
||||
projects currently implement PSR-0. If you're going to use an autoloader standard for a new application or
|
||||
package then you almost certainly want to look into PSR-4.
|
||||
|
||||
* [Read about Namespaces][namespaces]
|
||||
* [Read about PSR-0][psr0]
|
||||
* [Read about PSR-4][psr4]
|
||||
|
||||
[namespaces]: http://php.net/manual/en/language.namespaces.php
|
||||
[psr0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
|
||||
[psr4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md
|
@@ -1,4 +1,5 @@
|
||||
---
|
||||
title: XDebug
|
||||
isChild: true
|
||||
---
|
||||
|
||||
@@ -30,7 +31,7 @@ Your IDE will now intercept the current state as the script executes, allowing y
|
||||
values in memory.
|
||||
|
||||
Graphical debuggers make it very easy to step through code, inspect variables, and eval code against the live runtime.
|
||||
Many IDE's have built-in or plugin-based support for graphical debugging with xdebug. MacGBDp is a free, open-source,
|
||||
Many IDE's have built-in or plugin-based support for graphical debugging with xdebug. MacGDBp is a free, open-source,
|
||||
stand-alone xdebug GUI for Mac.
|
||||
|
||||
* [Learn more about XDebug][xdebug-docs]
|
||||
|
@@ -36,16 +36,18 @@ The path `$HOME/local/bin` (or a directory of your choice) should be in your `$P
|
||||
When you come across documentation that states to run Composer as `php composer.phar install`, you can substitute that with:
|
||||
|
||||
composer install
|
||||
|
||||
This section will assume you have installed composer globally.
|
||||
|
||||
### How to Define and Install Dependencies
|
||||
|
||||
Composer keeps track of your project's dependencies in a file called `composer.json`. You can manage it by hand if you like, or use Composer itself. The `php composer.phar require` command adds a project dependency and if you don't have a `composer.json` file, one will be created. Here's an example that adds [Twig][2] as a dependency of your project. Run it in your project's root directory where you've downloaded `composer.phar`:
|
||||
Composer keeps track of your project's dependencies in a file called `composer.json`. You can manage it by hand if you like, or use Composer itself. The `composer require` command adds a project dependency and if you don't have a `composer.json` file, one will be created. Here's an example that adds [Twig][2] as a dependency of your project.
|
||||
|
||||
php composer.phar require twig/twig:~1.8
|
||||
composer require twig/twig:~1.8
|
||||
|
||||
Alternatively the `php composer.phar init` command will guide you through creating a full `composer.json` file for your project. Either way, once you've created your `composer.json` file you can tell Composer to download and install your dependencies into the `vendors/` directory. This also applies to projects you've downloaded that already provide a `composer.json` file:
|
||||
Alternatively the `composer init` command will guide you through creating a full `composer.json` file for your project. Either way, once you've created your `composer.json` file you can tell Composer to download and install your dependencies into the `vendors/` directory. This also applies to projects you've downloaded that already provide a `composer.json` file:
|
||||
|
||||
php composer.phar install
|
||||
composer install
|
||||
|
||||
Next, add this line to your application's primary PHP file; this will tell PHP to use Composer's autoloader for your project dependencies.
|
||||
|
||||
@@ -62,14 +64,20 @@ Composer creates a file called `composer.lock` which stores the exact version of
|
||||
|
||||
This is most useful when you define your version requirements flexibly. For instance a version requirement of ~1.8 means "anything newer than 1.8.0, but less than 2.0.x-dev". You can also use the `*` wildcard as in `1.8.*`. Now Composer's `php composer.phar update` command will upgrade all your dependencies to the newest version that fits the restrictions you define.
|
||||
|
||||
### Update Notifications
|
||||
|
||||
To receive notifications about new version releases you can sign up for [VersionEye][3], a web service that can monitor
|
||||
your GitHub and BitBucket accounts for `composer.json` files and send emails with new package releases.
|
||||
|
||||
### Checking your dependencies for security issues
|
||||
|
||||
The [Security Advisories Checker][3] is a web service and a command-line tool, both will examine your `composer.lock` file and tell you if you need to update any of your dependencies.
|
||||
The [Security Advisories Checker][4] is a web service and a command-line tool, both will examine your `composer.lock` file and tell you if you need to update any of your dependencies.
|
||||
|
||||
* [Learn about Composer][4]
|
||||
* [Learn about Composer][5]
|
||||
|
||||
[1]: http://packagist.org/
|
||||
[2]: http://twig.sensiolabs.org
|
||||
[3]: https://security.sensiolabs.org/
|
||||
[4]: http://getcomposer.org/doc/00-intro.md
|
||||
[3]: https://www.versioneye.com/
|
||||
[4]: https://security.sensiolabs.org/
|
||||
[5]: http://getcomposer.org/doc/00-intro.md
|
||||
|
||||
|
13
_posts/06-01-01-Dependency-Injection.md
Normal file
13
_posts/06-01-01-Dependency-Injection.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Dependency Injection
|
||||
---
|
||||
|
||||
# Dependency Injection {#dependency_injection_title}
|
||||
|
||||
From [Wikipedia](http://en.wikipedia.org/wiki/Dependency_injection):
|
||||
|
||||
> Dependency injection is a software design pattern that allows the removal of hard-coded dependencies and makes it
|
||||
> possible to change them, whether at run-time or compile-time.
|
||||
|
||||
This quote makes the concept sound much more complicated than it actually is. Dependency Injection is providing a component
|
||||
with it's dependencies either through constructor injection, method calls or the setting of properties. It is that simple.
|
51
_posts/06-02-01-Basic-Concept.md
Normal file
51
_posts/06-02-01-Basic-Concept.md
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
isChild: true
|
||||
---
|
||||
|
||||
## Basic Concept {#basic_concept_title}
|
||||
|
||||
We can demonstrate the concept with a simple, yet naive example.
|
||||
|
||||
Here we have a `Database` class that requires an adapter to speak to the database. We instantiate the
|
||||
adapter in the constructor and create a hard dependency. This makes testing difficult and means the `Database` class is
|
||||
very tightly coupled to the adapter.
|
||||
|
||||
{% highlight php %}
|
||||
<?php
|
||||
namespace Database;
|
||||
|
||||
class Database
|
||||
{
|
||||
protected $adapter;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->adapter = new MySqlAdapter;
|
||||
}
|
||||
}
|
||||
|
||||
class MysqlAdapter {}
|
||||
{% endhighlight %}
|
||||
|
||||
This code can be refactored to use Dependency Injection and therefore loosen the dependency.
|
||||
|
||||
{% highlight php %}
|
||||
<?php
|
||||
namespace Database;
|
||||
|
||||
class Database
|
||||
{
|
||||
protected $adapter;
|
||||
|
||||
public function __construct(MySqlAdapter $adapter)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
}
|
||||
}
|
||||
|
||||
class MysqlAdapter {}
|
||||
{% endhighlight %}
|
||||
|
||||
Now we are giving the `Database` class its dependency rather than it creating it itself. We could even create a method
|
||||
that would accept an argument of the dependency and set it that way, or if the `$adapter` property was `public` we could
|
||||
set it directly.
|
56
_posts/06-03-01-Complex-Problem.md
Normal file
56
_posts/06-03-01-Complex-Problem.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
isChild: true
|
||||
---
|
||||
|
||||
## Complex Problem {#complex_problem_title}
|
||||
|
||||
If you have ever read about Dependency Injection then you have probably seen the terms *"Inversion of Control"* or *"Dependency Inversion Principle"*.
|
||||
These are the complex problems that Dependency Injection solves.
|
||||
|
||||
### Inversion of Control
|
||||
|
||||
Inversion of Control is as it says, "inverting the control" of a system by keeping organisational control entirely separate from our objects.
|
||||
In terms of Dependency Injection, this means loosening our dependencies by controlling and instantiating them elsewhere in the system.
|
||||
|
||||
For years, PHP frameworks have been achieving Inversion of Control, however, the question became, which part of control
|
||||
are you inverting, and where to? For example, MVC frameworks would generally provide a super object or base controller that other
|
||||
controllers must extend to gain access to its dependencies. This **is** Inversion of Control, however, instead of loosening
|
||||
dependencies, this method simply moved them.
|
||||
|
||||
Dependency Injection allows us to more elegantly solve this problem by only injecting the dependencies we need, when we need them,
|
||||
without the need for any hard coded dependencies at all.
|
||||
|
||||
### Dependency Inversion Principle
|
||||
|
||||
Dependency Inversion Principle is the "D" in the S.O.L.I.D set of object oriented design principles that states one should
|
||||
*"Depend on Abstractions. Do not depend on concretions."*. Put simply, this means our dependencies should be interfaces/contracts or abstract
|
||||
classes rather than concrete implementations. We can easily refactor the above example to follow this principle.
|
||||
|
||||
{% highlight php %}
|
||||
<?php
|
||||
namespace Database;
|
||||
|
||||
class Database
|
||||
{
|
||||
protected $adapter;
|
||||
|
||||
public function __construct(AdapterInterface $adapter)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
}
|
||||
}
|
||||
|
||||
interface AdapterInterface {}
|
||||
|
||||
class MysqlAdapter implements AdapterInterface {}
|
||||
{% endhighlight %}
|
||||
|
||||
There are several benefits to the `Database` class now depending on an interface rather than a concretion.
|
||||
|
||||
Consider that you are working in a team and the adapter is being worked on by a colleague. In our first example, we would have
|
||||
to wait for said colleague to finish the adapter before we could properly mock it for our unit tests. Now that the dependency
|
||||
is an interface/contract we can happily mock that interface knowing that our colleague will build the adapter based on that contract.
|
||||
|
||||
An even bigger benefit to this method is that our code is now much more scalable. If a year down the line we decide that we
|
||||
want to migrate to a different type of database, we can write an adapter that implements the original interface and inject that instead,
|
||||
no more refactoring would be required as we can ensure that the adapter follows the contract set by the interface.
|
14
_posts/06-04-01-Containers.md
Normal file
14
_posts/06-04-01-Containers.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
isChild: true
|
||||
---
|
||||
|
||||
## Containers {#containers_title}
|
||||
|
||||
The first thing you should understand about Dependency Injection Containers is that they are not the same thing as Dependency
|
||||
Injection. A container is a convenience utility that helps us implement Dependency Injection, however, they can be and often
|
||||
are misused to implement an anti-pattern, Service Location. Injecting a DI container as a Service Locator in to your classes arguably
|
||||
creates a harder dependency on the container than the dependency you are replacing. It also makes your code much less transparent
|
||||
and ultimately harder to test.
|
||||
|
||||
Most modern frameworks have their own Dependency Injection Container that allows you to wire your dependencies together through configuration.
|
||||
What this means in practice is that you can write application code that is as clean and de-coupled as the framework it is built on.
|
11
_posts/06-05-01-Further-Reading.md
Normal file
11
_posts/06-05-01-Further-Reading.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
isChild: true
|
||||
---
|
||||
|
||||
## Further Reading {#further_reading_title}
|
||||
|
||||
- [Learning about Dependency Injection and PHP](http://ralphschindler.com/2011/05/18/learning-about-dependency-injection-and-php)
|
||||
- [What is Dependency Injection?](http://fabien.potencier.org/article/11/what-is-dependency-injection)
|
||||
- [Dependency Injection: An analogy](http://mwop.net/blog/260-Dependency-Injection-An-analogy.html)
|
||||
- [Dependency Injection: Huh?](http://net.tutsplus.com/tutorials/php/dependency-injection-huh/)
|
||||
- [Dependency Injection as a tool for testing](http://www.happyaccidents.me/dependency-injection-as-a-tool-for-testing/)
|
@@ -45,7 +45,7 @@ which will delete all of your users! Instead, you should sanitize the ID input u
|
||||
<?php
|
||||
$pdo = new PDO('sqlite:users.db');
|
||||
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
|
||||
$stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); //<-- Automatically sanitized by PDO
|
||||
$stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); // <-- Automatically sanitized by PDO
|
||||
$stmt->execute();
|
||||
{% endhighlight %}
|
||||
|
||||
@@ -69,10 +69,11 @@ one database system that another is missing from another by wrapping your querie
|
||||
This will of course add a little overhead, but if you are building a portable application that needs to work with MySQL, PostgreSQL and
|
||||
SQLite then a little overhead will be worth it the sake of code cleanliness.
|
||||
|
||||
Some abstraction layers have been built using the PSR-0 namespace standard so can be installed in any application you like:
|
||||
Some abstraction layers have been built using the [PSR-0][psr0] or [PSR-4][psr4] namespace standards so can be installed in any application you like:
|
||||
|
||||
* [Aura SQL][6]
|
||||
* [Doctrine2 DBAL][2]
|
||||
* [Propel][7]
|
||||
* [ZF2 Db][4]
|
||||
* [ZF1 Db][3]
|
||||
|
||||
@@ -82,7 +83,10 @@ Some abstraction layers have been built using the PSR-0 namespace standard so ca
|
||||
[4]: http://packages.zendframework.com/docs/latest/manual/en/index.html#zend-db
|
||||
[5]: http://php.net/manual/en/pdo.connections.php
|
||||
[6]: https://github.com/auraphp/Aura.Sql
|
||||
[7]: http://propelorm.org/Propel/
|
||||
|
||||
[mysql]: http://php.net/mysql
|
||||
[mysqli]: http://php.net/mysqli
|
||||
[pgsql]: http://php.net/pgsql
|
||||
[psr0]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
|
||||
[psr4]: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md
|
@@ -40,7 +40,7 @@ catch(Fuel\Email\SendingFailedException $e)
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Use this to let user know email was sent
|
||||
// Executed regardless of whether an exception has been thrown, and before normal execution resumes
|
||||
}
|
||||
{% endhighlight %}
|
||||
|
@@ -14,16 +14,17 @@ In PHP 5.5 `password_hash` was introduced. At this time it is using BCrypt, the
|
||||
|
||||
Below we hash a string, and then check the hash against a new string. Because our two source strings are different ('secret-password' vs. 'bad-password') this login will fail.
|
||||
|
||||
{% highlight php %}
|
||||
<?php
|
||||
{% highlight php %}
|
||||
<?php
|
||||
|
||||
require 'password.php';
|
||||
|
||||
$passwordHash = password_hash('secret-password', PASSWORD_DEFAULT);
|
||||
|
||||
if (password_verify('bad-password', $passwordHash)) {
|
||||
//Correct Password
|
||||
// Correct Password
|
||||
} else {
|
||||
//Wrong password
|
||||
// Wrong password
|
||||
}
|
||||
{% endhighlight %}
|
||||
|
@@ -30,10 +30,11 @@ you run a project which accepts pull requests then you should suggest this as a
|
||||
[PHPUnit](http://phpunit.de) is the de-facto testing framework for writing unit tests for PHP
|
||||
applications, but there are several alternatives
|
||||
|
||||
* [SimpleTest](http://simpletest.org)
|
||||
* [Enhance PHP](http://www.enhance-php.com/)
|
||||
* [PUnit](http://punit.smf.me.uk/)
|
||||
* [atoum](https://github.com/atoum/atoum)
|
||||
* [Enhance PHP](https://github.com/Enhance-PHP/Enhance-PHP)
|
||||
* [PUnit](http://punit.smf.me.uk/)
|
||||
* [SimpleTest](http://simpletest.org)
|
||||
|
||||
|
||||
### Integration Testing
|
||||
|
||||
@@ -56,3 +57,4 @@ data and simulating actual users of the application.
|
||||
* [Selenium](http://seleniumhq.com)
|
||||
* [Mink](http://mink.behat.org)
|
||||
* [Codeception](http://codeception.com) is a full-stack testing framework that includes acceptance testing tools
|
||||
* [Storyplayer](http://datasift.github.io/storyplayer) is a full-stack testing framework that includes support for creating and destroying test environments on demand
|
@@ -4,9 +4,9 @@ isChild: true
|
||||
|
||||
## Behavior Driven Development {#behavior_driven_development_title}
|
||||
|
||||
There are two different types of Behavior-Driven Development (BDD): SpecBDD and StoryBDD. SpecBDD focuses on technical behavior or code, while StoryBDD focuses on business or feature behaviors or interactions. PHP has frameworks for both types of BDD.
|
||||
There are two different types of Behavior-Driven Development (BDD): SpecBDD and StoryBDD. SpecBDD focuses on technical behavior of code, while StoryBDD focuses on business or feature behaviors or interactions. PHP has frameworks for both types of BDD.
|
||||
|
||||
With StoryBDD, you write human-readable stories that describe the behavior of your application. These stories
|
||||
With StoryBDD, you write human-readable stories that describe the behavior of your application. These stories
|
||||
can then be run as actual tests against your application. The framework used in PHP applications for StoryBDD
|
||||
is Behat, which is inspired by Ruby's [Cucumber](http://cukes.info/) project and implements the Gherkin DSL
|
||||
for describing feature behavior.
|
||||
@@ -15,7 +15,7 @@ With SpecBDD, you write specifications that describe how your actual code should
|
||||
a function or method, you are describing how that function or method should behave. PHP offers the PHPSpec framework for this purpose. This framework is inspired
|
||||
by the [RSpec project](http://rspec.info/) for Ruby.
|
||||
|
||||
### BDD Links
|
||||
### BDD Links
|
||||
|
||||
* [Behat](http://behat.org/), the StoryBDD framework for PHP, inspired by Ruby's [Cucumber](http://cukes.info/) project;
|
||||
* [PHPSpec](http://www.phpspec.net/), the SpecBDD framework for PHP, inspired by Ruby's [RSpec](http://rspec.info/) project;
|
@@ -8,6 +8,6 @@ Besides individual testing and behavior driven frameworks, there are also a numb
|
||||
|
||||
### Tool Links
|
||||
|
||||
* [Selenium](http://seleniumhq.org/) is a browser automation tool which can be [integrated with PHPUnit](http://www.phpunit.de/manual/3.1/en/selenium.html)
|
||||
* [Selenium](http://seleniumhq.org/) is a browser automation tool which can be [integrated with PHPUnit](http://phpunit.de/manual/current/en/selenium.html)
|
||||
* [Mockery](https://github.com/padraic/mockery) is a Mock Object Framework which can be integrated with [PHPUnit](http://phpunit.de/) or [PHPSpec](http://www.phpspec.net/)
|
||||
* [Prophecy](https://github.com/phpspec/prophecy) is a highly opinionated yet very powerful and flexible PHP object mocking framework. It's integrated with [PHPSpec](http://www.phpspec.net/) and can be used with [PHPUnit](http://phpunit.de/).
|
@@ -12,7 +12,7 @@
|
||||
* [Derick Rethans](http://twitter.com/derickr)
|
||||
* [Chris Shiflett](http://twitter.com/shiflett)
|
||||
* [Sebastian Bergmann](http://twitter.com/s_bergmann)
|
||||
* [Matthew Weier O'Phinney](http://twitter.com/weierophinney)
|
||||
* [Matthew Weier O'Phinney](http://twitter.com/mwop)
|
||||
* [Pádraic Brady](http://twitter.com/padraicb)
|
||||
* [Anthony Ferrara](http://twitter.com/ircmaxell)
|
||||
* [Nikita Popov](http://twitter.com/nikita_ppv)
|
||||
@@ -29,7 +29,7 @@
|
||||
(PHP support is undocumented but based on stable Facebook partnership [link](http://net.tutsplus.com/tutorials/php/quick-tip-deploy-php-to-heroku-in-seconds/))
|
||||
* [fortrabbit](http://fortrabbit.com/)
|
||||
* [Engine Yard Cloud](https://www.engineyard.com/products/cloud)
|
||||
* [Red Hat OpenShift Platform](http://www.redhat.com/products/cloud-computing/openshift/)
|
||||
* [Red Hat OpenShift Platform](http://openshift.com)
|
||||
* [dotCloud](http://docs.dotcloud.com/services/php/)
|
||||
* [AWS Elastic Beanstalk](http://aws.amazon.com/elasticbeanstalk/)
|
||||
* [cloudControl](https://www.cloudcontrol.com/)
|
@@ -4,23 +4,29 @@ isChild: true
|
||||
|
||||
## Components {#components_title}
|
||||
|
||||
As mentioned above "Components" are another approach to the common goal of creating, distributing and implementing shared code. Various
|
||||
As mentioned above "Components" are another approach to the common goal of creating, distributing and implementing shared code. Various
|
||||
component repositories exist, the main two of which are:
|
||||
|
||||
* [Packagist](/#composer_and_packagist)
|
||||
* [PEAR](/#pear)
|
||||
|
||||
Both of these repositories have command line tools associated with them to help the installation and upgrade processes, and have been
|
||||
Both of these repositories have command line tools associated with them to help the installation and upgrade processes, and have been
|
||||
explained in more detail in the [Dependency Management][dm] section.
|
||||
|
||||
There are also component-based frameworks, which allow you to use their components with minimal (or no) requirements. For example, you
|
||||
can use the [FuelPHP Validation package][fuelval], without needing to use the FuelPHP framework itself. These projects are essentially
|
||||
There are also component-based frameworks, which allow you to use their components with minimal (or no) requirements. For example, you
|
||||
can use the [FuelPHP Validation package][fuelval], without needing to use the FuelPHP framework itself. These projects are essentially
|
||||
just another repository for reusable components:
|
||||
|
||||
[dm]: /#dependency_management
|
||||
[fuelval]: https://github.com/fuelphp/validation
|
||||
|
||||
* [Aura](http://auraphp.github.com/)
|
||||
* [FuelPHP (2.0 only)](https://github.com/fuelphp)
|
||||
* [Laravel's "Illuminate Components"](https://github.com/illuminate)
|
||||
* [FuelPHP](https://github.com/fuelphp)
|
||||
* [Symfony Components](http://symfony.com/doc/current/components/index.html)
|
||||
* [The League of Extraordinary Packages](http://thephpleague.com/)
|
||||
* Laravel's Illuminate Components
|
||||
* [Eloquent ORM](https://github.com/illuminate/database)
|
||||
* [Queue](https://github.com/illuminate/queue)
|
||||
|
||||
_Laravel's [Illuminate components](https://github.com/illuminate) will become better decoupled from the Laravel framework.
|
||||
For now, only the components best decoupled from the Laravel framework are listed above._
|
@@ -6,7 +6,7 @@ The PHP community is as diverse as it is large, and its members are ready and wi
|
||||
|
||||
## PHP User Groups
|
||||
|
||||
If you live in a larger city, odds are there's a PHP user group nearby. Although there's not yet an official list of PUGs, you can easily find your local PUG by searching on [Google][google] or [Meetup.com][meetup]. If you live in a smaller town, there may not be a local PUG; if that's the case, start one!
|
||||
If you live in a larger city, odds are there's a PHP user group nearby. Although there's not yet an official list of PUGs, you can easily find your local PUG by searching on [Google][google], [Meetup.com][meetup] or [PHP.ug][php-ug]. If you live in a smaller town, there may not be a local PUG; if that's the case, start one!
|
||||
|
||||
[Read about User Groups on the PHP Wiki][php-wiki]
|
||||
|
||||
@@ -19,9 +19,10 @@ The PHP community also hosts larger regional and national conferences in many co
|
||||
[php-calendar]: http://www.php.net/cal.php
|
||||
[google]: https://www.google.com/search?q=php+user+group+near+me
|
||||
[meetup]: http://www.meetup.com/find/
|
||||
[php-ug]: http://php.ug
|
||||
[php-wiki]: https://wiki.php.net/usergroups
|
||||
[php-conf]: http://php.net/conferences/index.php
|
||||
[phpc-twitter]: https://twitter.com/phpc
|
||||
[php-programmers-gplus]: https://plus.google.com/u/0/communities/104245651975268426012
|
||||
[php-irc]: http://webchat.freenode.net/
|
||||
[php-irc]: http://webchat.freenode.net/?channels=phpc
|
||||
[php-so]: http://stackoverflow.com/questions/tagged/php
|
64
banners.md
64
banners.md
@@ -12,62 +12,78 @@ Spread the word with _PHP: The Right Way_ banner images! Show new PHP developers
|
||||
|
||||
<p><img src="/images/banners/btn1-120x90.png" alt="PHP: The Right Way"/></p>
|
||||
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/btn1-120x90.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% highlight html %}
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/btn1-120x90.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% endhighlight %}
|
||||
|
||||
## Button 2 (120x60)
|
||||
|
||||
<p><img src="/images/banners/btn2-120x60.png" alt="PHP: The Right Way"/></p>
|
||||
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/btn2-120x60.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% highlight html %}
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/btn2-120x60.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% endhighlight %}
|
||||
|
||||
## Leaderboard (728x90)
|
||||
|
||||
<p><img src="/images/banners/leaderboard-728x90.png" alt="PHP: The Right Way"/></p>
|
||||
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/leaderboard-728x90.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% highlight html %}
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/leaderboard-728x90.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% endhighlight %}
|
||||
|
||||
## Large Rectangle (386x280)
|
||||
|
||||
<p><img src="/images/banners/lg-rect-386x280.png" alt="PHP: The Right Way"/></p>
|
||||
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/lg-rect-386x280.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% highlight html %}
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/lg-rect-386x280.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% endhighlight %}
|
||||
|
||||
## Medium Rectangle (300x250)
|
||||
|
||||
<p><img src="/images/banners/med-rect-300x250.png" alt="PHP: The Right Way"/></p>
|
||||
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/med-rect-300x250.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% highlight html %}
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/med-rect-300x250.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% endhighlight %}
|
||||
|
||||
## Rectangle (180x150)
|
||||
|
||||
<p><img src="/images/banners/rect-180x150.png" alt="PHP: The Right Way"/></p>
|
||||
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/rect-180x150.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% highlight html %}
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/rect-180x150.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% endhighlight %}
|
||||
|
||||
## Square Button (125x125)
|
||||
|
||||
<p><img src="/images/banners/sq-btn-125x125.png" alt="PHP: The Right Way"/></p>
|
||||
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/sq-btn-125x125.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% highlight html %}
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/sq-btn-125x125.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% endhighlight %}
|
||||
|
||||
## Vertical Rectangle (240x400)
|
||||
|
||||
<p><img src="/images/banners/vert-rect-240x400.png" alt="PHP: The Right Way"/></p>
|
||||
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/vert-rect-240x400.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% highlight html %}
|
||||
<a href="http://www.phptherightway.com">
|
||||
<img src="http://www.phptherightway.com/images/banners/vert-rect-240x400.png" alt="PHP: The Right Way"/>
|
||||
</a>
|
||||
{% endhighlight %}
|
||||
|
@@ -6,7 +6,7 @@ title: Design Patterns
|
||||
# Design Patterns
|
||||
|
||||
There are numerous ways to structure the code and project for you web application, and you can put as much or as little
|
||||
thought as you like into architecting. But it is usually a good idea to follow to common patterns because it will make
|
||||
thought as you like into architecting. But it is usually a good idea to follow common patterns because it will make
|
||||
your code easier to manage and easier for others to understand.
|
||||
|
||||
* [Architectural pattern on Wikipedia](https://en.wikipedia.org/wiki/Architectural_pattern)
|
||||
@@ -51,7 +51,7 @@ print_r($veyron->get_make_and_model()); // outputs "Bugatti Veyron"
|
||||
{% endhighlight %}
|
||||
|
||||
This code uses a factory to create the Automobile object. There are two possible benefits to building your code this
|
||||
way, the first is that if you need to change, rename, or replace the Automobile class later on you can do so and you
|
||||
way; the first is that if you need to change, rename, or replace the Automobile class later on you can do so and you
|
||||
will only have to modify the code in the factory, instead of every place in your project that uses the Automobile
|
||||
class. The second possible benefit is that if creating the object is a complicated job you can do all of the work in
|
||||
the factory, instead of repeating it every time you want to create a new instance.
|
||||
@@ -250,11 +250,7 @@ and gives you a central place to hook in code that should be run for every reque
|
||||
|
||||
## Model-View-Controller
|
||||
|
||||
The model-view-controller (MVC) pattern and its relatives HMVC and MVVM let you break up code into logical objects that
|
||||
serve very specific purposes. Models serve as a data access layer where data is fetched and returned in formats usable
|
||||
throughout your application. Controllers handle the request, process the data returned from models and load views to
|
||||
send in the response. And views are display templates (markup, xml, etc) that are sent in the response to the web
|
||||
browser.
|
||||
The model-view-controller (MVC) pattern and its relatives HMVC and MVVM lets you break up code into logical objects that serve very specific purposes. Models serve as a data access layer where data is fetched and returned in formats usable throughout your application. Controllers handle the request, process the data returned from models and load views to send in the response. And views are display templates (markup, xml, etc) that are sent in the response to the web browser.
|
||||
|
||||
MVC is the most common architectural pattern used in the popular [PHP frameworks](https://github.com/codeguy/php-the-right-way/wiki/Frameworks).
|
||||
|
||||
|
@@ -7,14 +7,14 @@ title: Functional Programming in PHP
|
||||
|
||||
PHP supports first-class functions, meaning that a function can be assigned to a variable. Both user-defined and built-in
|
||||
functions can be referenced by a variable and invoked dynamically. Functions can be passed as arguments to other
|
||||
functions (a feature called higher-order functions) and a function can return other functions.
|
||||
functions and a function can return other functions (a feature called higher-order functions).
|
||||
|
||||
Recursion, a feature that allows a function to call itself, is supported by the language, but most of the PHP code focus
|
||||
is on iteration.
|
||||
|
||||
Anonymous functions (with support for closures) have been present since PHP 5.3 (2009).
|
||||
|
||||
PHP 5.4 added the ability to bind closures to an object's scope and also improved support for callables such that they
|
||||
PHP 5.4 added the ability to bind closures to an object's scope and also improved support for callables such that they
|
||||
can be used interchangeably with anonymous functions in almost all cases.
|
||||
|
||||
The most common usage of higher-order functions is when implementing a strategy pattern. The built-in `array_filter`
|
||||
|
Reference in New Issue
Block a user