|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
0 q" Y, ~( z# K* [文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 ) A# o( Y. m: B8 ?. G( F2 H
8 T( P- o) G2 A- D O使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 1 L: m) u, s) Q; s& f
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) ) ?# \ L+ C8 N) c
结合使用方法来进一步理解它的使用目的吧。 " s+ o# u: U2 ^+ n f7 A+ g3 `- a- V
c6 @ B- o& I3 Inamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;7 B# m8 i, l& v* X) |* e& ?; H
- namespace One;
' x: e1 J6 |4 X* M5 J4 K; w, c - namespace ONE;
复制代码
1 ]% Z$ q# b# t7 T" N如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 7 \' B K6 P, E" d4 q9 k ?
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
8 j+ X% `/ u- x4 y - class Person{( Q, B# `* j1 w/ N
- function __construct(){
]0 x( n$ `! v! ?8 V' H - echo 'I am one!';
5 O6 t& Z7 x1 f& E2 { - }) l+ Q4 T! a# O! y4 ]$ Z
- }
复制代码- //name.php8 Q6 F H4 Y5 N
- require_once './1.php';/ X4 _( X0 i: s4 ^
1 w6 G& O1 e R2 O4 F8 M$ B- new Person(); //输出 I am one!;
K4 m$ g" M. O2 s+ D3 ~1 V" \ - new \Person(); //输出 I am one!;
复制代码 U* Q. D& D4 D( Y% Y9 b0 Y. }
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
; |8 R& D! W [ - require_once './1.php';4 I7 P6 }+ P8 ^. J# J! Y4 d" l. q
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
. O" a7 K: B3 s8 B/ m2 u, \) |4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
) s* w6 [2 s; L- {4 n9 r - namespace one;
1 ^( g1 P$ s% ~, `2 v/ p - class Person{
" x% E# I0 g/ {" N4 d- N3 x4 r. A - function __construct(){1 j3 c8 @. o5 _7 v
- echo 'I am one!'; U8 z! |& a1 v O8 ^. ]( \
- }
6 h: E3 D8 B. I9 y( Y, @ - }
复制代码- //name.php" h0 a; U! W& e& {1 D# {* }
- require_once './1.php';
* ]8 X: Z( `' H - new \one\Person(); //输出 I am one!;. b: {, I) `) Y" b$ H/ @
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
& F) f' P" B$ H6 t可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 % L/ ?( ^) Z5 q3 W, R9 e
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。! Q+ n) G: J0 c
- //1.php
; K% t. U" q/ U3 _/ \ - namespace one;
4 N4 d2 M E7 P4 A1 F& F - class Person{
# Y9 R5 V! G3 o' g x0 w! H - function __construct(){: ~2 a. S' ?0 o8 L5 ^8 W7 W
- echo 'I am one!';; O/ F- ]9 \( J9 G- ~) T
- }
7 C/ ]% t+ a; D; T j9 x$ | - }
复制代码- //name.php
5 Q) S' H; s" l' x* `& M - namespace test;6 Y$ X. W+ S8 C+ V& x2 B
- require './1.php'; . ?/ B. E `, G
- new \one\Person(); //输出 I am one!;
' A0 T3 i2 E2 {! x4 y - new Person(); //这里结果会是什么呢,猜猜看0 w f9 F# s1 x/ d! N
- 最后一行结果报错:( g* a( y: m: r* y4 K; i
- Fatal error: Class 'test\Person' not found
复制代码
r( \& |% C2 ? P: j
5 k4 u' }: l) {' p2 ^% M4 n首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 1 r% Z5 I% {! e5 k& k
结果报错: - Fatal error: Class 'Person' not found
复制代码
, t' e ^! v% T接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php8 j! a2 H0 p1 ` }9 n/ U7 p( `( x
- namespace test;1 A3 }* |( G% B/ ~% m: C7 v
- require './1.php';
$ c+ J1 y ^$ x1 q/ B" v - k( Q" L f9 U$ F% z5 R
- class Person{% q! A5 M4 t& B$ D7 j) Q4 u
- function __construct(){! r0 p' B0 _7 Q A# I( v) Q
- echo 'I am test!'; }1 H* d3 x' H) `9 V
- }
: y; Y, I: i/ C7 i2 q2 {% w6 O - }' P% Q9 i( d9 W i
- * v$ U" T: z4 |6 W- H
- new \one\Person(); //输出 I am one!;
7 ]" x" O" Q$ H [3 V% ^ - new Person(); //这里结果会是什么,自己猜猜看
复制代码
$ V$ l# _3 q* G" m& q; C, l( E最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
- r" `. f6 ]6 K1 d - namespace test;1 v) @) `4 `: S; [7 P8 P. F1 J/ _" Q# t
- namespace one;
3 k$ j3 ~; v6 r; |/ y - class Person{" {. {# X6 @1 _: l, w. i! N7 j
- function __construct(){
- i8 l- V7 J$ W - echo 'I am one!';
9 G9 l( _: p6 O& K( o3 M - }, I. Z3 F4 p4 Z" `8 V
- }% ~ f- G( g8 W a0 g5 S
- 3 [0 Q. q$ e" z+ ]3 b/ d+ M6 d
- class Person{
: c: |8 B5 I( V- m - function __construct(){8 ?+ _! f9 {1 P5 L
- echo 'I am test!';
. l2 r7 J. M) C - }
$ L4 Q( q' _5 i6 u/ n3 I - }
复制代码 5 H% f; r' a! @" N3 l' O2 r
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
2 [9 g3 s4 |! c5 }, j9 }7 o看来简单的把require理解为替换,在这里行不通。
0 Y, R0 @4 h2 F$ d* h6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
8 X+ V/ N. Z1 [: [! E- //name.php. e8 P1 D1 @! |% {* M+ o
- 7 d1 f: E' ?* n' |% L: V; h
- namespace test\person;8 T- U/ h2 L1 b$ S* U6 K
0 j" Q& L& t0 B* H3 P8 L( E' W- class Person{$ X& s; j U; D5 y( h# O
- function __construct(){$ {/ P( i5 G# V$ r8 o9 u$ `! x
- echo 'I am test!';5 Z/ F% s" S- i, r+ i7 h6 d
- }
( @2 {/ n9 t0 N4 k& |% W! M - }% p/ L) [: S7 J7 E/ O* n8 _
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
$ s) Z) d u v# ?$ S% F+ g不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 1 N, ]$ `5 a' e; ?2 g4 z
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
1 |# P. F) W8 w - 9 F+ U/ |( y& G
- namespace test;! q1 g# g% h. i* Q( i* w$ Y/ k4 y9 h
- echo 'zhai14';
4 H( d) W. }6 R; n* D4 } - namespace zhai;1 ^8 t& A3 X, G7 L8 s& ^9 M3 K3 ^
- require './1.php';
复制代码
" K l: X' P) y( aphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
0 f7 l3 `3 {/ @: o) l: luse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。8 q( L/ l6 M2 Z6 l3 F
- //name.php: k9 U+ L% l Y
6 {0 K8 G5 t' ]5 Q; G; D) J- namespace animal\dog;
+ Q% N5 d6 {7 ]8 L" J) ] - : Z/ I( d3 d7 G' f* e
- class Life{
3 g( E& D7 D0 W" u& \; O! m) N - function __construct(){7 ^5 q% H2 k* C% Z# `3 C
- echo 'dog life!';& ~) }# d( a5 ^0 X% C: h8 h! {
- }
; z0 j" I$ S$ X. L% R0 h" N! A0 y! ^, _ - }
5 U. i; l# N4 H9 [' a - 4 H2 U. T0 k% L/ O+ P
- namespace animal\cat;, U! A3 g) r' i4 a0 C: `( c3 L
& e% o! O- u b5 S' l- class Life{
& Z5 ?; L Y8 x+ P - function __construct(){
1 ^" {5 N6 J2 L# O3 c - echo 'cat life!';
+ V- M" G! G. H7 f - }
( F7 { U. a2 I" H4 H) n: ? - }
6 G! Y+ x/ f+ x6 r
) \2 U% r$ E, s1 U3 D- T- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
. ^ C! d( }6 i# N c* Q - new \animal\dog\Life(); //A
- z* n5 ?4 B! E# q; t
5 k8 U8 \ ~) v' R2 S$ t- use animal\dog; //a" o9 K9 ~5 B. g3 R! a2 ] `
- new dog\Life(); //B
1 D' Q) i1 K: u1 X# f5 P
7 ], V6 J |% Z5 B, Y1 N' b2 }. C# T- use animal\dog as d; //b# q8 L, B5 p; | [6 T
- new d\Life();
复制代码
S$ w" T* N" g4 k7 B通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 ( V( q2 }( r. @0 u( m
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
~, Q$ a+ a4 b* P9 V' Q相当于
* [ t: [5 N- S) m/ D1 O: u; @1 b2.namespace后面不建议加类名,但use后可以。
; e$ @) W8 o* R. o" n: t- //name.php# _/ s! D* `, h- I
- 2 ?$ ^* ~" @$ r( c* Y* w( R+ L
- namespace animal\dog;
8 S8 ~6 i$ ~" s
3 p7 y& U, s. w& H- class Life{
7 T0 n% U0 l2 }- `" i" _% f - function __construct(){9 B! f! P' z/ K
- echo 'dog life!';
6 d! ~& Z9 B7 ~8 h6 s! S - }% z$ \9 p ~6 G3 g% Q
- }3 o) T3 K+ G8 s0 `/ t; M% f
3 {0 T& U/ f( \- namespace animal\cat;$ h6 b, l9 \) d! }
- . u) G# S9 Y4 D0 X! M! n. Y
- class Life{
. g9 D( T& n0 w( Y* e - function __construct(){
; \( z& A4 q8 n2 Q - echo 'cat life!';' u1 g- r3 D$ m0 Z w
- }
5 `! T7 ~6 F1 | - }# W. O3 B/ a @8 u4 H
- 1 Y: G9 G8 J' D, B8 `# B
- use animal\dog\Life as dog;
# {# Z$ c! B( Y. G \2 ?3 X0 O - new dog();
复制代码
6 H& C# m5 [: v* b" D7 g" \4 a; Y0 W如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 0 o6 x( m4 M1 z0 U' E$ C- {
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php) ~2 J& m9 i0 |1 L
9 K( h& k9 G3 T' K- namespace animal\dog;
: c4 i. J( ]2 p+ ]$ V4 ?4 }) r5 [ - ' ^- w* W9 @- L' a* ~# y
- class Life{
, {; C( t$ n8 O. p - function __construct(){
" y! \, H7 ~9 D- ` - echo 'dog life!';
! L- _+ I& C) X8 j+ c' T) N - }5 X( F. o, q0 e: P: ^5 Y
- }% L# M2 z, S0 @
- class Dog{) o2 W9 M' H7 D9 _
- function __construct(){
0 T6 x: L# X+ @2 W+ o) k# K - echo 'dog in dog!';' U1 Y" z3 w6 K6 m7 f" b8 ^1 k8 R
- }
3 H- c% J$ y# C& S2 m; v - }+ }/ K% L9 x! W6 J( v ^
- 2 y4 m4 y: w7 b: f a( h. H+ m
- namespace animal\cat;% c* Z. J( U9 `
9 K- u& ~8 J- c" y- // class Dog{# M% ], P/ k ?
- // function __construct(){
7 Y$ I6 @# G8 C# s - // echo 'dog in cat!';
, M: x! a2 x1 o; S* b - // }
. }' p! h5 O5 o; ~5 r) d6 f - // }3 I2 ?( y. [+ o5 D V
- class Life{* b$ p9 D8 m# A0 c0 V$ Z
- function __construct(){
* V: h( e5 v' ^: k) x$ z9 o - echo 'cat life!';, s1 b0 j' l6 \8 F8 @
- }
) f8 R, `; `2 _/ n! A: N. q3 z - }0 z+ O5 C0 I% }; D6 J& Q
- $ B7 k- k8 I" J. O7 B* g
- use animal\dog;
8 Z# i+ K; r) H s5 x - new dog\Dog();
复制代码
( C( M' Z- j" k, G J3 t( F, ~! i如上,使用了 $ R5 \/ ~8 w5 g! v
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 8 _% ]$ P0 f1 {2 A$ Y' f
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
9 h3 Z+ d: W5 ^% k: i$ \6 ^
/ }7 d+ @6 _7 Y8 {/ T( I0 ~( ?; v2 B# b% r- E- _4 f
7 v2 b; d6 {# v% A M& W9 K$ y* B+ M
|