|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 ' K) e0 m) y2 Q' T
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
+ l: w& ~: M! y! ], G% B! r+ C& u' t$ \% Z6 T
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; + \1 K1 z/ ?& ]( R! g
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
+ f9 r9 y4 [! v; h: B结合使用方法来进一步理解它的使用目的吧。
6 S, ~! A$ ?7 b* ^ P5 O8 C* h9 a$ L" i8 P# U, _
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
9 Z/ P' u$ u' U1 M2 Q - namespace One;
- `, W0 ^% t9 Z! `+ w - namespace ONE;
复制代码 / z) w' P/ |4 E. R; E9 R0 }1 ^: s
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
# |: P0 b. g! \* X' O2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php / t: X: X/ }1 j. O! N& K' V
- class Person{
/ q/ |1 A5 J) j f - function __construct(){# V# {/ L& w2 Q' {' {2 A2 N) S
- echo 'I am one!';
2 P, t- ]( X7 Z: Y( d - }
) b2 b8 [$ s! Z" @0 I8 L - }
复制代码- //name.php
0 Y, |2 B4 T# { - require_once './1.php';+ \/ m1 |" m8 E( M l3 {! w( i4 b
- & [5 J+ @0 p0 a* x9 o
- new Person(); //输出 I am one!;. M, `. B7 Q( g1 n" H) {
- new \Person(); //输出 I am one!;
复制代码 * p- g' v3 t3 [( i0 }( |
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php E4 v) b J4 e8 u+ M
- require_once './1.php';
1 S; Q, [9 ^9 {" o! r+ [ - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 : A- l8 F* c5 V D/ W, t
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php & a4 L* A# _6 s+ Y! }1 }
- namespace one;- a q6 [" }% b' ~& ^
- class Person{, z; v: G2 @$ o
- function __construct(){; ^, X) x3 r5 e: t4 r7 O" Z# }
- echo 'I am one!';
`* N0 _0 F/ l9 n - }2 M4 w" _% I6 ~4 W
- }
复制代码- //name.php" {# w6 e; o- G8 J+ w! J4 {
- require_once './1.php';; z G3 Z5 |/ w+ a3 Z
- new \one\Person(); //输出 I am one!;8 {3 G; ^+ O! h1 [
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
5 u1 t7 }/ j/ ]$ ?可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 0 q& h' f2 N5 n1 I, d$ g5 _
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
' {- b% A* u( }4 C1 J3 c! t- //1.php
+ ?) d( G4 I; G" } - namespace one;" I( M) U2 ?6 E
- class Person{ {8 U, ]+ H2 v0 I+ y/ j% M' z
- function __construct(){
) U9 u; F* S# Z7 I! [9 Q2 v, [* D' _ - echo 'I am one!';
; b- w: R; d8 `' l - }
6 ~; S2 _& K$ c: K) Q6 T- ]- a - }
复制代码- //name.php. u5 Y4 G" k; c4 O4 g9 n5 g" H
- namespace test;
2 W' I1 @) D6 K) U, q" {! ` - require './1.php';
, d& O4 g) j: ]& L - new \one\Person(); //输出 I am one!;
& X7 m8 S' r' \2 l% C& [% W - new Person(); //这里结果会是什么呢,猜猜看
6 _7 A/ i! c0 e" C, Z4 Y# G - 最后一行结果报错:( Y* O% [4 u# q$ ^3 [5 e2 e) J
- Fatal error: Class 'test\Person' not found
复制代码
0 i2 H4 k3 a1 F. Z( M$ P+ S
, s+ O5 W2 h# [首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 5 g& f. A) n% ], Q
结果报错: - Fatal error: Class 'Person' not found
复制代码 1 N# F4 a& j$ l" U
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
/ f1 _; \9 q" h" O( Z - namespace test;$ i& A, w2 i8 T! g9 V
- require './1.php'; ' f9 Z$ Q3 B9 w
8 I9 w7 Q3 U$ f( m- P5 \ Q. F, {- class Person{
. m" H* Z4 D5 k* i - function __construct(){. r7 t! W6 \9 _3 I" [# g
- echo 'I am test!';* ? b- i4 B* g) o. B8 {
- }) v, Y/ @" ]# Y: [' t& Y; N3 \
- }7 L3 i" y% z( _3 o* i
- 4 v( }2 E. V+ g5 E3 p" L4 _
- new \one\Person(); //输出 I am one!;
8 T3 g9 c& H! \0 \3 ^" [ - new Person(); //这里结果会是什么,自己猜猜看
复制代码 ' F; a# E/ S7 f4 w& o3 x* e& R5 B
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
2 v; y) `6 \! ^- V6 A - namespace test;! ^1 Y h7 U/ f$ r& v6 v2 J
- namespace one;
* ]# {/ n. k$ k7 a$ v* E: y* c - class Person{ d2 b1 }( I7 _( x
- function __construct(){/ y8 x" h" B; l8 L+ I6 `
- echo 'I am one!';# q2 n# b* w) a/ D
- }
# Y. H8 r( o" W0 { - }
) a' j2 M) Z2 e/ v) m6 d( Q; n' S - & _( q- q" _* m; f9 I. e
- class Person{
' \3 X5 U3 @* @6 d5 b3 c - function __construct(){9 n2 c% E0 _& V$ M
- echo 'I am test!';! v+ R V% y% p' e
- }
& n. {( z/ x% N7 ~& N8 r8 U - }
复制代码
* m; n2 z$ S* a# d- h无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
- l# z' x" C$ [( E u1 l; J看来简单的把require理解为替换,在这里行不通。
( o# _! g: k/ o6 @3 ?2 N6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
8 J1 w7 x) p- O2 d7 Y* l7 p- //name.php! L/ G7 O% c% L7 h% L* l x, _; Y
- . u+ m0 |$ { V" Q4 A5 |
- namespace test\person;
. p( Q$ ]( d5 {+ N* D - # G- T1 N6 S! r/ d
- class Person{+ `" z% V8 K5 T' S
- function __construct(){
+ q7 y8 s. @* s% r - echo 'I am test!';
* T+ O: P& Y9 L; U% Z - }8 {$ M1 ?2 u, o+ G% ^
- }. z1 d2 m+ f0 b$ u0 G
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 * \, i$ J( h; o3 R2 h! b* l$ R1 `
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 ) r/ \" S2 q5 ]
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
. Z; O& Y- F2 k+ x- A( g - ' D2 s# ]0 R- s& d: ]
- namespace test;. ~3 ]: L4 J$ x. T7 e7 V
- echo 'zhai14';
K% A* i0 I' _) f5 d - namespace zhai;
0 u% O$ f: r! T3 M/ x- E, K9 j% _ - require './1.php';
复制代码
2 E! H- X3 O% N5 u% s6 gphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ( Q: D3 O3 }6 Y* u- t/ K7 x* Q. _: p. X
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
" r0 [6 x! m6 m0 w) @! V- //name.php
' P1 y7 e5 B$ e7 N
6 b- A7 S1 U* `/ V" H- namespace animal\dog;
0 B7 J W# e$ ]- z- b8 {& s - 9 a0 F% W, |: R# H5 l& k
- class Life{
8 d; A: f0 H) [& g) K* g2 l. ^ - function __construct(){
S% R. V- ?) a7 ?$ B - echo 'dog life!';
; j+ C9 o5 o, }3 G3 f* L: { - } y; x& F! ~- }+ _: N# P* m
- }
m6 d/ w/ P r* P - + Y5 H2 {$ E# Y* g: P
- namespace animal\cat;# a& r* V, B5 h6 N6 k2 K: C
- $ h( B8 J+ ~& Z- y9 M! z$ k2 d
- class Life{
, y. v' X4 V: M" W8 l% X5 Z - function __construct(){
2 p1 S. G) ~* ~' d- o) C - echo 'cat life!';# m& s$ k, h# ~
- }
7 R* n. R/ U$ L7 ^ - }
! ~* k& ?3 n& G6 x7 u* y - 0 `/ P* ~* d* m9 J y3 `
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
; A7 P) H8 s0 _+ l - new \animal\dog\Life(); //A
1 N# z- u4 M! z- M" _
4 H' Y* u r- Y- use animal\dog; //a
% r4 Z" Y2 Z- [+ `4 R0 R5 f - new dog\Life(); //B7 P: r4 U8 h+ H$ l# B6 u8 J
2 T0 s& [- M" a1 X3 c- use animal\dog as d; //b
* P# T' x: V8 `$ e7 g - new d\Life();
复制代码
) m# D; s8 H* L2 m5 S通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 - c/ n+ G* Y# X: N: W3 I0 O8 s
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: + ]% k- G" f J
相当于
, i9 |7 a8 [+ c/ e' i5 x2.namespace后面不建议加类名,但use后可以。/ ~' s2 [" s7 s- `7 F: @
- //name.php4 |& w) c2 q) ^( U- n$ p7 C l
: H) r9 b* w+ f6 ~% {. \- namespace animal\dog;6 V5 C3 @, l7 B ~, Z: t, j
/ C" B5 x6 @ Q2 T+ z: K2 e- class Life{- z4 J2 @, ~9 c/ G9 _
- function __construct(){1 t7 Y! o( A1 C9 L, c: O4 X
- echo 'dog life!';
. ]8 v+ Z3 b5 I/ N( J - }9 H4 R# j2 Q; V
- }6 Z6 h9 l8 {8 _5 p
( F; d& r B2 [7 l, w( O; j& t- namespace animal\cat;- H' O o, P1 g" ^) B* l; A% A
1 J$ D4 O4 e3 U8 M+ f- class Life{5 S3 ?& }5 T* E6 R
- function __construct(){
/ P( U |( K) D$ O8 {5 k5 j: L - echo 'cat life!';" o1 G% c" t6 e2 a+ o6 T- u
- }
_. c. C0 I* D - }
- ?$ Y+ N) _5 S$ b7 k/ _$ n1 \ - 1 `6 s2 f. x7 [
- use animal\dog\Life as dog;
6 n1 S% ^. I, x4 ~. V" `" Y1 G - new dog();
复制代码 * |6 x" d s2 c) `
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
; A7 j2 O: D3 I- A/ f G因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
0 P+ J0 M3 @3 w' a0 v - / l3 f* j2 x: b
- namespace animal\dog;
: e4 |8 G. [2 d6 o - 1 B' |, T' l( v S
- class Life{
* t/ n! j B: Z# j8 C3 X - function __construct(){
% \1 n+ l* Z: l% g& G - echo 'dog life!';/ i6 M/ P" g$ x; Q
- }; Q8 v6 v0 d/ |7 m5 B+ S6 Z2 Y
- }
O' x3 \9 i. m" W9 M - class Dog{
+ F' E ^6 Y1 d$ z; n& @. p# E# V - function __construct(){: A# J4 K5 m; C+ J- w+ G% Y2 x
- echo 'dog in dog!';3 o9 q. A, V, v# a! L! ]# U
- }
9 m5 b" \& [* i7 w - }
/ K6 |5 a7 ?" W" _# } {2 j - " z3 f4 }3 h/ o+ p" u* n/ H
- namespace animal\cat;
- H; D; C# }& q, T% V2 f" X, A, V3 e
0 x6 f; I" f2 A& v5 g6 t- a+ O7 |- // class Dog{
. e/ N' J: y6 @ A" \: m4 E% l7 m - // function __construct(){
% g4 }6 Z p3 ~# K' V, R. R - // echo 'dog in cat!';
* X2 |) U s% h# N1 j" w - // }* g1 q* B; j2 q( ^/ l5 [
- // }
+ _2 q2 M+ ?2 `9 e: z6 E& |3 W$ h - class Life{" y1 U; R) T, [" K$ N
- function __construct(){
0 v* Q: w8 E. K9 N - echo 'cat life!';
& f5 Q5 F( R/ W6 w2 j - }3 I7 J- L3 P' E1 C' _
- }
& i; Z" U6 A7 Y0 P! T - - z$ q3 z3 z$ G# M( S' o( C5 ?
- use animal\dog; 6 Z/ Y! J2 }% J- L3 L& B4 g
- new dog\Dog();
复制代码
- m* W; n& t: m J4 c如上,使用了
/ Q3 l7 ?; J0 m7 p& A7 S( Rcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
6 c D. v, v k+ a$ K! G简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 |6 j) Y9 }# E; ^2 g/ w3 W
# E. O# b: ]8 u+ B) ~/ k
# y4 \9 U- k3 A$ `
o- n- @+ h3 L2 Q# u' R: w: b2 @4 F' Z T. [8 Z
|