|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 6 G- B# k) @3 a* ]# w' S, Y
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
& Q0 h7 ` U6 M" }' J: H5 J
: V% j P2 d0 C2 k使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
+ q* g s1 K$ @4 Q0 a据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 3 Y5 {& G: J2 S7 G2 H
结合使用方法来进一步理解它的使用目的吧。 + s% n! Y6 n2 Y% R" m
& t/ h! p4 @; a; C5 i5 z1 k: rnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;* Q6 t% y& u- e; J
- namespace One;2 b" J5 l( j! N, u) K/ W
- namespace ONE;
复制代码 1 v( d$ ]- {6 k/ ^( r$ E0 w, Z; }0 W1 z6 s
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) + x" _. y/ J* M
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php - [$ Q! P" L* w5 e0 I- X
- class Person{
1 t+ @: q- ]* l, C4 U3 u - function __construct(){5 A. [# j7 L" E. m0 T
- echo 'I am one!';
' R# G0 w1 T* b) E. H - }
3 O4 v! d1 d4 C/ J- l- k - }
复制代码- //name.php3 {" R% O' t, ]
- require_once './1.php';
1 s+ X, x! K9 [
o+ ]7 @, b: W7 h$ Q! l- new Person(); //输出 I am one!;- u8 j( x7 v) l/ k
- new \Person(); //输出 I am one!;
复制代码
2 a+ L X8 @+ C9 p% O0 z3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php4 Y& M: G# ~9 X
- require_once './1.php';- h: e2 X% U8 a! y
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
8 T2 D% |8 p/ H: q% f& B) R0 ?4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
* u8 @1 |6 I, t* w - namespace one;
7 ^ c( ~, B9 M4 P6 a* w. p6 G - class Person{! }. `! S5 F4 L$ `' X. ?* g) H
- function __construct(){
0 g; l9 |) i& K. G/ W( D - echo 'I am one!';
7 |: b6 e, {% |$ v - }
+ ^7 ^9 Z' E" ]4 @ - }
复制代码- //name.php5 G. p& t% g- b3 {9 _% Q8 V( q" q
- require_once './1.php';
$ w# ?3 j& }& y: P# p4 P( y y7 X - new \one\Person(); //输出 I am one!;
" \; I" R, ~2 \: W! a0 M$ } - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
1 N t1 U" Z0 V/ ]% W* w可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
) [. s, r. h" \4 \/ ]5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。. ^- `0 C. Z8 d1 k% U! o
- //1.php ' e. I3 o, [4 `6 P
- namespace one;! Q8 v& x& b' m8 @. m4 W
- class Person{# P! _# e' _ y/ y: v* Q& b
- function __construct(){
/ l1 W5 ^7 U( y, T0 t+ ?3 A; t9 K - echo 'I am one!';: w6 @' U( i% E; |6 ~1 h. f
- }3 z. j$ D- M! t$ I
- }
复制代码- //name.php' t4 {$ s1 ?! k s; m( W
- namespace test;
8 W2 P' _) c3 @& @) w - require './1.php'; 0 A: b& N) C O% {4 m- P* k' N* O
- new \one\Person(); //输出 I am one!;
- f+ n- q) g) v2 F: \/ u - new Person(); //这里结果会是什么呢,猜猜看5 b# S9 l- G ~7 g' p3 u" s
- 最后一行结果报错:1 F6 m4 E0 ?5 ^ e* p6 N3 V
- Fatal error: Class 'test\Person' not found
复制代码
) F) H% h! Q) ^, {/ \4 v
* h4 m# P* m$ m& b首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 ! V' P3 ]! x |8 G w1 z
结果报错: - Fatal error: Class 'Person' not found
复制代码 0 R& U$ S3 N& s5 a( P3 A ]1 q
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php8 r! @4 a0 z# a. [; |
- namespace test;+ c: V9 P; B3 t' N$ N/ @
- require './1.php'; 8 h7 H! A: S$ D4 m
# l8 s$ |, [3 A! N n2 q- class Person{
0 B1 I+ f, Z ~$ @* c. p - function __construct(){
$ g# W$ x" ^- _5 D- B) |# c - echo 'I am test!';
" N1 v+ v0 `1 y# j - }* u( k1 V6 s$ w. O
- }
' y/ p0 @% y) Z2 g5 X' ]3 k. M+ \2 t( ?
. F7 r Z9 ]3 C- new \one\Person(); //输出 I am one!;. j. v# f4 b+ y$ a
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
# A" D8 l7 C2 u最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php2 Y* \: B- E3 @$ \
- namespace test;
) n8 o/ y# z5 `; w, [ - namespace one;
1 Z+ @& j) p) y, v - class Person{' T% z& e2 f: M1 f4 y7 V* s
- function __construct(){
3 W5 f! V; {. R# G - echo 'I am one!';
% f0 P- E0 E- \- O* o' F) D, s - }
% g6 h* ]7 F% x$ b v3 P' a - }
' I* j. G* j7 G5 {; `. @% e - % O4 D! \+ m% V/ O
- class Person{3 `3 Q# }" A$ \ }2 u; D
- function __construct(){ u6 A$ J) N6 `3 c, E. W2 \
- echo 'I am test!';& p6 P6 A' I9 ^( g6 x- u
- }
. B# \( a- z# B2 l* g - }
复制代码 8 x' Q2 X0 h7 }% N* |
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 # O' p4 W) p4 b2 `: Y' h
看来简单的把require理解为替换,在这里行不通。 ) q1 C' U' f9 j2 Y- B, g
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
2 {, L& k# {- `$ A- //name.php
; @3 u4 p! |% j( U* m, s - + {. g, N, F" f6 U' ]8 K ?2 [
- namespace test\person;
& w0 M7 M( g* [9 U8 n - 0 v/ H1 U* S3 W0 B
- class Person{
, }4 q7 s: d* k - function __construct(){6 q. }$ N) x0 M9 Y4 s6 C# _/ K/ S
- echo 'I am test!';
6 \, R3 l, C2 d* S+ F6 X- d+ {! s4 R2 Z - }5 [3 X; \& F. [" b7 a3 ^9 R# S
- }' X/ n6 S: U* `1 _, d! R2 i" i
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 ! F: T+ I' p0 J1 |& ?
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 6 a$ j) T d" }) p/ d
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
* k" y/ s+ b6 R- p# R4 O# M, O m- d/ t3 _ - ' q% A0 M" S/ a: D! I7 l+ K+ }3 n! j
- namespace test;
i# f# z+ Q! L - echo 'zhai14';2 w; |3 z/ S. N5 I9 O2 R& Y: G
- namespace zhai;( f. V* [" y- C) ^$ V o
- require './1.php';
复制代码 , P5 y$ c2 X- S6 d2 a( f& I1 N
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
9 C$ g" U' r& q6 F8 n' k1 @& W% V$ cuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。+ y' {% h0 l4 X
- //name.php
+ _" ~# w0 Y+ U: b5 [* u' l$ _
0 c3 K3 G _$ W' ?- namespace animal\dog;+ B3 y4 e% u% q1 @
+ ?/ F. a) }# ` V6 I- class Life{
4 D- I# [5 V# T# L$ y5 n - function __construct(){
' f" R3 B( u* ^. Q - echo 'dog life!';) C% }5 {) B: c& g- t% A
- }/ V5 v) X) W n# w9 I2 D) S2 y
- }
# v2 v0 \( }2 ]8 C3 q0 ?
" ]2 N! {* [* l& n' w6 w- namespace animal\cat;
" J3 P% w- k. T! B/ ^
) ^4 F0 ?6 R- A8 ]6 o6 O* @& H; u- class Life{# x' p+ ?( T$ m h$ U$ ]6 B$ R
- function __construct(){; \; ~8 D! K& \$ K) o
- echo 'cat life!';' R- E, X2 N, w. J9 u
- }
* G2 d, c& X: J. q. N x - }
. V: R1 g( w, w) E; s8 V
% u5 N+ v: h5 V; f, C- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间/ N3 d9 H0 U, y! t* h. z. H. \
- new \animal\dog\Life(); //A8 F; @, p, _' Z# q! s
- . c- C* A( P' b n
- use animal\dog; //a
8 f) a" @2 k4 M j. q - new dog\Life(); //B
+ f, o/ F% o& }$ V8 G) W& O - ! Y* [! a* H- N( X) v! n
- use animal\dog as d; //b7 w( H2 ^8 v1 m3 k* Y. R# Y
- new d\Life();
复制代码
) b; k3 R8 j7 x( }通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
1 T$ |) x5 j6 p2 @+ [6 J通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
+ C( w$ o2 X. X" v* I相当于
: C1 r5 |5 g1 S* U2.namespace后面不建议加类名,但use后可以。
' C+ G/ D6 u/ W- //name.php+ o- z3 ^' T3 ]# s# e
3 ~ p/ u# P. _0 j5 [- namespace animal\dog;
) I2 x# D2 P8 w0 y
4 M* W% c4 S- f- class Life{
4 B2 L5 B1 V" V4 H - function __construct(){
" f5 d# M1 |' |4 Y) x* @7 d - echo 'dog life!';( e! x; s4 n/ g' P' B6 [
- }
$ [: o. x3 R2 ^: F3 v7 e - }0 p l5 x* S- p! j
# s v" ^( a- [: N- namespace animal\cat;+ u5 w* j' S* L4 v
- 9 R: ~6 K+ G; T' p7 b: B. U! f
- class Life{
8 c( [( y7 ?+ T3 E) e( E! W - function __construct(){ ]+ `: K5 c) @1 D7 B/ [
- echo 'cat life!';# J, l8 y: G$ d B# ~+ c6 s
- }0 T" I1 }: R! G9 x4 j' B% _) Y. T
- }
2 K' `: k7 r% x3 { - 0 h. g+ a" ^3 |% x& W1 c2 F; z& ]% R, X
- use animal\dog\Life as dog; , }1 D& s/ \6 U* ]: A/ X1 N- I$ |
- new dog();
复制代码 % W. \+ m; U* f5 W, l1 @- m7 b' W
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 1 O0 |( N: o+ c9 i8 c
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
% H. i3 F0 K2 F% y' V/ b. N - - j D* _1 C2 Y
- namespace animal\dog;
8 P5 y' [% |+ ?% k- g - 7 P0 \9 F! n: V" p z: E7 ?/ W
- class Life{+ E, O& K1 `2 U* G( T/ F9 D# b: l+ A
- function __construct(){2 s& M' U- U7 u8 A/ Q$ f( n
- echo 'dog life!';6 x, T0 N: W. k, d6 A! _2 G! n, K
- }6 j. T! H& ?4 k G- M( h& {# _7 ?
- }
* ?3 s/ v) x& X9 b/ L# P N+ S - class Dog{
5 z k3 o8 i) f$ x8 ~3 I+ c - function __construct(){9 b% ]8 p5 t% R, ]: s: D
- echo 'dog in dog!';, w o) E( d4 r4 B
- }
7 c( u( c/ A; O$ m - }! b) x7 r' x6 j2 h- l% Y
- ( v& e9 `6 T) k$ h; K( r
- namespace animal\cat;7 K9 m, u& ]4 ]1 D1 b
7 n" x3 ] l' f, t, m- // class Dog{3 w: i S( ]* U6 x' m- V8 [
- // function __construct(){. G; I: R; L* }1 c
- // echo 'dog in cat!';
0 x H, X$ s: | - // }
8 n0 Q$ f& q- c - // }8 ^7 R( Y& N2 ?& M
- class Life{& e9 _( z2 F" @" b; J
- function __construct(){
9 l2 s: E' @& {5 Q5 _* \$ R& |" z3 s - echo 'cat life!';$ \% b( _6 }+ @' q: X; ~8 ]$ d4 a E
- }2 X+ o: l. c, N
- }3 G+ Z7 h) E8 z; h: \6 X' M" K
- / B$ l& ~7 r+ n o2 @, _4 `
- use animal\dog;
1 r3 O0 f, W6 y T- g+ Y" G9 R - new dog\Dog();
复制代码
" M) T/ c7 s2 |8 X7 K" P如上,使用了 & U+ l4 l4 J7 B- I2 c
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
) v9 ]& @! O& L1 l% t/ X简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
! A/ z4 x6 W# T& \) T. z4 X+ l
2 o4 R' p) {2 ]1 _8 W8 O* }7 [' H" u) M& S* ^
|. u9 g/ B: ^8 }. b2 K7 v" V3 R7 s7 w. F: {! }8 @
|