|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 4 r2 N! b* u3 e% r
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 . S1 ^: v! q. d* B m
( [. A; E) X! L: _使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; + s, o, \. Q, u2 j" p
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
0 Q/ v: b. k+ \1 w+ D结合使用方法来进一步理解它的使用目的吧。
3 U! S# n$ H2 T0 i" @' w. w2 X, I- Y+ M7 d. ~3 ]% M
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;* ~( A. q& o& I* C2 R0 s8 [& w
- namespace One;
$ Y1 a, u* z0 M& ` - namespace ONE;
复制代码 5 K; R% {! E/ p" _
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 3 [5 a+ V. ?" z
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 0 A: w/ N& |- N
- class Person{" S- `0 v# N) g6 o- {
- function __construct(){
9 p6 T: @& `1 S9 _+ J - echo 'I am one!';6 I. F. K3 ^/ B$ M+ w
- }8 V$ W8 n. X: b. d- D/ h! I
- }
复制代码- //name.php* Z# f$ F/ g. j# b! h
- require_once './1.php';
# K9 L9 ?- w) i( L/ g( V, E - 6 X1 p8 v4 W. {9 S, I. E
- new Person(); //输出 I am one!;1 d, F5 b3 t1 e& @) J4 t& i
- new \Person(); //输出 I am one!;
复制代码 2 f1 K2 a; @: ]" s
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php+ y! o# z. g4 o, Y
- require_once './1.php';
2 o% o& s( X0 d1 P' q r' m - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
/ h( n2 a! }: {( X6 {" u$ G1 }4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 5 q6 c6 g* d% z% S- G* E
- namespace one;
9 I6 w8 `; G( ~' K - class Person{
& J) [. R: }3 @9 C - function __construct(){0 {: h3 k2 l6 g
- echo 'I am one!';1 \ M) s6 O3 @+ J: R
- }
# r9 V5 H0 v' d - }
复制代码- //name.php
( ^; l1 {5 _( c* v/ b7 L! K% B - require_once './1.php';1 V2 l2 e9 B7 b9 j. J4 Y# L0 J( P5 l5 W
- new \one\Person(); //输出 I am one!;1 X0 _% j% q, B7 J9 j, d3 C5 f
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
3 n+ K6 g/ x8 Z% O! M* i3 l可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 , n. p2 J0 N0 `! j
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
4 K9 x' v- [ k- Y/ ~- //1.php
. j5 ?% y; ~. ], h8 t - namespace one;8 c- Q4 C3 N9 G
- class Person{! O; l- l3 y& ^1 O& B+ ?
- function __construct(){* a; q9 O0 ]$ {! v2 w8 h
- echo 'I am one!';
/ O0 T( _) K) q. s: v - }
: c3 ]+ P* i) M3 Y" l/ z$ F - }
复制代码- //name.php
. O& V* Q$ W- w' V& P - namespace test;
; y' Y+ K' [! ~) O - require './1.php';
/ G' D' v1 R- M) j5 J/ x - new \one\Person(); //输出 I am one!;
- Y. q n1 ]( C* Y! r, w* a* X - new Person(); //这里结果会是什么呢,猜猜看
/ j; o3 p7 U" B8 N |4 O; ^, B - 最后一行结果报错:
6 k3 }$ |' i6 ^4 H) {3 @ - Fatal error: Class 'test\Person' not found
复制代码
. ^0 h9 }( \/ J! \( X) h% g7 }/ _. ]4 l9 ]1 r7 D: U
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 ' m/ i; O$ I D, B- [
结果报错: - Fatal error: Class 'Person' not found
复制代码 6 t1 }$ k# v! D) Z* f
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
: j5 _2 h3 J( i' L* ~0 k( L! r - namespace test;
+ J, L7 P4 F6 }9 \ - require './1.php'; $ ?; i- y/ C% X0 n( X4 `' s
- # v6 l* V& ~+ e/ m
- class Person{
7 e; s K, G- L - function __construct(){
. W* C2 P) v/ [0 n3 Z) v* \ - echo 'I am test!';
* M* B4 H+ C" g7 C - }' z9 a6 d: q, s/ e5 m$ F$ ?4 L
- }# P" J1 E1 T. [. a4 U/ u/ o
- " W' C% g$ g/ y% I' X
- new \one\Person(); //输出 I am one!;% H! i I; _ l; N b) G' p
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 5 I5 K& c L4 n
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
$ z4 c6 k/ T$ I4 M& A - namespace test;
6 u1 |2 Z0 C) q5 z - namespace one;- T- F: {6 B; U5 q0 k
- class Person{8 _% F7 G" ]# z: g
- function __construct(){
' `( L' k: g7 E8 L3 V/ q - echo 'I am one!';
6 u: y8 ? J0 x; j( \0 n - }) ]. V E8 D1 K9 Y6 h
- }' b7 G6 ^5 l. ^6 A% P
! ^/ j w+ v' T* l4 Q- class Person{
9 f' `7 L5 t. ?" k, Y - function __construct(){# a( b( ]2 M2 ]9 g5 u0 Z3 t
- echo 'I am test!';
) H1 O7 A/ Q/ t5 _3 O - }
3 @4 f- d1 f: M2 ` - }
复制代码
$ X2 s; k7 C! b1 Z2 ?) u8 H2 t4 u5 }无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
8 `2 l0 N3 M# n! Z S看来简单的把require理解为替换,在这里行不通。
, B5 ^: K- u! \0 r+ v6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
6 n+ A, r3 ^* K* Z6 O6 l5 h- //name.php
* j3 n# h4 J c+ u - 1 m: t$ b( a7 A2 V2 y3 u C! v
- namespace test\person;
# i3 f' I8 C- {0 L
/ l3 _& \( Q5 T- J- class Person{
, `( j8 a! S R+ D. ] - function __construct(){
: }7 a1 i1 P3 }0 a/ ^! t( K - echo 'I am test!';
5 c7 }# F2 a @( d: B) j - }- w9 V2 ~0 A u3 e8 _3 l) C) ?
- }
5 ~- P, z) i+ i* r2 q/ b; b - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 5 t* N O/ J; \% F2 `
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 ! V* Z( B2 ^( a, h: R8 l
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
! H( e S7 J4 Q- r! m
( ]9 ]( `/ s, f- namespace test;
# b9 ^$ n6 f' J9 m - echo 'zhai14';- R; t% E7 _* _6 K e
- namespace zhai;
- D" v% Q Q4 o - require './1.php';
复制代码 8 g. V& A/ y. B. M* R/ ~7 q
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 * h% N% P p7 O }
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& g8 p7 j" A9 V2 O8 G& w- //name.php) `$ o* V% c9 W7 Q7 E% d% ]- y& h
- , c9 T ^2 T0 S# q, q
- namespace animal\dog;0 ~/ {" G! ?$ c- b, H0 T
: \7 h( n* d8 D3 M. o- class Life{' R# A+ E: B/ I& |7 I
- function __construct(){
2 x- B/ E9 [3 E - echo 'dog life!';
+ q: k% o' ~$ _& J! v - }0 W* {0 Z. i1 ^ |7 M( M
- }( c* R2 a) V0 E6 [1 O" V+ ^/ k
- & A5 _4 k) A- |8 u. s
- namespace animal\cat;
; G: e9 K& l' l! H" r6 r) U* Z1 ~; J+ Y! m - " k" N/ Z* R! N
- class Life{
9 F4 i/ Z$ m3 W* q, A - function __construct(){
% Y% B- N; e6 p - echo 'cat life!';
9 z% I6 H% |0 A - }. E$ c! Z. K& ]* u- y( Z I
- }
3 R$ ~* V% f- x ^! w5 f$ T - 9 h5 s4 r9 F* w, a
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
) ?' j# R6 e" j5 ]' [4 c% i - new \animal\dog\Life(); //A
& W; u6 P# p6 w# I# T3 x
. p# R1 ?# h+ q% C& v& v) f- use animal\dog; //a6 ?2 w N4 }: t0 X) F
- new dog\Life(); //B
" `' j1 Y4 H4 I* r; I0 q+ j. r - 1 g, C9 M3 b s1 \% U8 t1 z
- use animal\dog as d; //b
: o# C0 r6 K& }, Q# s - new d\Life();
复制代码 - S9 E& S0 Y" ^& o" p+ Z# ^! v
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 / r0 s; R& x0 z- B( }& Z9 q
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
% P5 J" F' N+ p7 V相当于 $ ?1 h" w% a# ~9 X1 b, O( C
2.namespace后面不建议加类名,但use后可以。
! J$ ]* @1 } C0 Q- //name.php
1 w+ X" @# E! D+ s" G) y - 4 s7 |9 c7 m0 r1 i6 Z1 B
- namespace animal\dog;
- t; t1 [% w: d5 f
- I0 C6 a: ]3 O2 R- class Life{
9 t' e+ S" C/ G i - function __construct(){2 ?( \( l" r4 ?# m( H% ^) @
- echo 'dog life!';2 g2 Z& y! b$ h e0 g# I$ _2 e2 c2 l
- }
3 O) I# Y5 [% Y/ Z$ Y - }! W4 X }9 |7 g: r" `6 S
# j$ l! a z- S- namespace animal\cat;
7 R8 @+ J; M( T% z% _% q
" Y# F1 d2 l# v$ P6 O- class Life{4 [8 q! ]) W e% d
- function __construct(){ e i( {$ X/ M; ] v
- echo 'cat life!';6 s2 J& U: u; t$ H, n
- }
% t u1 ~. Y. A. j% |& ? - }1 V' Y0 c3 K! l" T
- 0 F3 u5 S# O) e) j. Y, O
- use animal\dog\Life as dog;
' u4 [0 B, v2 f+ z - new dog();
复制代码 2 U& _# d3 n5 I6 a9 @
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
( a) a+ z% X z2 g8 A5 u因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
6 @$ D$ o) [, I. D/ u; p
4 L+ n+ ?1 I' |" T- l+ L- namespace animal\dog;* V! ^* D& t# t: E! ?
- . f8 f& H! _8 Q& s3 n
- class Life{
2 X/ W% B- f, C1 w* z - function __construct(){% s! D$ |: E$ F/ X# t( [
- echo 'dog life!';
4 t6 ~& r _% f X - }
* K" t6 d4 Q+ ]& y0 D4 t ~ - }& ~& G% t- h; g4 U H
- class Dog{
, @+ ~* k, _7 b$ U: S! ~, P3 |6 y' d - function __construct(){7 [ c: u0 T* c/ [# S
- echo 'dog in dog!';! v5 x0 r* I v/ O% q7 B
- }
( p& B7 V' h. Y" v# i - }
1 ~ @* P' m' X5 [- g. Y3 l s: H - 2 g5 E( T% g4 e+ x# J+ g
- namespace animal\cat;! y9 V& x7 I% Z* N4 \
/ W6 X' p# Z3 V3 X2 l- // class Dog{- a' e5 ~1 o' ?1 ~1 Q h
- // function __construct(){
, {* V2 S. [3 ~- g - // echo 'dog in cat!';9 c' U3 M7 E4 `2 n3 s
- // }
$ s' A9 f- ]/ f4 J& C4 @ - // }
# u3 U) J; I! Q/ g - class Life{
3 C2 g. Y2 f5 S; e t& @9 z; N9 g - function __construct(){# v; Q. y- w9 g3 u5 J# M
- echo 'cat life!';5 ` z0 X- q, m" Q$ s* B
- }
' l# m) b# d" q. J- X - }. W& q5 M0 V2 g P6 n% c
- J! k# Q! i: ^
- use animal\dog; 5 @6 u3 n) i: \, S
- new dog\Dog();
复制代码
. H% f7 Q4 }3 I: m* E如上,使用了 ( l( n! t2 r6 |5 { a
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
; l! }4 H( J x* q; f7 f" G& |- i简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
5 z, G4 j M# m; i+ h7 K
0 z9 G& X% p, Z5 R0 ^2 r3 Z/ A. f' S" i; O3 H$ z, k' C' d/ U
5 G& O6 b7 b( L( I4 k. A+ u4 z* S+ [8 I8 l$ v
|