以下皆为本人自我理解内容,如有失误之处,请多多包涵。
9 a* I7 f+ ~! ]8 U7 U! h7 ^. d文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
; Q! z3 |) X+ m" K ?$ D L$ j: c4 z* p
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; , i- J/ {9 @+ c) A5 }
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
2 Z) o% R+ j8 M, M, T结合使用方法来进一步理解它的使用目的吧。 ) e6 j- b( c, g' w; g
4 t( K; P2 n7 m9 l# S0 W6 i
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;8 [+ O; p% L6 y. Y% [! a
- namespace One;, g- ]: C) L, {& K* F$ ^' J: h8 q. u
- namespace ONE;
复制代码
) ^2 u+ Q z O4 {如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 4 H1 e: D* _( |! g
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
" j3 d8 D) ~' c$ ^ - class Person{
' d5 P: q1 g0 @( D - function __construct(){+ R8 T8 v2 L7 F
- echo 'I am one!';- k' g/ h9 k$ U
- }
3 X- ~% u; a3 k/ |0 L0 `1 m1 ^ - }
复制代码- //name.php$ v. ~9 ], Y# B* j: f7 l
- require_once './1.php';
. D4 _$ ^/ \' O! g7 ~5 E - 9 m8 u3 H& F1 D/ e
- new Person(); //输出 I am one!;
9 G1 I! }+ L/ R# O& M7 W - new \Person(); //输出 I am one!;
复制代码 ) \& `$ [& Q% h+ U* E8 j
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php# G4 ]; z; p+ s- l: ^% x- ]
- require_once './1.php';
3 ]: ~% u' ?9 o - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
. o2 K5 m+ `3 e7 k4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
: {9 k. ]/ W/ }6 X4 D' z - namespace one;8 Q7 T4 X. n- ]7 a2 z
- class Person{
( w3 n- n: u1 c8 R5 X* u8 K - function __construct(){5 |6 _4 b& a8 k8 j; Y3 a
- echo 'I am one!';
4 r) J% V% P- d1 @# b/ E% `* q; H - }
% {! V2 A3 Y8 r! ]/ |3 f2 K - }
复制代码- //name.php
* W: C8 A/ Y" p7 k+ J- j1 ?. _, x - require_once './1.php';2 {, x; X& r. c) ^ M( H
- new \one\Person(); //输出 I am one!;
$ D I7 `- t! t5 E9 E. [) j - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
: i P5 G% \, u" Q可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 3 e) p8 w8 _3 o, m6 S6 p% \
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。1 J/ i+ B j8 r
- //1.php
/ \+ C) e, ?) L6 b$ f; h2 N - namespace one;3 s. P- O) R Z" F
- class Person{# _0 C( |6 ]) z J5 W2 z3 i- b
- function __construct(){
4 u E& r$ _3 q - echo 'I am one!';* G7 q. J% O& Z9 u
- }7 ^4 ]5 h, i N4 ~, x
- }
复制代码- //name.php
% Y! u7 Z8 @( c - namespace test;/ k( j1 C) q9 n# C, u" h
- require './1.php';
+ ?% f% z' Y6 R0 ~/ r8 j# j - new \one\Person(); //输出 I am one!;
" [1 M' D' f$ M$ h" U* n - new Person(); //这里结果会是什么呢,猜猜看
6 n4 y# _1 C% k - 最后一行结果报错:/ `; [7 A5 b+ A9 _1 V$ R9 y; W
- Fatal error: Class 'test\Person' not found
复制代码
9 B: Y- R" ?7 X1 w3 M
; `8 W' i- G2 j& I: Y首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 ! l, N$ z4 c; i
结果报错: - Fatal error: Class 'Person' not found
复制代码 . I5 n& j/ j' W( T
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
$ v+ m, f6 O- |1 L - namespace test;
3 x; n) S8 W1 h) w+ E+ r3 X - require './1.php'; 8 @' P% V5 ?& T% G. ~, F3 Q
- ! p. x- i$ E( Z" C& e6 v# G
- class Person{& ]6 a7 ]" T1 w/ i/ C: F# i7 T
- function __construct(){
9 A9 [/ Q' d! r1 @* `" ` - echo 'I am test!';
8 s; C0 @) t9 ~3 E - }
. R2 r: `. `- _5 t8 u7 E9 \ - }1 a/ p: G6 U) c8 y( m
- 9 `3 B+ r) d) e5 ~& e: ?* S! [# s4 G- F
- new \one\Person(); //输出 I am one!;
8 q" A8 {; e5 u) p - new Person(); //这里结果会是什么,自己猜猜看
复制代码 , E u, S3 f( K. M( M U
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
% ?% t- L" v3 ~ - namespace test;
E7 s% ?- C- }2 n' ]6 l1 f - namespace one;# l! l9 T( c9 [7 }2 [
- class Person{
# L- k" z. l0 f. [, x4 O4 ?7 U - function __construct(){
) m" o! g O5 W* E) y - echo 'I am one!';# d/ Y7 _* ?- `* ]
- }" K% y$ V3 P9 n
- }
6 \$ F: I% E x& ~2 h: U2 q- { - / S- r" `) m9 g* t- G7 t% ~
- class Person{
, x, `% [/ j1 c" z - function __construct(){
6 w' W( j* v8 Q- y& R( T: ^$ e' `8 D, D - echo 'I am test!';
' u+ p3 [8 T& z# { - }
. M5 x' s. U2 t! T; u% p1 \7 h - }
复制代码
' c9 M" W3 ^9 u7 {无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 ! K7 L+ Y0 y: P9 P- _2 M3 T
看来简单的把require理解为替换,在这里行不通。 2 a. k2 K# V' ^, b- V( @# S: ~
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" v; y4 |2 y9 T- //name.php# } @! Y9 C% W4 N2 ]
5 |$ c. h* n9 g- namespace test\person;
8 k6 e- U0 M7 G% f - 5 o9 r5 ~! {& \% n8 H5 j
- class Person{
" t4 M' F3 T, J, V8 @ - function __construct(){
2 F! d4 D5 X, E4 s0 D - echo 'I am test!';5 d+ P1 r# h D& W4 a; ?0 v
- }
2 B. r8 _" K K2 i3 c( Q5 { - }! d" b- W% c' o: }' z7 w; g$ v+ u: T4 {. L
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 3 c* D- }7 m& R! {. K3 Q9 k& L
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
7 R+ R7 W' n6 Z0 W7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php# i, Y9 d3 i- l& ^; t5 g# _
" c' Y7 U4 S. H1 C- namespace test;
5 s( d& H" J4 {) Q8 r* r) b - echo 'zhai14';
" a4 A, ~ S# G+ _& | - namespace zhai;+ H* t# J, M f+ V
- require './1.php';
复制代码
" D' ~: x* [: W) W# K8 ~php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
* Y2 ]8 K) Y$ D) |. cuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
) D( Z. l3 D0 @/ b$ T- //name.php
+ s8 F/ O$ S; R$ M0 H" k
: a$ U0 x3 ?) M% v9 c- namespace animal\dog;
- [9 m, O% X; i9 F
& ?( y5 a7 M! [- class Life{& D0 ]" j9 d+ S/ n& ~
- function __construct(){+ _! O/ t7 ~. G' k/ _3 z0 K' S
- echo 'dog life!';# M! U6 U u) w8 E3 y4 J
- }# X* ~1 T, w2 P: I1 Q% J
- }
3 |- i6 @$ o$ ^' Z8 n6 a! O+ z' B
. L {/ r- R+ t" E- namespace animal\cat;0 f% C' x. _$ e( q) n4 P$ q' f
# y$ q: @# p$ a! |% @2 I& K& W7 _- class Life{
5 @; [) u u7 m& Q2 Q6 A - function __construct(){
) A6 }2 Q/ ~ J* I. L7 Q - echo 'cat life!';. W9 g# S# `& J0 `
- }% q2 M% I9 V* v4 x& y0 t
- }
/ V) n% J3 U- C$ Q4 n - # w' S- X9 }5 d' P2 v
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
e) O1 H, R0 N2 u# t - new \animal\dog\Life(); //A, |. p4 q. G$ U) L
- 0 [! l) o- v. s
- use animal\dog; //a
0 F7 z* E9 K' T) _: ~- D, h - new dog\Life(); //B" }: P! e1 F6 _, _8 v
- + Y: {! G" L( f5 i& S! R
- use animal\dog as d; //b
$ E% t/ o' ^; g7 P4 S" l# o - new d\Life();
复制代码 ( R- F4 |# ~$ V6 G+ d
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 9 \" U/ k5 \, b9 f5 p( d- i
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
7 S5 _ I4 L0 A! t1 h- ]相当于
% @( Q! P) y* G, N) i2.namespace后面不建议加类名,但use后可以。
& G: b s( M, | y0 Y7 v% B/ y0 C- //name.php. O8 r7 n% j) p% [2 C/ h0 [
- , L* |# o( S# z4 U$ J& H
- namespace animal\dog;( t2 J& u, ~2 H# _/ R
! s. ^; v0 }9 ]- y/ m5 J, G9 ?3 m# }# x- class Life{4 l- F1 E) h2 ^" ]& j
- function __construct(){
! h: K2 F% B6 C6 M2 _ - echo 'dog life!';
6 B2 e. a1 x" H9 R$ a/ y - }, G) I7 n; L8 _8 m9 {
- }/ E1 j9 a- p5 E4 y2 P' i
, y! H" \4 x% d( h2 o% n* h- namespace animal\cat;
$ R7 r X8 q- N9 y1 | `8 J) C - ; x% w+ Q7 B5 d6 m" S
- class Life{1 @: I( z" p( e. [( D: B
- function __construct(){
/ C( i4 y6 ]# K0 e5 M4 A - echo 'cat life!';
! w% B+ [/ {1 ~' f* P, J1 ~: L: } - }
, k+ Y. M/ ?% p& Z# a) f - }/ W/ b u; T6 \/ s+ b
( C. \2 ~# @7 V* I( _+ a1 d/ h" t2 j' n- use animal\dog\Life as dog;
( S8 F/ ?9 Q6 z4 ~8 U - new dog();
复制代码 ( I9 t; @; U, _6 j5 A. m( X x
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
7 e# l8 P$ N- m/ @8 t因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
0 D% d/ F, y' B8 J3 l& x$ H - 3 ^, W) q4 [- D$ e
- namespace animal\dog;
2 u8 t+ r7 C* E8 H. Z' m9 l
$ X a* c& c1 [3 y- class Life{. h' F8 \5 L* }$ r$ U: g
- function __construct(){) E, V+ f" f9 A8 ~2 {9 y0 s& t2 C1 Q% K
- echo 'dog life!';
$ f* R& U; k1 f) x' w - }
' d, }* G- g+ F. x. z. |! W+ I - }
6 {3 d' F! d! z% ?# T. G - class Dog{
4 D1 |7 G: A+ Q9 F- [1 t - function __construct(){
j/ o6 ?- z% _+ D" W# S - echo 'dog in dog!';9 Z) C& C4 d: \4 V' W
- }; q. u, s% [% `6 d
- }7 o4 K* T4 m; `- [0 n9 w* ?/ a0 R
/ c& k P/ Z5 Z+ \9 V+ R# k- namespace animal\cat;
: {0 _) i3 T% L v- H* Y
& G, D9 Y5 ^- J2 A3 Z- // class Dog{* f* s; }1 t3 Q& M a5 c
- // function __construct(){
, x! `; H f; t s - // echo 'dog in cat!';
( K4 r6 Z' r- K% O7 Z; z4 q - // }
3 j) g0 N: a, h' y - // }
- r0 y5 r9 ^9 Q+ I - class Life{( u9 z% l* ^7 u6 \
- function __construct(){9 e$ t8 y, `( N0 V( u0 Z
- echo 'cat life!';
% @7 U4 e* S7 j. K3 j3 g - }
* m3 M, W8 z1 ?; {4 n* ]1 r - }. I! T& k, {/ B) n5 Q3 E2 C
# ]# L$ |, D1 ?# a1 e8 e$ I' N- use animal\dog; - f5 F& m- i" n) h1 a3 @
- new dog\Dog();
复制代码
* n4 q& n! U$ C1 T' u3 E! |如上,使用了 " J# K# U s/ ^* A$ b
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
$ H) o+ e: B* ~7 f! ^" Y$ Q' m0 r4 S简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
I0 g4 k {5 k2 q4 g2 `! c3 ?+ w8 I
2 R4 C( |0 O' @& h3 k" h1 j, X: g
1 d" ^: s* W( B( i |) S; g) y
" |* E5 F/ y& t; T6 Y |