A Brief Introduction to PHP Namespacing
来源:互联网 发布:java gmt 时间戳 编辑:程序博客网 时间:2024/04/26 18:14
A bit of history #
In PHP prior to 5.3 (2009), any class you define lived at the same global level as other classes.
Class User
, class Contact
, class StripeBiller
--they're all together in the global namespace.
This may seem simple, but it makes organization tough, which is why PHP developers started using underscores to separate their class names. For example, if I were developing a package called"Cacher", I might name the class Mattstauffer_Cacher
so as to differentiate it from someone else'sCacher
--or Mattstauffer_Database_Cacher
, to differentiate it from an API cacher.
That worked decently, and there were even autoloading standards that separated out the underscores in class names for folders on the file system; for example,Mattstauffer_Database_Cacher
would be assumed to live in the fileMattstauffer/Database/Cacher.php
.
An autoloader is a piece of code that makes it so that, instead of having to
require
orinclude
all of the files that contain your class definitions, PHP knows where to find your class definitions based on a particular convention.
But it was pretty messy, and often ended up with class names likeZend_Db_Statement_Oracle_Exception
and worse. Thankfully, in PHP 5.3, real namespaces were introduced.
The basics of namespaces #
Namespaces are like a virtual directory structure for your classes. Soclass Mattstauffer_Database_Cacher
could become class Cacher
in the Mattstauffer\Database
namespace:
<?phpclass Mattstauffer_Database_Cacher {}
is now:
<?php namespace Mattstauffer\Database;class Cacher {}
And we would refer to it elsewhere in the app as Mattstauffer\Database\Cacher
.
A real example #
Let's take Karani--it's a CRM with a financial component, so it tracks donors and receipts, among many other things.
Let's set Karani
as our top-level namespace (sort of like the parent folder--usually named after your app or package). This might have some classes related to Contacts, and some related to Billing, so we're going to create a sub-namespace for each, Karani\Billing
and Karani\Contacts
.
Let's make a class or two in each:
<?php namespace Karani\Billing;class Receipt {}
<?php namespace Karani\Billing;class Subscription{}
<?php namespace Karani\Contacts;class Donor {}
So, we're picturing a directory structure like this:
Karani Billing Receipt Subscription Contacts Donor
Referencing other classes in the same namespace #
So, if a Subscription can send a Receipt, it's easy to refer to it:
<?php namespace Karani\Billing;class Subscription{ public function sendReceipt() { $receipt = new Receipt; }}
Since Receipt
is in the same namespace as Subscription
, you can just refer to it like you would if you weren't using namespaces.
Referencing other classes in different namespaces #
OK, but what if I want to reference a Receipt inside of a Donor?
<?php namespace Karani\Contacts;class Donor{ public function sendReceipt() { // This won't work! $receipt = new Receipt; }}
You guessed it: This won't work.
We're in the Karani\Contacts
namespace, so when we wrote new Receipt
, PHP assumes we're talking about Karani\Contacts\Receipt
. But that class doesn't exist, and that's not what we're looking for.
So, you'll get a Class Karani\Contacts\Receipt not found
error.
You might be tempted to modify it to instead say $receipt = new Karani\Billing\Receipt
--but even that won't work. Since we're in the Karani\Contacts
namespace right now, it's seeing anything you write as being relative to the namespace you're in. So that would try to load a class namedKarani\Contacts\Karani\Billing\Receipt
, which also clearly doesn't exist.
Use
blocks and Fully-Qualified Class Names
Instead, you have two options:
First, you can precede it with a slash to create its FQCN (Fully Qualified Class Name):$receipt = new \Karani\Billing\Receipt;
, which sends the signal to PHP to escape out of the current namespace before looking for this class.
If you precede the full namespace with a slash, creating the FQCN, you can refer to this classanywhere in your app without worrying about your current namespace.
Or, Second, you can use
the class at the top of the file, and then just reference it as Receipt
:
<?php namespace Karani\Contacts;use Karani\Billing\Receipt;class Donor{ public function sendReceipt() { $receipt = new Receipt; }}
As you can tell, use
imports a class from a different namespace into this namespace so we can refer to it more easily. Once you've imported the class, any time you reference Receipt
in this class, it'll assume you're pointing to the imported class.
Aliasing #
But, what if you also have a Receipt
class in your current namespace? What if your class needs access to both Karani\Contacts\Receipt
and Karani\Billing\Receipt
?
You can't just import the Karani\Billing\Receipt
class, or you won't be able to use both--they'd both have the same name in this class.
Instead, you'll need to alias it. You can change the use
statement to something likeuse Karani\Billing\Receipt as BillingReceipt;
. Now you've aliased the class, and then you can refer to the imported class as BillingReceipt
throughout your class.
PSR-0/PSR-4 Autoloading #
You know the folder analogy I just used above?
It's easy to think about your classes that way, but there's actually not any inherent connection between your namespaces and your files' structure. Unless you use an autoloader, PHP doesn't have any idea where those classes actually live in your directory structure.
Thankfully, PSR-0 (now deprecated) and PSR-4 are autoloading standards that actually map your namespaces to real folders. So, if you're using PSR-0 or PSR-4--which is extremely likely if you're using Composer or any modern framework-- and a compatible autoloader, you can assume that the classes actually are in folders.
Composer and PSR-4 Autoloading #
So, let's say I want the Karani
namespace to live in my src
folder.
Here's my folder structure for a generic, framework-independent project:
apppublicsrc Billing Contactsvendor
As you can see, the src
folder represents the Karani
top level namespace. Since I'm using Composer as my autoloader, all I need to do to get my application to autoload my classes is teach Composer how to map namespaces to folders. Let's do that using PSR-4.
I'm going to open up composer.json
and add a PSR-4 autoload section:
{ "autoload": { "psr-4": { "Karani\\": "src/" } }}
So you can see: the left side is the namespace that we're defining (note that you need to escape the slash separators here by doubling them), and the right side is the directory.
Conclude. #
As you can see, there's a lot going on here, but it's really pretty simple: 98% of the time, you're going to be working with a PSR-4-structured, Composer-autoloaded, set of classes.
So 98% of the time, you can check your composer.json
, figure out where the root of the top level namespace lives, and assume you'll then have a one-to-one map of your namespace and the folders/files in that directory. Done.
And remember: next time you get Class SOMETHING not found
, you probably just need to remember to import it with a use
statement at the top of your file.
- A Brief Introduction to PHP Namespacing
- A Brief Introduction to IoC
- A Brief Introduction to IoC
- A Brief Introduction to REST
- A Brief Introduction to REST
- A Brief Introduction to OVF
- A Brief Introduction to Myself
- A brief introduction to VXLAN
- A Brief Introduction to XACML
- A Brief Introduction to UNIX SHELL Virus
- A brief introduction to geospatial coordinates
- A Brief Introduction to Multiset[STL]
- A Brief Introduction to Language Modeling
- A brief introduction to feature selection
- A Brief Introduction to Digital Video
- IoC 简介:A Brief Introduction to IoC[读后感]
- A Brief Introduction to the JTAG Boundary Scan Interface
- A Brief Introduction to the JCo Server - Austin Sincock
- iOS 并行开发技术之 NSOperation && GCD
- Android Volley完全解析(四),带你从源码的角度理解Volley
- Hadoop分布式文件系统:架构和设计要点
- 剑指offer 55-字符流中第一个不重复的字符
- 《鸟哥的Linux私房菜》第四章 安装CentOS 5.x与多重引导小技巧
- A Brief Introduction to PHP Namespacing
- OJ期末模考B
- pixhawk学习笔记-----mavlink
- 136.求最大值
- SCAN----Redis检索键值对
- doT js模板入门
- OJ期末模考C
- 一个关于多态之虚函数的例子
- 【算法】9 散列表【待补充】