以下皆为本人自我理解内容,如有失误之处,请多多包涵。
3 f' p+ d5 u9 ^* [- ~文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 " Z9 I8 c: A: T, D& Y. y, _7 r
" T0 H+ |$ I4 n, |1 g* I& b
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 9 g, u+ E' W: m! n. u! K0 j
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
' d) A! W$ q; \, i. ]0 y结合使用方法来进一步理解它的使用目的吧。 - f, r2 E/ V' r3 |* `+ x
5 q7 t' p3 V% P0 z1 `; z% {, g
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;6 U3 Q! b; N0 ]" c: p" w0 g
- namespace One;" C. g5 G, s+ P' C
- namespace ONE;
复制代码 & N, D. h5 d' O5 T. K9 W4 `
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 8 Q7 x8 c8 {9 B( M
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
+ c3 ^4 l8 a! f4 t2 z) p - class Person{
: N5 `! g8 `# y3 e2 ?2 v! U6 F9 r4 D9 u+ r - function __construct(){6 ~( k$ S% M* s I5 m+ {
- echo 'I am one!';- p( ?- k) t+ e7 f" m
- }& U8 ~, m g* v
- }
复制代码- //name.php$ N! Q' ^! k: ?4 `: R0 m! d
- require_once './1.php';
" W. w) M5 ?3 V5 V- @- |/ Q - " Z$ s/ x& e8 e) L! u" y$ a: {* {
- new Person(); //输出 I am one!;2 k& H- D, v+ O* G
- new \Person(); //输出 I am one!;
复制代码 ' }5 A [* T& O9 L. i8 X1 Q
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
; h8 C @* E$ @6 l- J - require_once './1.php';& f# X* U- e1 d4 s$ a
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 " ^, ~8 H9 M- r9 r3 s' I# _. S; x/ K
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
& g7 x- `# x2 f - namespace one;$ i) l3 N. R8 _
- class Person{0 ^( b3 q/ e6 L B; i
- function __construct(){
) n$ N" i; Z3 o- k, @7 ] - echo 'I am one!';
" y2 p8 O! s: \, z0 z. X - }6 X3 f0 {" E- D1 g; J3 `8 `
- }
复制代码- //name.php
8 A+ }! r6 S) V2 F& k/ s - require_once './1.php';
# q' ]; p8 @9 @0 j* i5 v/ A - new \one\Person(); //输出 I am one!;7 x" O- `' W4 v, I. W0 e
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 % L# E4 B% S( C9 E+ A/ P0 Y5 t
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
" f) J( V( P/ s6 |) P5 K5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
0 k, I" F, x; X* M" H- //1.php $ N" Y- I2 `& u% z$ v& ^
- namespace one;( b: B, J/ R4 B+ |
- class Person{. J# L1 f+ J* X: @
- function __construct(){/ v: J. i9 u# |* w$ v
- echo 'I am one!';4 k( ^8 s5 y3 {
- }; Q; N2 f0 Y; r, c, `
- }
复制代码- //name.php
. }' R8 i- o; A$ X$ L$ y - namespace test;
: B2 S! i/ l1 @. j - require './1.php';
6 P+ `' \5 g8 r& F$ ^ - new \one\Person(); //输出 I am one!;
9 R9 _: R' o @+ Z/ |, `* W# F% h: D - new Person(); //这里结果会是什么呢,猜猜看- g5 A) P, s) i: Z
- 最后一行结果报错:
/ \; {/ `! F9 ?% a1 H' A( C - Fatal error: Class 'test\Person' not found
复制代码
4 ~9 L' w5 q3 w# R R) f9 F
+ ^2 M, y; C6 h+ E3 p首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 " S6 e1 b/ K8 a8 E( u: c! M
结果报错: - Fatal error: Class 'Person' not found
复制代码
% g# [) ~4 ]- ^0 J接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
. x% I ?( |" E' F - namespace test;2 x4 E" l u7 t$ o& T: p
- require './1.php';
( g$ B& [& n" c& l9 \
# x0 Y8 K2 c& G6 {: s- class Person{' a% f! y% {, F3 ^% O+ }
- function __construct(){' [8 z% |, B2 x7 G( F' \8 ]
- echo 'I am test!';
2 H' n9 L/ n" K7 e, R5 A- ?6 M - }
. K7 j3 ^3 d& J, L - }
" t5 `0 f! F: v - 2 E5 F/ ^/ l/ ~6 f
- new \one\Person(); //输出 I am one!;
$ d/ V8 v/ a, P& |1 ]) h# {# i& N - new Person(); //这里结果会是什么,自己猜猜看
复制代码
) y v. R; w9 ?: G: r9 g; V最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
$ k, E8 h, J" Q5 ], m& c7 r - namespace test;
4 T/ ]0 u5 ^; K7 i) z) I3 V - namespace one;* E9 y0 ^- D; J# }! w5 p
- class Person{
2 [8 v) `0 p9 C6 n9 p$ i- N8 s1 ^ - function __construct(){( f" ], D( b/ a0 l
- echo 'I am one!';
: i/ T# I6 w+ c8 s% T* f - }
& {- p8 l# t {; o9 O; M! a$ [ - }
- w ~- w+ D- `8 n - 4 m. @5 [& T& J7 O% L
- class Person{
( [2 }7 ^$ v+ } O - function __construct(){# ^; K- \+ Q9 L) B3 }
- echo 'I am test!';
! m6 l N/ e, B, u* l4 X" M - }) \3 x2 ]8 p8 B4 B* X6 w" Y
- }
复制代码 6 o% H" c) N3 t2 X1 p% Q
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 " k+ O6 J' }. E2 v0 U# y
看来简单的把require理解为替换,在这里行不通。 ) z/ ~5 R/ }) b2 @% e! p
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
c5 J: b4 l' l: P" S% u- //name.php; f9 E1 c5 @6 d
; u/ A0 ^. g% A- namespace test\person;
2 V: B8 C" @! L6 D4 M: ?8 n5 I - ; `" W+ {+ q/ W( K* R* @4 H
- class Person{: H _0 E+ D0 G/ [6 J" N: j
- function __construct(){
9 e/ l0 ^) Y6 U9 ` - echo 'I am test!';" N4 Z. n# `* w+ e" u) P2 b
- }* |$ \; U9 O8 k( I7 u) ?, U- ^: o
- }
9 `) j& ~* g6 `2 D% A" ? - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
2 [+ k0 R% S0 Z7 R" j7 f不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 + Z6 w# o$ @" w# {/ ]# o! y
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
" p$ Q3 x: |! A9 }* e: `8 d% W* {
9 L3 C3 j. s. R/ H6 c- namespace test;
7 L, A& Y+ d; r - echo 'zhai14';4 D* Z! V! d& m. ^+ y4 k
- namespace zhai;1 t& K- y, p4 e9 l. D, Y
- require './1.php';
复制代码 % B3 r, y; H8 N
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
9 k( e9 F& R$ I; u4 Nuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。$ u& b/ F& K; N( @6 `
- //name.php; ?5 ]! A; ~- ]# ?9 J
- : g% |. M+ K" z6 x
- namespace animal\dog;. S% U+ [' o. u2 E3 H8 A i7 q, N2 @4 d
, {4 S0 V' q& E, q c9 r- class Life{
- h+ ]' k3 f& l0 c7 b5 [ - function __construct(){
V, U) _7 e$ r3 a - echo 'dog life!';
( a4 I$ W& K' C+ D6 F" B - }2 p' [9 Q# H: w+ M
- }
' _' r1 M4 y* [: o" B( v0 o
% r" p+ h$ }$ y% b- namespace animal\cat;
/ l: K" [2 a6 O; l% n, X U# O
0 x# W1 M# |3 k( }9 L* U: i- class Life{
; c' V# T K5 H; K* C8 a2 k - function __construct(){
$ K: y; ~. m+ u& _ - echo 'cat life!';0 N1 E' G5 z- S; Z x" ]( \
- }; }( j8 v6 B. v2 O
- } _. m2 i0 U+ }+ O+ {" d5 X9 U
- 2 O9 l& g" W) l7 P1 v5 S
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
7 H/ ]; `. Z+ \1 W - new \animal\dog\Life(); //A
9 A% p* `; R9 j. d8 e
9 m) ]: k# ~: d1 f; Z- use animal\dog; //a
" u0 W8 K- Q5 g5 A - new dog\Life(); //B
. X. Y2 z3 w9 Z8 [( }, Q, L
1 p, _1 C5 S* {5 h8 O- use animal\dog as d; //b6 `/ w" z+ I8 m: R8 d1 h5 J5 P; C
- new d\Life();
复制代码 - [, y! j8 I5 P' v/ @2 R
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 * {, \0 ^, }, U! u7 n3 J- t' k$ s
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: - o6 }/ h& B% l1 k3 T+ P2 ^3 E
相当于 # M0 ]/ ~6 ~) \& Z* T
2.namespace后面不建议加类名,但use后可以。
. l4 S6 m8 }6 J) _3 y8 J- //name.php" q0 g& U2 \# Z' Z c
4 U- O8 ]4 [( g: \- namespace animal\dog;+ ^6 g4 F. ~3 y: ~- B' u! C
- D+ v! \0 n/ x' X. S8 U- class Life{0 i5 Q3 [- h) j, _& o; @2 M; Y
- function __construct(){
- s3 o& f/ a! K5 C) e% Z" @2 I - echo 'dog life!';
0 c9 l/ K& H% ^8 h7 B! [; D5 l2 } - }
% E2 R- _1 \2 l. i3 l) w - }. {* ]6 }) t- ]) a' i3 f& T9 Y( ?
6 d1 j) H# I# Z& x- namespace animal\cat;
8 h/ q) D5 A+ h$ U3 ~6 R- { - % n( @! e: y) R" A4 W! j
- class Life{
. C Z! T% R9 ` - function __construct(){
5 S' m ?" \$ {& z0 h6 p! ? - echo 'cat life!';
% ?' V9 B5 v- Z% b- A - }
6 l {, E- \* n8 A - }
9 l0 b: A! w+ Y2 h' w/ @
" U% D( T: I7 S- use animal\dog\Life as dog; 1 O6 G: q4 B. j
- new dog();
复制代码
6 n6 F, r1 n& Z2 f1 t( W! v如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
' q$ H' ^5 m) p因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php4 H1 e# N) |- x" l5 \5 C* x
- + a6 n) N5 _1 y+ V$ v2 _: Y' \. i) b
- namespace animal\dog;
, K- I' |2 u# ]; z$ s) Q: I - ( J8 d. n8 B, v9 D. \: |3 A
- class Life{! Z" j' u' J; Q/ V9 O3 ~/ J
- function __construct(){5 E- O& i9 x# }2 v
- echo 'dog life!';4 G' i* V' G' b$ ^0 T% {6 B
- }! Q6 \1 q5 s; t2 ?, G4 o
- }
! Q L- [* E m* ]' i - class Dog{# X( w( u1 u. J1 {1 `3 B, N6 G
- function __construct(){
* r$ B0 u- c% n" {) m4 p8 v - echo 'dog in dog!';% l0 q) n$ w2 h$ B% v
- }
& `6 }; R4 G" W - }9 W G; l8 G, g4 ~
- 3 K/ _3 f. ~* @+ Q/ M4 I+ ^* a" J
- namespace animal\cat;
, w. f8 c$ S; Z& I: F - / S9 p- E- Y( V+ B# Y4 a; ]4 x$ l) m! Q' D
- // class Dog{# t2 H0 C2 d; c5 O/ h4 O) y
- // function __construct(){. ^! B. ?4 o0 n
- // echo 'dog in cat!';" o2 |+ H3 t2 q! Z* q0 N
- // }6 I+ p/ V+ H( G0 R9 j* J: \/ i
- // }
) U( {+ f- O2 m% x2 ~: B1 Y, w - class Life{/ Y7 {0 m, Z) U- U0 h6 n5 a7 x
- function __construct(){
, Z& k; y t; w. h6 d3 ` - echo 'cat life!';; B. I8 [, Z0 g! k* x! d% M' L, n
- }
2 a+ G4 s2 j* S" s! o7 J- b - }
: R( {4 s" |7 ], _& }
; v/ M) P2 ?" { Q1 {- use animal\dog;
$ C9 E! ]2 f6 G3 Q - new dog\Dog();
复制代码 & w. J" g& o( i# E8 |( L) z* L
如上,使用了 - F/ u+ r: [8 t: n: ~0 g! Z9 o
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 3 |1 |* ~& b, b* @) f6 Y) W
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
: ?3 E5 E$ |) V; [( S( l
# U! b/ L' E0 y7 ?
, s8 u6 q6 y3 V7 p7 J) n) z c7 @0 F
+ G" g9 G$ N9 {
|