以下皆为本人自我理解内容,如有失误之处,请多多包涵。
) [7 C' I# _6 u' R. m( V文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
8 ? L7 e% N% X" |( x: |( N. F
7 v" N4 K/ F' S: `使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 4 l& j# E1 Q7 ?! `
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
! z. r9 F i! _, ^9 r9 V2 m& }结合使用方法来进一步理解它的使用目的吧。
& D2 b% I. G5 g7 w3 s
, }/ q3 w& X) e4 anamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;$ b5 j) P. a5 I) P [9 B
- namespace One;, ]% a j* {; x; D
- namespace ONE;
复制代码
c1 y# {3 r$ c$ V如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) $ k% ]) }' w5 U2 m
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
4 ?' l$ l; x; M: S" R. ~+ K - class Person{: k! F" V1 k( v: p
- function __construct(){6 x/ w. t; \8 e2 ^
- echo 'I am one!';
! ~, z3 b" Q. |5 V$ c1 C - }
; l/ Y# O" s2 U# b- H& A! b2 i i - }
复制代码- //name.php2 S- ~# \! a5 ^# ?5 v* ?/ U
- require_once './1.php';# H( u3 P$ a; ]: w8 k$ u0 d
( ~+ H% @) t( E! }7 `6 ]& n( V4 J- new Person(); //输出 I am one!;
9 x# F$ W' c- ~; u$ b8 E - new \Person(); //输出 I am one!;
复制代码 0 Z3 p; S) J7 Y. ?
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php- I2 I' p4 \ w5 k F+ q
- require_once './1.php';
* y. c, o3 C- u- N' O - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 / }0 @/ _, `4 h! n5 ^+ H- q0 x
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
7 J% i" ?, A: A2 ^+ h - namespace one;
$ }8 t4 v- h- g+ M+ m - class Person{, M( p. ^ q4 A7 x8 y1 l
- function __construct(){" R/ H3 G( N( |7 U' ~, K
- echo 'I am one!';
" t, g2 I. q) M- O$ J: P - }/ c- M3 G5 d3 s$ v( ^9 K" g8 e
- }
复制代码- //name.php
" c8 c- o/ ~( O3 K* r, f - require_once './1.php';
% X8 }1 r( s; o" H - new \one\Person(); //输出 I am one!;+ }; o) V. w% ?" Q( ]% u3 i1 p
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
5 L" d& J! T, P3 X5 B7 C. V* o可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
' L* {7 ?6 i: `) ^3 _/ M5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。6 v5 ?6 m4 Y" t8 O: t; j& R
- //1.php
9 A6 R" f; p2 v, N4 i) i" z - namespace one;
$ M3 V/ r# F4 a4 l1 ` - class Person{
: u3 E) t+ r) H; p' u7 K; o! z9 Z - function __construct(){
/ v$ ]2 x8 N% Z3 H8 h( R3 Q; q- N' { - echo 'I am one!';0 S$ s# ~ J" y0 a* \7 e2 t
- }; \2 k: }+ [4 V& ^* a; z
- }
复制代码- //name.php
3 ?: ^5 S" Q7 u' w, H: F - namespace test;& v |4 a! R0 r
- require './1.php';
; q' }5 w7 T9 h - new \one\Person(); //输出 I am one!;
; w' Y* @0 a5 G6 [0 j" Y - new Person(); //这里结果会是什么呢,猜猜看 |8 a# G R, d4 E
- 最后一行结果报错:
( `0 O# g8 x+ {- w - Fatal error: Class 'test\Person' not found
复制代码
: @; ~$ w( _2 g# _- E" ~7 X f! o3 ]+ W8 c3 b8 o# p3 V3 F* z5 O4 h0 f: b
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
( f0 ~9 Q2 |. a: z% z$ q结果报错: - Fatal error: Class 'Person' not found
复制代码
+ ~7 [/ H3 V4 o0 T5 m接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
7 X/ z2 A1 d d- Z% I) N% a: E - namespace test;
) R$ `3 m# R. h8 H) m* p2 f/ n7 Y8 L - require './1.php'; $ j0 Z# N* v# U
- ; L3 t" [% i" T0 T8 j. E
- class Person{
% k' c: X* ?# r3 Q" V& u; k - function __construct(){2 D5 `3 o0 ~. ^/ s
- echo 'I am test!';5 Y& y, O5 _6 v b
- }
1 N! n h4 P/ H - }
9 {8 E" u/ z& ?, w$ X }
9 Z8 o& j' l3 o# y! N- new \one\Person(); //输出 I am one!;) P/ ?) m. b t/ W! S$ @2 Y: q
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 1 }# }) }) i# Z5 J5 R
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php, ]0 ^9 c0 }( `/ u
- namespace test;
: U1 N5 v m5 ~- m - namespace one;
' Q! }) O% g6 L+ d) d/ L# u+ S+ R - class Person{
( g4 N! [- T; L* h- W1 l4 k c1 B" A - function __construct(){) L& C1 f& `4 ^0 @0 ?9 o) [( ^
- echo 'I am one!';) [( L/ B2 \' U2 m# `+ y1 {9 s3 b
- }2 x$ _+ W M& Z9 T# n8 a* D
- }
& N" ^2 r2 ^* r1 X8 S$ }5 s* B - ) V2 I3 n0 s, ]" [0 { ^
- class Person{
4 |. c; b B4 {& I- R# | - function __construct(){$ x9 W }* F* x" D( ~8 g" ~
- echo 'I am test!';' v# Y% x2 ~. Q1 ]8 o, h) o' @3 k
- }
" h: L9 Q9 c1 W* O8 u* h - }
复制代码
5 S) m0 A7 c; L0 Q' R无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 % c, |9 @% Q; q- `8 `9 O
看来简单的把require理解为替换,在这里行不通。
9 V$ ?1 e" k+ \0 `6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。" M9 D6 @; W: @- h! w* g$ @7 L/ t9 M
- //name.php
1 w; o- K+ G5 w0 ?' ~/ V& \+ r - " V, Y& d5 Y) e l* }
- namespace test\person;' O! H9 N+ J- A- W/ o$ A0 ?
! n# g& N1 t4 u; \5 h2 h: z- n- class Person{
0 _! q7 W+ o0 f - function __construct(){
7 @8 ~* Y, s' C. S. Q' m - echo 'I am test!';! K2 c Y+ g- }9 ?8 [
- }$ ]5 }" _4 Y0 ?4 R6 K
- }, P3 K @2 w# P5 y( ^) x
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 & |5 r" z# N- z: @; [
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
w, v4 U2 F+ g0 E7 {" W( w7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php# `; {! q" ^) o8 u& p" h3 a
! [" p/ @3 Z- T5 O% d- namespace test;
9 r% I9 Y) Q+ a6 H( C. k - echo 'zhai14';
2 x' t) p8 G8 ?1 O* y - namespace zhai;
5 |, E. O4 ^8 X$ n8 @ - require './1.php';
复制代码
1 o0 z' A. v# h- Hphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
9 b' {+ n1 h5 Wuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。$ M1 n; o7 ~9 Z3 x
- //name.php, n4 O+ p! P8 x p. M) c, Y3 H
- * D+ \7 I- k( G2 G# `# S
- namespace animal\dog;1 g3 o. Y4 k/ B2 S7 T
9 T5 n- |. b1 z/ o" M/ c$ q- class Life{
+ U4 y/ S+ t: |4 }8 Y! |0 l - function __construct(){
) z0 G9 z( A+ g - echo 'dog life!';
5 v9 m# F; z- |$ [! i. } - }
# d* z- M4 @' y2 J+ | - }
( W# F7 P* g( f) n. x8 O) q - : j! A% B( w4 ^, D! ?. |( x
- namespace animal\cat;0 L/ I9 ~; M C& l1 W. A7 I4 F g
- $ w; f& N7 @# W4 z6 @3 l, \
- class Life{; R8 p: \( Y6 h I# l
- function __construct(){
, R, `( B& B9 [0 c - echo 'cat life!';( A- X' q0 g+ m; @
- }6 ~: ~) U/ A' W/ u
- }
/ a* m, X6 U) U9 v, `. S8 o7 }6 t - 0 }; {2 B! [3 p: Q0 K" b
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间1 _2 g R4 H' m7 U+ z! I
- new \animal\dog\Life(); //A6 {3 w$ a5 g% d) Q! V( d2 e
8 s2 B1 P) H6 `/ D& N6 ~7 G- use animal\dog; //a- _$ I( s. R8 p9 i- k
- new dog\Life(); //B/ l" N4 E8 U+ A2 g
- 4 b4 Z' J7 f; b/ S, H0 c8 o) a) [
- use animal\dog as d; //b
, J- J- m; ^4 C; N - new d\Life();
复制代码 9 c. Q, [, M# J+ o# L2 _ h
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
- [7 I# y" K# D: j$ s3 ~- [- |4 k3 d通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
5 x4 W, F X" E$ z* C% M* L相当于
4 x( w% E3 Z: E% H! V+ J2.namespace后面不建议加类名,但use后可以。
3 O* k4 n" |/ ~- //name.php
# q5 [6 k% A" @' D! e - 6 E' Y% g; V$ _3 h5 ]: X
- namespace animal\dog;* A& E3 Q# L" Z2 }, j* m! f
- e8 f5 e6 T0 N1 w. A+ J3 J5 l
- class Life{, m) O$ K# t# B5 h2 v* P
- function __construct(){
( i, M) o4 T6 k - echo 'dog life!';
& ~8 d1 Y& U2 i: ]3 v. b - }
. s, O( \& S; e- g - }5 d7 }$ y/ u" i0 g+ t+ @" a. L
- 3 q4 I" O4 k# ?7 O1 L) r
- namespace animal\cat;; O: W) n: Z$ x) t0 s. m+ ?7 D
- ' e) @+ c0 |* ]; s1 Q
- class Life{
0 r5 E7 f! K0 N3 } - function __construct(){
9 {. I: g M& r. I: K& {* q) V3 | - echo 'cat life!';6 l" j" {7 {' V5 O1 [
- }" }& h. g! g& D4 o4 v# I6 R
- }3 ~$ Z' o1 q( f5 U
- 6 E4 e* r, V/ r4 J
- use animal\dog\Life as dog;
% e2 P) l! {9 b% q - new dog();
复制代码 $ B* f% @5 W0 L1 v8 z5 B: W
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 & a- \2 E E* s( t0 r2 {
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php( L! ^! G/ J5 T* d8 B
3 m8 U p7 f2 Q- c3 r) f; x- namespace animal\dog;
/ i9 D7 [1 n5 @6 V3 i - & n; I3 F1 e. i0 X$ S, u
- class Life{
3 ]! _; u( K4 `! P - function __construct(){! C! s4 l4 W0 q8 Q$ k( T
- echo 'dog life!';+ ^# X. v _% e3 z! y% {2 H5 }
- }; A [5 a) n3 R; G' u. m+ c& g4 `- t
- }
+ ^; P# l! B9 `% ^$ B4 I. @ q - class Dog{
1 {' U3 \# Y$ {$ x: u! W; e - function __construct(){" \4 K+ s" i7 U* J. C8 B
- echo 'dog in dog!';
6 ]8 W/ T9 ^5 S2 x# ?7 u6 A - }
3 y! R1 E( M% [; r$ b - }# w3 T$ @; t; T G8 H( y
- 8 a9 @) T# ]9 e) t
- namespace animal\cat;+ K7 T- K% o' M$ @; B/ C5 C7 `
6 b, M2 L. k& d, a- // class Dog{
& w2 B: m& I) G - // function __construct(){5 s$ O1 l4 n6 Z2 X3 q& L
- // echo 'dog in cat!';
" B# d) j& M1 e$ X, S - // }
% n2 u( b" |. I4 d7 P - // }
. M( t0 }" |# |0 A$ ], \2 D - class Life{
% C( V, T" ^$ H0 x9 R - function __construct(){
3 h, n' k0 a; R! P - echo 'cat life!';7 J6 b: j4 @0 {. b% n" Y6 h# Q
- }
4 u. Y0 Y! i* k- r7 i - }
' T# x, J5 a) ~% H8 o6 _
- J6 F; N( F, W( w0 \- use animal\dog; 1 s! B% z* W1 n4 w
- new dog\Dog();
复制代码
9 g" f8 r2 q. w7 ~. c4 v如上,使用了
8 i) r( k* f; K0 ]& {cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
h% Z( w. }: J简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 , N- N1 I$ O! r- U2 h2 i' k
& g+ q3 \4 s% i7 O* |& F, ?! `- Y4 l7 G: j1 x2 B
0 F `( l' q+ \+ ~) |" u
8 D* L8 K: i+ U& H P! U
|