Merge branch 'gh-pages' of github.com:codeguy/php-the-right-way into aranw-errors-exceptions

This commit is contained in:
Phil Sturgeon
2014-02-17 11:23:47 -05:00
44 changed files with 293 additions and 95 deletions

View File

@@ -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/)

View File

@@ -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>

View File

@@ -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>

View File

@@ -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.

View File

@@ -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/

View File

@@ -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/

View File

@@ -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

View File

@@ -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]

View File

@@ -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

View 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.

View 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.

View 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.

View 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.

View 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/)

View File

@@ -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

View File

@@ -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 %}

View File

@@ -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 %}

View File

@@ -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

View File

@@ -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;

View File

@@ -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/).

View File

@@ -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/)

View File

@@ -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._

View File

@@ -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

View File

@@ -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 %}

View File

@@ -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).

View File

@@ -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`