以下皆为本人自我理解内容,如有失误之处,请多多包涵。 # T* M4 E( |/ w
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 . f; E: K7 r& ~) L- h, ~0 f& [4 X
- p" F* ~3 j- [& y4 e' ]- y使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; - x, W3 n- v) @9 f" M* Y9 R
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
$ }7 j$ W: D( I结合使用方法来进一步理解它的使用目的吧。
- z- q6 F' e* R) a1 [; C; L- ?3 T! Y* Q
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;1 |- l X# q. X$ h+ L4 N4 D
- namespace One;
! j. \$ R+ z( E) o+ h - namespace ONE;
复制代码 : \! r$ s; P/ X; |
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) G+ w) ?! L* Z, R
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php / q8 S3 B; ~5 ?5 q9 g' c
- class Person{+ Q( l" L9 D& w$ B; S" E, J; v' _7 ]
- function __construct(){: v4 w0 u5 u# n Q% {
- echo 'I am one!';
0 T* [0 [/ Q* }/ ~2 s( C4 b0 \& M4 ? - }: g$ m2 {7 Y3 X# f
- }
复制代码- //name.php' b3 B5 k k4 ?: v. `
- require_once './1.php';
& {5 @& p2 w& ~+ D; u; u k
8 A: s8 p3 T! p! D- new Person(); //输出 I am one!;
( w5 I( q( p7 N - new \Person(); //输出 I am one!;
复制代码
) C" W. d1 ?2 ]" d0 H3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php3 o, t( Y6 q2 w
- require_once './1.php'; X( i5 U B" E) y$ e! W0 Z
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
6 T; b$ \) h5 J8 p6 a4 w9 H' H. u4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
2 B! D' z) T( |% P0 D1 n, t( Z# s - namespace one;
7 r9 G- D5 o5 e* M0 L+ y& k - class Person{
- d0 K4 J: W+ L- p% x6 q. S# ]$ r - function __construct(){
6 f, `, B. L% J6 |; r! ? - echo 'I am one!';, b! ^; V9 q8 e$ S# I6 q/ p3 v, {* l2 F
- }1 S9 s! ~% Y9 t1 ]; o; m
- }
复制代码- //name.php" a1 j' B, n5 z& X: d/ J
- require_once './1.php';
1 L R! |4 T! r) Y3 x1 M& ` - new \one\Person(); //输出 I am one!;% \& ^2 p- c4 w& _% u9 T- D; Q
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 * ^+ Z0 [1 H5 U, r0 j% \
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 & |" t5 q% w, U6 ?$ }
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
: p7 @; R% U L, @8 X! I% |5 S- //1.php % C2 n, V/ ^& [& g. r Y8 B
- namespace one;
: Q5 Y: Z# b! m8 i( X" t/ O - class Person{
9 k, u. B0 S. y4 B# r6 z) \+ x - function __construct(){
- F" |, e! |$ ] - echo 'I am one!';
4 R5 T& g% A9 y; B/ v+ _1 S - }. A& @1 o$ G; X6 a1 @7 \' P
- }
复制代码- //name.php5 D, j3 r! V7 T$ N J2 @% e( S# o
- namespace test;8 Y6 }$ Z1 x2 C9 m; a, B4 p
- require './1.php'; 6 y; E& W: f: O* V& ~
- new \one\Person(); //输出 I am one!;( {3 r7 J& S$ v0 c% V
- new Person(); //这里结果会是什么呢,猜猜看
7 O' T/ g" m4 l6 x! g4 O7 [ - 最后一行结果报错:
2 t5 P9 @& N! d - Fatal error: Class 'test\Person' not found
复制代码
4 {! I( i4 [: \$ Z' h- n, g! T
5 p5 X! ]7 M3 D6 @0 y0 E6 M9 _首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 ) N, N3 k, g, w9 Z( d
结果报错: - Fatal error: Class 'Person' not found
复制代码
6 m2 v; f# ?* v3 D接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php8 X/ Z i$ R( f
- namespace test;2 o' |+ m' t v# F9 A' Y \$ }
- require './1.php'; 0 Q6 Z5 ^1 R! n5 j1 v) i
! W# b9 I# Y; V- class Person{" m9 _! \ Z6 v, P
- function __construct(){
5 r0 C. J- H, b5 r% L) J - echo 'I am test!';# x# p$ t8 b3 A7 \+ @( f: d! G
- }; k3 T) a4 U6 S8 W: V1 V
- }
! p% ]& p( r% U+ ^/ V - e8 r0 i k$ O+ B7 k8 T( V
- new \one\Person(); //输出 I am one!;4 n- a2 _6 P( B7 x" c7 J
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 / j: \% B; W6 n( C5 c* e
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
$ s6 V+ N8 V8 O3 Q9 O - namespace test;! m7 ~+ E: A) s- I1 Z
- namespace one;
! K3 D" K7 h+ t! P1 t - class Person{
/ ?4 Y! E7 i+ t: E: b - function __construct(){
$ `5 o2 Q/ U; B1 t) @1 O [ X - echo 'I am one!';
8 w8 T8 h% J2 Z. d& W - }
* O9 Q4 Y3 K: k3 r - }
6 _0 v" C0 T6 |/ ^/ n
+ T: P+ f7 u- d0 F- class Person{- C& R/ r0 A- @2 C G+ V( y3 A1 ]2 ^
- function __construct(){
* T* M, a/ p& C3 j# ]. }4 j - echo 'I am test!';
. c. R" f, r; r X& V - }
& B* L4 u0 d5 v4 B: ^* C! K - }
复制代码
0 t$ O. [8 {- j# K) G$ ^' m2 M无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
6 y5 ~6 m. |, g1 S看来简单的把require理解为替换,在这里行不通。 4 R9 w8 W. s# Z1 X& D
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。2 Y1 l! |6 ]4 W3 @9 z5 V, R5 `: w
- //name.php
) w9 T: n- m& Z8 m) ~8 K Y
6 z+ b4 m$ ~& e; F! f5 L3 K- namespace test\person;% }( L6 b- s' z5 J
W$ h& b/ X0 M3 z, ]( x3 d- class Person{8 Q# V2 {4 H7 |$ Z9 U9 p+ M: Y4 s0 w
- function __construct(){
% Q3 H% n0 n W$ X. q( b - echo 'I am test!';/ ?5 c, c, l( Y9 s: x: |3 ?
- }3 {% i$ M+ M3 g b
- }& x: J+ _$ d# ~+ g0 L
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 2 `2 L. R* ~+ p7 S- _
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 , a- t3 C: B8 q0 R9 O
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php7 N, ], s8 M& {" k6 l
4 ]3 D L! D: t/ Y. v6 c: W- namespace test;% n2 m- ?* Y3 x( ^/ l! r3 S
- echo 'zhai14';
7 ]! v# _4 w$ D* T( q; }4 i - namespace zhai;% f1 j, ?% l! Y/ {$ I
- require './1.php';
复制代码
+ x$ b4 G# g5 o$ }8 I) Y; Uphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
9 \9 K7 [8 j! j) k' G2 B' Nuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。' c7 d3 k/ v& f, f; w
- //name.php
2 @4 g/ \7 {1 w' ^5 o, S k8 P3 G# _
: h6 W; t+ S% o# U/ L- namespace animal\dog;
) I; y& y- [: \# Z: y - v# t2 t6 A* K" B, c
- class Life{) d2 v: `8 c' N
- function __construct(){* y- j, K) b) \. |
- echo 'dog life!';9 H) S! P/ |5 j. v6 `0 A
- }+ V1 n& Q' D( r9 [- m
- }+ U: F K1 f( U* F" M
- 9 W! U) r' e5 |1 @, f z
- namespace animal\cat;) q) |8 Q0 B2 z8 L" r4 U1 g9 [0 v
- ! K4 y. k2 M% F& b* v
- class Life{3 y! c( X& q5 g! j4 w& w. R0 L
- function __construct(){( [' f! F4 t' D" N6 z1 J
- echo 'cat life!';- u; J8 i+ m8 u6 E8 P9 |1 @
- }
$ A( U, h0 F" X) n - }
% |6 N3 O2 h- u. e8 {' \4 P
- j" r9 B; h) @0 m/ S! A- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
* S! ]$ [0 t0 F. Q - new \animal\dog\Life(); //A) l9 }5 Z4 ]) a$ r% b
- / T; x9 B4 [" @* @$ a9 G; Q
- use animal\dog; //a+ v5 x: t: W2 Y% {* a; ]- B
- new dog\Life(); //B/ w4 G6 i1 Y$ z0 g+ U5 F0 \' N
: P* d! i8 C- R- use animal\dog as d; //b, D! R1 ]9 @) ?0 `( z
- new d\Life();
复制代码 8 M$ Z6 Z% l/ b2 K3 M, L
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 / \+ k1 {+ w, E
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
5 g5 }1 k3 ?& s3 I% S ~. I相当于
/ `- k9 I8 s, s; ^% H2 z7 E2.namespace后面不建议加类名,但use后可以。& x6 @4 A6 N8 `$ ~/ i" d4 j4 y' w
- //name.php
8 h+ F$ N3 W L( |
/ _8 X- p X) ~ y. x. k- namespace animal\dog;
8 x3 A* ?+ @6 \0 |
4 x4 m5 ~3 B; ]6 z; `# ^- class Life{
- e4 R2 F. F& {7 C' W2 y - function __construct(){
; V) T- C& m" p7 {" q( G9 h8 ` - echo 'dog life!';
- H! N* ]" N6 f2 k; E* ^$ y - }
# J9 N( n6 i+ v0 I" m8 @" N - }
2 O! k; k( T5 B, x: X9 W
4 M$ U3 G7 d6 A6 N# `' m a- z- namespace animal\cat;
& L) F. e0 t) ^6 z4 A
r! b2 r0 j2 o- class Life{
Q; f# h' C! D& ~ - function __construct(){
; k4 z4 V9 `+ ]- G# Y1 g9 A& b - echo 'cat life!';
# U, J5 T1 y) V D* B# |. a* O - }
- X1 _: l! j1 I3 X - }9 `% D' ~4 |% i7 X+ [5 Q
- " t2 N. q) W6 `% ~% e# a! m
- use animal\dog\Life as dog; # a5 G H2 J' d3 N
- new dog();
复制代码 ' q! X8 u& e' d# @+ O
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
9 v ^) B; b* a# X因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php$ E L0 g/ h+ ?: L" a1 n4 [" p
0 x: ]9 F+ U1 o5 R- namespace animal\dog;; u4 ?; \6 T3 T+ w
0 x+ M1 \" g) l' U5 N- class Life{: c/ \" U3 c! n
- function __construct(){) g5 a4 x! ^2 o
- echo 'dog life!';
# ] S+ K$ i- [% f& N! i - }
: P' d1 X1 P. H - }
. z" b- A) ]3 T, T+ G# X9 t - class Dog{
$ X7 N0 O. j% U3 j- I. a, V6 t - function __construct(){
% Y4 |% p& Q' ~6 g - echo 'dog in dog!'; Y$ n ?8 N4 I+ Q. J
- }$ q4 |0 L9 e% I' E7 H# c+ g3 d
- }
/ L8 m0 {, x: i8 g! _9 Y- X( z
3 [/ B+ E, M5 F1 N( O3 g" h" ?7 ]0 F- namespace animal\cat;+ c* R: i* M. q
+ U/ o8 p8 t( J' a! K$ N- // class Dog{
, F& A* |; K( o - // function __construct(){
5 l( P& w4 H" `) z; x* D+ _ - // echo 'dog in cat!'; J# m9 r+ {' z! _' ^0 P
- // }
3 x8 w% x5 {3 n* w1 [2 R, D - // }: @, x, Q/ N, X
- class Life{
5 k/ z3 ?( v$ @" |8 q) F8 `% y - function __construct(){- v0 q8 x. G: C Z7 @, E% l# c
- echo 'cat life!';8 e, s$ |: q6 `+ S! i; ]
- }7 v" E& W* Q, v# u5 }6 D. q$ t
- }
$ ]* V+ O A; N# x. q+ ^
/ p" W3 r1 ? Q; d- use animal\dog;
9 G% t- X/ N! O7 h - new dog\Dog();
复制代码 d; t% H( d. T3 R1 a% c$ I6 D6 c7 o
如上,使用了 8 s8 B4 Y3 O8 B( q- H
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
& q$ |% |+ G j( P: x简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
% S# S7 f! d- S# x2 b" ]$ A( l4 S
+ S2 {: n+ n; a! y" J9 K( o/ E3 A! g" h6 k/ C" U
& b$ d) I1 ]9 i6 q
; z a7 I* d0 s; e) ^ |