|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
! ?! {+ a& x X' [! t) G) |- S, s0 a文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
M. j) s- @3 B4 O# U
' R; j( H. k- b使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; + R( w* U/ \1 }5 h4 V3 f
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
* B, {; S' {2 d* D7 }$ `! q- b2 A结合使用方法来进一步理解它的使用目的吧。 ' l+ ?4 r2 |" k# p/ S
. i* W: `; T8 B( a9 h8 ~4 o! bnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
- u8 f- Z3 k8 A; \4 t0 P - namespace One;
3 x- @% T& H3 P( s# N" ` - namespace ONE;
复制代码
6 {8 u5 ~% I1 v' J, g* I如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
8 V# @& S( a: z9 j2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
8 y8 R& U2 E1 c% H# y- Z; D3 ]. ` - class Person{& L' _4 b% n5 p. P; g
- function __construct(){3 s/ F: O- S, E2 f5 Y" \
- echo 'I am one!';+ [0 e3 z' ]2 z0 d" B; y$ f5 r
- }; A1 t- n* L5 m9 i# W
- }
复制代码- //name.php
& z0 K8 q7 I/ U7 q4 [) N+ ? - require_once './1.php';" c$ I' J* r. t0 _! p o
. ?+ i7 T7 ~- ~1 m# M- new Person(); //输出 I am one!;
$ S* Z& W/ N1 C2 I - new \Person(); //输出 I am one!;
复制代码
. ^2 Q( |/ o: O% [) s2 P' r8 L3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php8 U4 r/ j* ?( s# {& `) L9 Z' G
- require_once './1.php';$ S( H2 r6 _$ n) X; D1 g
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
) J# `) p; k4 z# j8 i4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 9 Q, c) U% b7 s) S Y% W8 O0 V
- namespace one;4 l7 v) ^ f2 P% Y @* Y
- class Person{
! ?3 n( _, k. [1 ^4 I9 W: O - function __construct(){; }% [) y: Z c' o. W4 {, c2 d
- echo 'I am one!';% g- l' l8 d5 K+ T t
- }8 } s+ m9 Z' n- k( s9 l
- }
复制代码- //name.php7 j9 j8 x" ^3 T, B& _( Y U
- require_once './1.php';
8 p- a& T8 j3 U7 X' b - new \one\Person(); //输出 I am one!;
* b7 F7 w( `* F4 _2 Y/ N - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
0 k/ N% E9 @$ ~可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
9 D( B4 H4 a: n k5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
5 X6 c2 B5 h' q; y- //1.php ( Y! i% ~. b+ Z! R# k
- namespace one;
% z$ z, [5 G- o7 H' v, X5 d/ s, C - class Person{, V9 A1 O$ w! N. l' w6 O/ g6 |! T1 c
- function __construct(){
" L, i3 h: H% R" `. F8 l+ D/ g - echo 'I am one!';
& x# f/ a5 ^4 c% I# L' v( q: s" \( V - }
% x# u5 c) j6 r+ Y' Z - }
复制代码- //name.php; X" P E; d/ m, V
- namespace test;
- w5 a1 }: x' j/ p4 Y( q5 G - require './1.php';
+ g# M+ T4 B" C, e: _3 u - new \one\Person(); //输出 I am one!;
( B% L' V4 o% W. j1 N - new Person(); //这里结果会是什么呢,猜猜看9 ?0 ]! X! m! q- _
- 最后一行结果报错:( z k6 i% |7 E- u3 R
- Fatal error: Class 'test\Person' not found
复制代码 1 e0 @/ Y0 w+ m5 g! e8 R) X; u
4 [( O8 U4 ], `" J; }6 C- U- s% |% K
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 F: A* `, L& o, ]; X( ]
结果报错: - Fatal error: Class 'Person' not found
复制代码
6 F" X: q8 @5 W1 W e x( }; }接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php( |$ Y3 C( D6 k
- namespace test;
+ {1 r# ^ f7 @! f6 | - require './1.php'; 4 b: n S: T. z y5 ^+ ]
- & x! |( [8 m4 o4 l' Q8 K% x
- class Person{
# ~& f' W$ a0 L% g - function __construct(){
( `* D* H4 C" W2 f" E' D" O - echo 'I am test!';
1 s4 }$ ]: L5 c# C1 Q - }% n; B% ]+ n! q
- }
) h/ n: s- O) W. Y
1 h5 |3 a! C+ v' q0 C- new \one\Person(); //输出 I am one!;
p( \/ `9 e* p* ^) v% z - new Person(); //这里结果会是什么,自己猜猜看
复制代码
1 Q+ `1 y+ F+ b# U( j& w最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
/ s. F3 q+ A; S; G3 \/ W7 p2 Z - namespace test;7 ?6 V- T0 s5 I7 B9 a5 j5 G! P0 x
- namespace one;
7 I: f4 f& a% B- Q% H4 j - class Person{
% i, w. k2 ]# T- R, c% q6 F4 w - function __construct(){. A, p& t. M K& H+ u A6 a
- echo 'I am one!';8 M0 }& ]9 t6 w; |! d/ M' O
- }* v/ T2 E: i7 m9 i
- }8 q- v# i7 ~ k, j3 t. T& g# q
0 _( d8 ^# W2 o& k& f7 z7 s3 ]- q: W- class Person{5 Z0 x) o8 {: A2 z9 K* o+ O9 h- v: o
- function __construct(){
! u5 u3 X5 p, j+ a& @6 e8 X - echo 'I am test!';* {3 Z8 N' j$ E q M' f! z" f
- }: Z' p% G0 H& O, l+ S1 J3 `3 M
- }
复制代码
/ ]; [- K8 R0 R4 _ B! v& F无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
7 e4 H" K8 ?4 P) @看来简单的把require理解为替换,在这里行不通。
2 d( S9 N# ^: u6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。+ Z `0 G6 z2 I5 ^$ u, i
- //name.php- {# T, n* J! r3 {+ f9 ~7 }& N% |5 e
- + f7 ?# e; }( B1 M1 D
- namespace test\person;# Q: `9 L. t+ P. O _
- 2 b3 s3 L2 ^; _4 c9 N: Y' a
- class Person{2 `3 U* a+ f& b# ? m" \
- function __construct(){
7 r5 M8 L9 `5 F3 O7 D - echo 'I am test!';% D1 G, ^ G! K. w
- }+ s* l) p/ W3 E6 l& g% f. Y
- }
/ R# M" g1 `5 G) D* ~. q/ [ - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
; H& m8 ~2 f4 i1 ~4 w不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 - Z$ V- G) O, E5 N( g8 l& J+ K& v5 j
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
7 I& c/ p! l% }& Q
* M7 P- Z% D) Z; O1 L- namespace test;
4 M# o5 _7 r, Y( f8 i - echo 'zhai14';
5 K3 F- K$ t) I+ ^1 z4 R - namespace zhai;
3 ]% B0 |. p% e - require './1.php';
复制代码 * P# F4 W' T% T4 v9 d
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
v! V$ ]% ~1 E% j8 ?; Duse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
! A! R0 P- S \9 t, N2 i2 t- //name.php1 H8 t; @0 [( d. [! t
- + B" q! R: E7 M5 D) [$ W
- namespace animal\dog;
# B- l C8 A- T$ A8 q6 r2 {7 d - ! N/ _3 |5 z: D `
- class Life{# Y- {, i: `* F% m7 Y3 c1 ]
- function __construct(){
2 h* g7 W! f* e# _2 [ - echo 'dog life!';
0 M1 T |) ^( w" h2 e0 w- E - }0 b, o) L3 z$ X% v# \
- }: O1 u1 C! {+ P% I9 \. q
: z6 ?$ k' u+ ?) I% @' j. _- namespace animal\cat;3 `4 O. O& M2 h1 O! v
- # p6 b/ P; c! R) l: ?" O
- class Life{
: A+ W: z! V6 r5 t* Q1 ^# ]" G - function __construct(){6 p# d% }3 |$ i' {
- echo 'cat life!';
4 @# h% U% ~; E7 g9 E - }/ ^1 n6 e" |8 g& p% w3 m
- }
& g' {9 A1 V# | - " i& R& b& P2 [5 \3 p- z
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
; }2 @, L* n. Y; `9 u7 n+ U - new \animal\dog\Life(); //A
6 D! R4 M; L9 q4 }: I+ z - Z U5 H" Y' z% C- b* ]
- use animal\dog; //a
4 w/ |9 E' V+ r% Z1 B. p7 x - new dog\Life(); //B
/ Q- T5 q& F/ D n6 [
+ q+ `0 D6 v* e0 p- D, e- use animal\dog as d; //b
, f9 y& Z8 | G/ h' t9 S/ n( Y - new d\Life();
复制代码
+ a/ m! l I6 `/ z- O. s通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
' u+ ?0 m/ v$ m" _通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: % _! S9 |; B2 R5 |4 S: C- B
相当于 * K+ X; U, j/ s/ R7 y
2.namespace后面不建议加类名,但use后可以。
& L6 u: y4 }2 R4 E: P4 R- //name.php
3 b! F" [: Q# j) L( Z% \/ M$ B0 u
; d3 o) l: R, T6 ~) ]: F6 u1 K$ l- namespace animal\dog;/ j4 ^# P! W9 n8 f" c2 e
, N C3 r' J8 I* u, b. o: f- class Life{4 t8 ~; L" S( Y" T* d
- function __construct(){& q3 ^; H4 V6 Q: J
- echo 'dog life!';# y# v6 b7 r5 S5 @5 L7 m V3 A
- }
$ G/ ]" ?0 z6 z% q( Q+ c. z0 @ - }
# }# @; o8 ]: t- H. Q9 c0 n u - % a3 @' H# q, x$ {( Z3 X
- namespace animal\cat;* g; {" l$ _2 ] L3 H$ Z
9 ?* G& H, u2 F! h- class Life{5 A; S0 p: {. a: v: x5 C
- function __construct(){
P' }) I; C+ K o# ?0 I; p! m& ] - echo 'cat life!';3 f/ W, y( n3 [3 e( I5 g
- }6 f2 R! C# K, H" y
- }/ z% [3 v" d( M3 O8 l
- ' I& Y# s. Q6 R
- use animal\dog\Life as dog;
9 `2 q5 }6 ?; V" p1 o - new dog();
复制代码
6 z# M, c+ [6 m, P( q, N( \# `: W如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
0 L/ B5 z9 ~! r: S因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
1 b5 R9 b) r8 P$ U7 Q% v/ U - 5 |" ], i; J- Q/ t
- namespace animal\dog;
5 B6 L. Q2 e1 R- z6 o: T
5 f t, r# Q7 u, P0 o- class Life{) z" G" ^/ @, U# O% n1 \
- function __construct(){
$ g( r# s' L8 a9 n7 f+ Y7 w$ J1 o& D - echo 'dog life!';
: L3 T3 g6 u2 A0 c3 b+ |+ ^! U+ ~# w - }6 ^7 @, e3 m( X2 v. z
- }
- }9 W) S6 X7 O7 K* f - class Dog{
- R2 |4 C6 b, S; A, E+ y$ w+ I1 J - function __construct(){
9 r. B2 S( O# K' K7 K - echo 'dog in dog!';6 l! t6 {8 {( Q C! W3 B0 O* X
- }9 f5 w8 g0 Z" q
- }. [1 s/ _, E5 f: K- a+ v
- " F% {4 U/ K* v
- namespace animal\cat;$ {; C0 U1 Q, _" M& P
- y. z2 F$ ^3 L& l7 ]" q
- // class Dog{% r Z; [. t0 Z/ d3 n
- // function __construct(){
1 r4 G! J5 p& N* [2 Z5 Z* v - // echo 'dog in cat!';
# e' b$ C* a% b9 S& P$ x - // }8 \! f: l" e! c1 j C; w+ ?: q) D
- // }- \/ z/ S+ w1 n' L. G
- class Life{5 e$ v5 s/ Q, [9 \% C; U9 e# v
- function __construct(){
2 |- b# p6 y9 T; j4 C0 S2 b- L: c - echo 'cat life!';; G8 M6 g, b; @1 ?9 R9 S% C
- }
, c, F/ R: C; P& A' s7 d0 Y; d - }
6 j1 \; Y' Q% r y' I- j `+ ? - 1 X( T- G& C/ s. M N
- use animal\dog; % h' I; Y1 E- i0 r% _
- new dog\Dog();
复制代码
/ D% k: s& o% L0 s如上,使用了 / k! d# E0 D4 n/ R% }& [
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
, `) ^2 \. g9 g. g' ^* V简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
# e& s, N' Y$ I X& d% d! x! [* h1 Z) C! {) z5 \
/ V2 R% ]/ C2 L `+ `; L7 d S8 ~ h& ^; c! v
- ?5 f4 A7 y/ }, B# U0 A |