以下皆为本人自我理解内容,如有失误之处,请多多包涵。
* C- Y* i! [8 F文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 , O" i) ~( S5 M/ ]7 d
{- o6 @& H! i/ ~
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
" d3 G u; t* J0 O据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
! ]4 s1 C' h _4 E( w- J0 B结合使用方法来进一步理解它的使用目的吧。
/ S8 s, j4 z, G5 ~, x2 u# E7 t- `( {) \
1 H7 t4 a. [* T3 D$ O' jnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;7 N% T% d# l: e4 Z8 c' r/ k
- namespace One;' E9 z+ q B1 ]/ A6 W3 A" d
- namespace ONE;
复制代码 ; Q S. p' L. _ F
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
4 L: d1 y" s& r" u2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
0 u/ l' ]7 n4 N6 Q* L8 f - class Person{
6 w+ R @/ a. E; c" ] Y j - function __construct(){
: Y* n+ F/ L3 \$ w( |4 g. q$ O# W! b - echo 'I am one!';
8 N& ~9 g( p' ]+ Q. ]8 v - }
& {" [4 `. B( Q( j( g; p# z. v - }
复制代码- //name.php
- ?" ^ E, c8 c5 e# I - require_once './1.php';" o& P; v* i! O
% ~. `5 O8 `4 _1 _* f- new Person(); //输出 I am one!;
+ C0 R5 u( s. ^ - new \Person(); //输出 I am one!;
复制代码
' [5 L9 L9 a0 |0 P- k3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
; [9 G t; C" H) v! U* Z - require_once './1.php';# i5 N) e- K8 L J" S
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
. q* ?! z4 m& H; B* C: v3 }4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
9 v8 Y) S3 X- t8 f1 u' s$ \# B F - namespace one;" C; f0 k- p) K7 j4 @' n5 ~9 W2 [
- class Person{! p K* [$ Q( Q0 j8 z
- function __construct(){
$ W2 ]8 Y* k! } }+ C1 d5 I - echo 'I am one!';
. Q8 J: [8 r0 d& p - }# q f/ T' j. _0 F5 h; a
- }
复制代码- //name.php
" l& B# J6 t! A8 A - require_once './1.php';
. ~5 m) N- Z- R4 ]& Q a( x - new \one\Person(); //输出 I am one!;
& f: Y$ J+ L" H0 r, ?' t6 } - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
1 C+ \8 F2 ?6 B4 F; p5 `可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 }' }* J+ B! R& x Z
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
% M; W( K5 ]8 N. o' n- //1.php 1 a8 s: ?+ G$ l/ w4 z; i* ?
- namespace one;
9 H' X* a0 s" v - class Person{# i* y4 n3 {* u' S( w% f& ]* k
- function __construct(){/ y* s% ^" I8 `9 x" Q$ J
- echo 'I am one!';
0 b J% |" H( s' B - }
; E! r# G6 k6 c/ [+ o" [* | - }
复制代码- //name.php& L7 p+ \, j: t) i# h
- namespace test;
" B A4 I* G( H+ _. n' O2 _2 a - require './1.php'; / m0 w) y. ~$ A& u# v9 w/ x& z
- new \one\Person(); //输出 I am one!;2 v# W+ M5 E; R, G
- new Person(); //这里结果会是什么呢,猜猜看9 `, Q& i# X$ I q# f r0 F) ~( J
- 最后一行结果报错:
9 S& C B! @3 s+ j7 t - Fatal error: Class 'test\Person' not found
复制代码
8 h6 D- x4 `6 z" J O! D/ c. t) l, m
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 ; f8 i8 T3 b" w
结果报错: - Fatal error: Class 'Person' not found
复制代码 4 K/ @5 f* N9 C
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
, H( L r* g- G, A$ y9 n - namespace test;
4 k9 Q$ \3 L4 T! }$ @6 D* D! z - require './1.php';
4 @+ U+ B$ d$ }# r# u
; p/ m q- [1 }3 }- w- class Person{
+ i6 i- k3 z' d- t! h- d - function __construct(){
( \ M+ W& r: l& H - echo 'I am test!';: v% f5 F. ^. j
- }
7 A8 g, X* g( c" U! r - }
4 a! D- V$ S# w4 H5 F' B
- ^# `3 v7 S' ], p7 w' V- new \one\Person(); //输出 I am one!;# y" k6 N9 w; Q4 a9 o) w4 O+ u
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
$ n. v! J5 ~2 _6 b最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
% M" X+ y% K& I& M8 m9 m - namespace test;
. E+ c& R6 R% j, \' C D3 V; r" s - namespace one;( t) B" j4 U& e5 h- w' c
- class Person{
6 F0 z1 w# { H - function __construct(){
& i* N# ]2 _: A - echo 'I am one!';
4 V( T# h' m D f# ~1 E6 e - }
" L* w, Z: ~- P" M' g - }, |- a3 L: i/ L' f% V6 e6 [5 i3 Z
- " y4 J M" J } `- |4 H3 L
- class Person{# W4 ^7 t! {! r8 {; c
- function __construct(){
+ k8 u6 v6 X P# _, y6 K! L - echo 'I am test!';5 i+ _7 B2 I: w/ Y9 W7 [$ h9 a
- } W. ]- Z9 w; K- X1 h& S i6 U
- }
复制代码
- `5 y) {7 o6 a/ W! O* o/ p无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 ; K W1 M- v7 _! D; m" Q
看来简单的把require理解为替换,在这里行不通。 + g" W/ s g' ?5 |3 _- S
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。. O% L4 J0 W" `
- //name.php
4 `* x: K9 H! u- Y+ C
7 O' H' x# `( q" Q. |$ k% g9 @" w7 [- namespace test\person;: e2 b4 }4 K9 ^2 D( K' n5 q7 K
% `# g" L) Z: I) r- class Person{
& z0 B/ D3 x3 }* u- o - function __construct(){
* r D3 o9 ^* Q( _ - echo 'I am test!';
m; q, @+ h ? - }
6 N) ^/ v3 E6 c - }8 i% d' @3 i' t
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 1 |1 y* e' O4 n. q- Q
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
8 }$ k, L& T! q& s1 u" }7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
" j/ |: }2 ]8 X
8 A3 p7 x5 Q3 y( R7 X2 G- namespace test;+ O6 S2 j. x7 p- G8 `! s6 R( H
- echo 'zhai14';3 t; H5 g( ]) P' l) \
- namespace zhai;
! ]& H6 f+ I! S: _2 ], b - require './1.php';
复制代码
4 \ H; {9 J% C* Hphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 5 n, D+ v: S) K% r
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
5 u% E& k$ D$ G2 A( v& X# G$ B- //name.php
D0 w* ?2 {' `+ {+ ~ - ) z5 q# e) |% u, b
- namespace animal\dog;
/ U6 \+ w6 P) K9 S# C3 w) _ - 1 v0 r6 ^( E* C8 v1 L, r4 [
- class Life{" j1 T- Z0 H& [
- function __construct(){0 ?' c# _' v; L' l
- echo 'dog life!';
, B- r0 \/ p2 D4 ]9 Y - }
' X! U' s$ R- G6 w* ^( O - }! {9 d& Y4 k" L% u4 S% N
! X; b% o9 ?3 V; d* h- namespace animal\cat;
7 T& c0 O( M7 k R8 G0 F' P" Y Z
0 N8 D6 l2 C7 b. v- class Life{
3 h/ _ w. q: t2 T - function __construct(){
! t9 M: {+ V; j+ S% v - echo 'cat life!';8 p% w2 c8 h3 }# w4 L) K
- }
6 J! C8 v8 b* j# G6 G7 h - }
: H& `" x9 H" ^+ j. V
6 H6 y2 g+ N5 `9 M& G- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间' J% n3 Y y& c; H, S5 i0 T! l
- new \animal\dog\Life(); //A3 w( d% f' ]: O, D2 N0 V
7 v9 R( M: E3 p- use animal\dog; //a
2 H- }+ k- S( K* g. Z - new dog\Life(); //B& t+ ~7 j* w# k! ?/ \
- 6 B6 e5 o! m3 K4 E! D1 c5 ?
- use animal\dog as d; //b6 u: ~% J1 k& X0 {' r
- new d\Life();
复制代码
! Z5 S$ n% D6 ^# ]通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
# T- w" ]' d# u W; r6 {$ y通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
% G4 w" z$ _& [8 x3 ^& R: p相当于
. F" |3 v5 P7 m& k( D: y( L0 f2.namespace后面不建议加类名,但use后可以。
6 S. c0 G+ E0 K8 m# K9 D- //name.php |: ?/ a/ o- x' N
( ^, X. x) ^& c* }3 u$ Q) A- namespace animal\dog;- Y" W5 D/ ~: Y7 a @+ b, `- U
- T: D* e& C! Z) @4 P5 Y$ m
- class Life{$ z8 ^' h* O6 {+ s" s6 B
- function __construct(){
5 k( B g; r* ~8 G - echo 'dog life!';
4 k; J0 ^* U/ |/ q6 h* A) _. `0 ? - }4 L8 t1 W' ^0 g2 e5 P+ X
- }
5 Y5 p o$ |6 n, h/ W3 I - : A# F B& X' o/ y
- namespace animal\cat;) A) E" z3 ^# F% ]/ d
- , X: N7 Y1 ?3 X. q! X
- class Life{0 U* K( S J$ _. }. U
- function __construct(){" [9 j6 i- L4 X$ C; I. V" T
- echo 'cat life!';
, R+ r# h. o$ Q2 `* h. c; B$ a8 W3 C - }& m2 p0 l+ ~4 ~: z
- }6 S( l% M) D2 C: a0 S0 T
- ; B; I: e1 ]1 ?0 Z
- use animal\dog\Life as dog;
9 `8 x, t4 S) O) Z - new dog();
复制代码 $ d7 V8 z% h, d* r
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 3 D% J, x& A. J h
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php: T6 a3 M2 E( T# h1 F, ?
7 O' @% \0 E) m- a# U( d+ S5 u( _- namespace animal\dog;. B* Q U1 S7 J/ z! w
: u0 ^' H% m" R) M! X9 N- class Life{, W% U5 E# f$ W: j- O6 B1 x1 ~
- function __construct(){
# N9 R' F) V$ r* f; Z - echo 'dog life!';5 Y4 q7 b0 Y2 W; A# w4 n
- }; z: z0 i a, o, g
- }
! G' r7 U' f# f - class Dog{
1 @5 c% d+ r. N2 o3 a( ] - function __construct(){5 o' `. H0 g4 |8 j* j/ ]
- echo 'dog in dog!';
. y6 ^5 z3 m; q' c1 j9 k! y8 Z - }
4 |# e8 N# t3 R$ A - }5 [5 z- Y- K) Z, j
2 G. }: u% y) ~' m3 W' O- namespace animal\cat;& g% X) S9 [& \4 N# V _2 S) v
- * Z G x. f9 z- T; L
- // class Dog{
, |+ T- h9 J9 ? J5 z - // function __construct(){! k6 e! Z8 h i* v4 t
- // echo 'dog in cat!';
5 {# n5 s' v! O - // }
' y1 q ]2 @3 C" Y2 B5 ? - // }1 F! f8 [* P; M8 v0 P' [2 k
- class Life{/ v0 \$ `, ^# u9 i1 }
- function __construct(){* X& n' R% ]) x O/ W; L
- echo 'cat life!';7 o+ C' F6 [1 q$ A# W/ N
- }
+ m: N& y! u' a1 u - } |' q/ u, \+ o+ P# w' ?6 q1 C/ a
- [" k0 W% ^+ y6 W& s* Q- use animal\dog; ( K0 l) [4 ?* J) s2 z/ m0 d
- new dog\Dog();
复制代码
* _+ {; B( N6 {9 z9 d( A+ q如上,使用了
# X$ }. J7 H" L, D: M) ^7 J7 Ucat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
- k% ~* r2 |& j/ k简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
9 X$ c6 \' q5 L3 ?/ N( G: b& C/ }
! Y6 Z4 F% B9 v! {
2 k7 _; ^. p3 m0 o. T& E& h }
, l' i* I: k1 q, F4 E9 a+ S |