|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
/ K8 |4 u. r* q; @( f1 d文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 5 z. N: `& _" V( Q. |- {( o( n) d
9 m* B# n6 {: w8 U) k' j使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; & d3 [+ g6 q0 X D
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
# a) c4 x: A; @1 W结合使用方法来进一步理解它的使用目的吧。 & c. M' k( ~, N4 \* u/ s+ \% E8 l
3 @' w! B9 E3 ^8 K
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
- g0 I# J3 h8 H) e- ^ - namespace One;
1 R% I8 {( M' J/ W d8 k - namespace ONE;
复制代码 6 `/ k5 D; ?/ N
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
% k2 [6 r9 {% A1 ~# i G2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
, ~6 H, F7 u* B' W/ w4 d - class Person{7 m, z. \4 n- s, m/ Z5 ?5 O1 W
- function __construct(){6 E* _$ t+ k8 }7 ]& s
- echo 'I am one!';
( W! T/ ?7 H+ k y - }1 k+ W/ t! u& I" Q0 m7 l& e
- }
复制代码- //name.php
$ ]- S$ x) f+ ]7 S" l* ]( F - require_once './1.php';
6 T7 |$ b5 p ~6 R1 E, i/ A/ ?$ M% j
3 M& n* b! x1 I6 k- new Person(); //输出 I am one!;
2 r# k8 Z6 l. y: m* c9 | - new \Person(); //输出 I am one!;
复制代码 - c! v( d3 L3 y. B4 ]& |5 T1 f
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php, @/ ~: `% D, s; d+ }0 D
- require_once './1.php';
9 i R0 }4 s3 v1 L7 i$ [5 G% F - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
: h" t0 R6 _. B4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
6 F$ k( q0 g. g, i' I - namespace one;9 x5 a2 k. i" v
- class Person{
4 r4 F8 C* T0 w, S# [ - function __construct(){
+ `. O8 C* W h5 T" L- {/ w - echo 'I am one!';6 F7 C' T3 u' H3 V5 V
- }; |8 T9 m( M u
- }
复制代码- //name.php* j( S, M$ l4 C7 P
- require_once './1.php';
1 R8 k' C1 t2 n }* W5 k - new \one\Person(); //输出 I am one!;
" T: e6 I6 N6 O% T3 Q( X+ L - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 / @* [( e8 N6 N7 i7 m, V
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 : |1 I) }& X9 d" M( d
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。% B7 Y) u% A1 w1 J9 D# @! m& u
- //1.php / j, J2 h8 z' a
- namespace one;
: Q/ |* ?# m7 w* X: T8 ~0 i, T - class Person{* v1 p- F, C) |9 M4 C
- function __construct(){- J. g% m5 b/ q: E/ Z3 [0 ]0 y
- echo 'I am one!';3 F! ?9 v. g E! F. m! K
- }7 r% o: S% T) B4 p/ J5 c/ T- ^
- }
复制代码- //name.php
7 y- t0 J" Z' J9 I - namespace test;
3 L/ X5 e. A$ c% p9 q [% j7 K - require './1.php'; 6 r" b9 c4 t! y! v
- new \one\Person(); //输出 I am one!;) L, h( R, r/ _1 M: ^9 O
- new Person(); //这里结果会是什么呢,猜猜看
g7 o' Y- K& v$ M' H4 K& B& { - 最后一行结果报错:
9 `/ L0 e$ |- | - Fatal error: Class 'test\Person' not found
复制代码
6 W- L: M2 n7 V7 F3 N6 P# _2 V7 ~* c
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 9 s5 ^$ F0 g C: e
结果报错: - Fatal error: Class 'Person' not found
复制代码 2 Y6 E8 l+ H% z8 e9 [. p5 V
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php8 Q& O" g( U: ~3 D* F
- namespace test;5 H/ v' W, T; D, ]- {
- require './1.php';
$ I/ e& V& n2 [; l) {" Q - - ]' d6 Q: I4 T4 C! Q
- class Person{: h3 z5 z4 K' q$ d
- function __construct(){: Y: i9 Y) q" V2 v( N
- echo 'I am test!';" f5 }/ \% H) c) I7 p+ ` u
- }
; a5 S( w# s0 d6 Y% s6 f - }1 L& K1 X5 U$ p# ~* t$ j
- # g* l9 Q( O- o/ M2 X8 M2 A& k: Q
- new \one\Person(); //输出 I am one!;
6 U4 L+ E$ R# d9 J( F/ z - new Person(); //这里结果会是什么,自己猜猜看
复制代码
) X, K$ h- _2 }" ?5 P( w* e/ n最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php9 S6 @& i7 T) E. p- F
- namespace test;5 x3 g6 i, g! ] ?; L' w# A
- namespace one;
8 C6 x$ J% q( J/ I- g* w' b2 ?& T - class Person{
9 [9 a j: u/ R! U( x- h. B( X8 Q- h - function __construct(){
" s6 |5 j3 M! ]4 W5 z - echo 'I am one!';' V( s6 K$ h* d5 n
- }
" a, u! K# [ L" v% K2 M - }
2 i0 p; b1 [0 e1 D8 o2 s - - ^. x, Z$ X: H: R$ S* M( N! \: c
- class Person{6 U/ R4 _: N: U) i* A) L1 e j. W4 H
- function __construct(){
3 n# Y) ?1 V3 E0 S! ^; l - echo 'I am test!';6 M" @9 I& S2 I) U
- } I+ n$ F1 e0 ]$ F% `/ b
- }
复制代码 2 I/ _) u" [% x0 Q$ M2 R: z9 e, s4 m. f
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
! q; J+ w$ ^ G2 v看来简单的把require理解为替换,在这里行不通。
; a6 _- j- @5 m# c' R$ M# j6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。7 p$ W5 l% I, t. R; B! s
- //name.php8 N2 y. k: \: }( r( `5 k" n
. A% l1 O- h: k0 X9 k- namespace test\person;
6 Q6 K3 k+ T+ ~* J* G6 i' j
" M2 V* B% E, ?1 a8 Z! I0 s- class Person{
* a# a. ^) l1 |; I( v. i) ] - function __construct(){$ {2 X. a: |0 {' N
- echo 'I am test!';
0 _) M) y" @6 ]+ O" u - }# u$ K) O/ i6 C
- }# H5 _0 U a. h* c* Z% F7 B
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
0 ?4 t4 R9 P- B不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
( _) H5 Z8 z2 V# s' o ^7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
% B: ~$ P0 l% L) R# y+ M" |% n
" t: K" e& c6 \8 Z: t8 a- namespace test;
! v' n% y0 ^5 S" R$ B/ K - echo 'zhai14';% X. J7 }% l' {. j6 b6 S
- namespace zhai;
3 x& G5 B2 Q( h2 w/ n - require './1.php';
复制代码 1 g: c3 \/ e/ d0 m
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
8 X J4 {. D4 m, P' O. x3 juse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
/ \# m! b: J! T" b1 B& }- //name.php
) D6 r& q) j* \# k9 p - 8 @6 `" n+ @) W& x( ]
- namespace animal\dog;
6 v/ I4 B4 Q% D5 e
6 J$ Y! W% {8 I- class Life{
/ b" B7 m; ]5 T1 ^1 m% o6 D3 ? - function __construct(){
! U( W _* g. O! M8 f - echo 'dog life!';
. P" w7 Y9 j7 N- m! \ - }
4 b# `$ E! m+ y - }
9 A/ N ~: U3 I - : K, ? t, w; m. [4 p, B F7 ]+ P
- namespace animal\cat;8 o$ Y- j) H- `8 l- k
- 6 S& B# x5 u) n: o& S/ f; ?! \
- class Life{, ?( t$ b( R f( @8 r
- function __construct(){
4 P" c/ i; _' N - echo 'cat life!';
) s) k0 v) q* s; _- `! A; b - }
. X+ \% H7 U( e9 l Q* q' I - }# r9 p% h6 O( l2 E! A
- 9 d2 q. m$ i5 J
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间2 T; h' @3 A+ g u' o& Q
- new \animal\dog\Life(); //A
$ M' ]* A7 ^4 e% F. w% a' u - & _ |/ } W) R. X% ^0 M# H
- use animal\dog; //a N4 f5 d0 p7 ]/ h( C
- new dog\Life(); //B& H. z P9 B4 T3 _, b6 D; M6 T
- $ i5 K4 x, @5 Z& \* m
- use animal\dog as d; //b
, O8 |/ H J# |- ^ - new d\Life();
复制代码 + S( q3 D3 I) K" g
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 5 Q4 l1 ^5 o5 s5 ~, G6 R' ^8 I) [& I
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: $ o- x- E' v q& B; R! I: e& q
相当于 4 @, i4 v/ b- T' b
2.namespace后面不建议加类名,但use后可以。# \ d( o/ [; d: i O
- //name.php
5 e8 Y: D" J9 C( }0 u' ^
+ B! a9 f$ r: F* M- namespace animal\dog;
: X" x! c. q* F, V/ T2 t" | - # r8 G( Q6 Q7 k' ]
- class Life{+ q( Y; s: z5 C" `
- function __construct(){
6 T2 o! @( V+ F7 ~4 z+ B8 b - echo 'dog life!';
" m& W' q4 j+ W1 P9 ?9 C - }: `. ]5 ~5 ]! X
- }
8 b3 L# @. b9 L8 M9 H5 E - - }3 B _( U( T9 h2 g
- namespace animal\cat;- W! p& {5 n3 g" R5 R
- ' _% a+ B/ e# H; h' Q' |2 Y6 b
- class Life{7 N8 a& i M, l7 x( s
- function __construct(){! p: V( U( I+ o ~$ M- L
- echo 'cat life!';) _' x0 O0 E& u/ B% O
- }
2 [6 m c" M5 X5 }# ? C) y - }. M7 r: ^0 P+ s1 \1 R
& n7 U* @6 Q: j1 l- use animal\dog\Life as dog; + V$ s7 ]% m; {/ `' h4 i
- new dog();
复制代码 / G* g7 Q. ?/ n+ d, T
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 ' {; |9 @! A& [; w
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php4 W# K5 U% w8 {) A: {$ @
- ) o; O' E$ u" T& a/ P6 x$ c$ E
- namespace animal\dog;6 }) E' J6 S4 m0 v6 V
1 c1 B3 k4 `+ J& r# I- class Life{- }3 }) t4 Z- [# o* k
- function __construct(){1 n2 c4 _* C: w* A: ^8 t/ s/ {
- echo 'dog life!';
. e+ k/ F8 W9 I1 Q - }% M* N7 _, V- o3 A6 ]/ b' `5 ]' L
- }+ O# ?, k5 s }! z' D! W3 P) o Q6 J
- class Dog{- w$ J# h3 f% C6 o6 M
- function __construct(){7 z2 L! V, n& h. w2 z
- echo 'dog in dog!';* @$ k- @5 h* a
- }
( N/ R* k/ {$ v2 e3 D& P - }
% K1 T# d( l1 t3 L
$ e( S$ u5 f8 g8 P, J. q$ H! R- namespace animal\cat;& Y% s* ~$ G2 |6 u9 T H
, Y+ S# C! u+ V8 S$ X) V% y- // class Dog{6 g, r! M2 o" M8 y3 O, t2 c
- // function __construct(){/ e3 e$ ]" W6 U% v
- // echo 'dog in cat!';
5 q5 D8 r3 Q( ?; e( k - // }
) L: R7 m# f- j8 l! L: }$ {: g% ~! X! z - // }0 Q7 ]9 i. _, D' B6 p
- class Life{
: e2 v3 t- L' }4 ?+ w) Y! t/ Q$ \ - function __construct(){
) w# `( \$ G) ~5 N3 u - echo 'cat life!';4 f1 A* q. w2 h
- }
" w4 X# a+ i4 m - }
" p& H$ T# q+ _( G( ~# i( L5 @0 F+ y
* E+ p* Y# ?: |" r1 @; u6 q- use animal\dog; 3 C1 K. R7 Y) a" o! J5 |) k+ v. Y4 c
- new dog\Dog();
复制代码
% `2 }/ M4 T8 d2 j2 P1 B. o7 G如上,使用了 " K- Y3 C5 b+ a, x6 W
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
9 i/ w6 v+ Y& i( k简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
, h# p! E2 p& n0 y, |: C6 s5 s% i, m- q3 G
4 R/ h. X, l# ?
* C6 w* ], @; M& S# R8 D5 v# E. O8 o
|