以下皆为本人自我理解内容,如有失误之处,请多多包涵。
0 b+ q& @- Q1 J8 K: a0 c, j文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 2 _, l T. O/ u
0 n! V/ G% R& n$ k, c2 ?
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 1 k+ G0 z. I, q7 K) y5 s% i3 j
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 1 N1 H9 a) ]0 n3 F% r
结合使用方法来进一步理解它的使用目的吧。
8 b9 N8 J# s Q' x
; T1 z# ]1 X+ ?/ V5 o( anamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;, F' J1 A0 n# x& b f
- namespace One;
" \ H% Y+ Y& ]( S - namespace ONE;
复制代码 |# k, {) s+ P9 |; B! s
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 1 S" ^- m: q0 y }9 `/ U
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php / D5 Z! z# V0 e% @/ r/ f) u
- class Person{
( P: g0 F/ ?0 A" s - function __construct(){* o3 t" t" C- p# ^- l
- echo 'I am one!';
- C6 n0 i: G' J' m - }. z ]0 {2 c9 A. S% Z2 H c& ?
- }
复制代码- //name.php
* Z6 q) K& {5 T - require_once './1.php';
; T8 ] B& t) Q/ F# T! Z
2 \+ L) H( p/ y% @- new Person(); //输出 I am one!;
. g% R& L$ [6 q- I& x2 ~ - new \Person(); //输出 I am one!;
复制代码 1 O. r9 a8 Z' S+ ]
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
' X9 }$ ~% b$ z) j; @: x% E' m - require_once './1.php';0 H, u2 p3 C+ a
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
- @/ M# Q$ `/ n/ N5 X3 {4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php $ C0 D, y% E/ G/ g. [: w
- namespace one;
4 D% T8 K) Q+ Y4 Q) p& |5 j* W# \ - class Person{
2 P* ]+ o; G1 \# N" @# i - function __construct(){
4 q0 w4 U- q3 s- t/ h. @; z - echo 'I am one!';
z+ B5 A: n. s3 v1 Q" R: E* f: Q - }8 ?) A- e9 U8 L: M
- }
复制代码- //name.php( E( P8 \2 e3 v4 R3 ~
- require_once './1.php';
2 ] r+ B# [+ F; j* ^6 J2 t - new \one\Person(); //输出 I am one!;/ `0 q* N* ^6 w5 P( L ^! n5 U
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ; F* v% `: x' X6 _( ?1 e
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 + K4 u3 V% c' j- ^# l K4 e: [' k
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
6 [5 |, a, X; L6 a- //1.php
9 X2 G+ T: x' S- j - namespace one;
7 a5 [/ a+ y/ W( D - class Person{
$ D0 T8 }3 ]+ e' b8 G# L - function __construct(){
0 }1 O5 y! G3 {8 X - echo 'I am one!';
) A+ T! d9 C) l2 ~, w. M - }
6 H2 E& `2 Z. ^+ i/ D - }
复制代码- //name.php8 M7 j0 Y, R1 P2 O0 ?
- namespace test;- Q2 I" q! m; o; \9 M, F4 A( G6 k
- require './1.php'; 7 o0 a }+ K, K8 o$ q+ C4 K
- new \one\Person(); //输出 I am one!;
2 @- k+ y$ g! p; o4 O - new Person(); //这里结果会是什么呢,猜猜看3 ~. J/ l3 K: g
- 最后一行结果报错:$ e* s8 a. n" s; |( W
- Fatal error: Class 'test\Person' not found
复制代码 : J8 n$ ^2 r2 M; m2 N- M3 Y
, @+ B# |0 z& y2 z' t. b0 r* G/ o& b# V
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
& D5 R4 `& f, f6 o/ O# H8 H结果报错: - Fatal error: Class 'Person' not found
复制代码
- S* W8 A: ]: o5 e b& C( L$ q* C接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php: m3 Y2 W! ?2 h; ?
- namespace test;; m3 v% q2 Y/ l# v
- require './1.php'; 5 u+ D1 O Z# q1 e5 H, z
- $ }7 E5 {- b0 v6 Z* I
- class Person{( Y7 Z `. r% e+ C. r% ?
- function __construct(){! w/ d) Z1 d1 s6 \- y7 m6 i, X$ F
- echo 'I am test!';( O$ A( s' q" R; z6 ~
- }
& u( c+ d/ A4 L& O - }
8 v1 t1 z( s: o- a( u1 T4 ]
0 i: K8 M7 G) u- new \one\Person(); //输出 I am one!;
8 G0 |+ o# `: k3 w% M - new Person(); //这里结果会是什么,自己猜猜看
复制代码
% A% Y- j6 n8 v* x3 S最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
. d2 x' S6 q9 {) p+ @ - namespace test;
- c2 C9 S- E l3 E. N" n3 r1 t - namespace one;
; W% K3 t" S- b3 `" o - class Person{6 @5 Z: p( h2 O1 o- x2 l
- function __construct(){
! e+ C, V8 y( a. Z2 G - echo 'I am one!';
8 R5 }" L6 X$ P' G5 P- | - }- m& R x6 y8 a
- }
T7 i a. A: L) v$ z - , A- L7 n, J& ?. u
- class Person{
1 `9 C( ?4 v& j. q5 L5 T5 Q5 k - function __construct(){
( f+ S- v' Z n* \( M0 u m. B - echo 'I am test!';" E2 q: I9 h1 a7 T% E6 l' I
- }
0 G: v+ [5 Z0 `5 b& I2 W( W1 S - }
复制代码
1 U [+ F3 ?9 ^% F4 X# P无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
! C& r1 q2 x) U看来简单的把require理解为替换,在这里行不通。
1 w, B0 j8 d& g6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
K- f8 B8 J6 D: F' w6 E/ `# L- //name.php
8 l6 v6 {) E- t3 ~$ {! I9 u* k
) H3 b* H5 ^* n& Q$ H5 n0 S, A9 q, Y- namespace test\person;
6 Q% V3 s- ~8 n( N- ], ~% o/ j4 a3 \
" [1 `. t% l7 t- class Person{7 V/ o9 U$ Z- p
- function __construct(){
1 w( [; v% n* y% q - echo 'I am test!';
8 g0 d$ A% f% V% [& P9 `+ h - }
- X1 ~ ?4 s* E7 Z2 V: G) `5 N" M - }
. ]$ G4 w6 R! A: j3 [* v - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
# G/ L/ f% D% b6 o" E& {% p0 a不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 : F$ k5 o& F& P5 t- z5 H( L& t: ?
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php$ ]4 X9 x/ ^7 u' n2 {7 y8 K
- 7 H: ^) U3 s2 v6 ~1 W% J
- namespace test;# _+ `9 M" |0 f6 P
- echo 'zhai14';7 }3 s7 Z! R$ v4 v% Y; U
- namespace zhai;
5 U8 j+ x% x5 N9 t, |$ [) b/ Z - require './1.php';
复制代码 % l' S+ k, k m: x
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ' @" }" Q8 d3 ]
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
# m' K% g7 \3 C" [- //name.php1 S$ i: X/ c6 M7 y, r
# H0 C8 ?5 c& ^# R/ J. L, u- namespace animal\dog;
8 n* F ]! \+ n% h* q' W - 5 @3 h0 k2 G# S9 Z6 ]
- class Life{4 H( O1 Q$ ` c8 n0 C* d ?
- function __construct(){
" N% Y4 y8 ]/ D, G2 m - echo 'dog life!';0 ?% U6 Q% V; B3 G
- }
! G; r. E/ q* R7 S7 K/ S9 Y - }
7 a o0 c* S. Y3 ]1 ?9 w
0 z+ n$ R" f9 J4 l5 H7 c- namespace animal\cat;1 h+ P6 F( C2 r& ~
- ( N- E G$ s9 o* p% k/ `
- class Life{. S0 F! N& h; M: ], @0 a
- function __construct(){
/ K7 Z6 @* z6 H& n) J9 `' K - echo 'cat life!';
" p3 t1 R9 |7 t, z& o - }6 {; X' O$ }2 F. b& \ t
- }4 R# J1 J. k l8 ~- @
( H9 C5 a7 V2 E- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
% k: P" K& l. H- B6 r6 A" d- o8 U( s - new \animal\dog\Life(); //A1 ?" F2 G4 M" o2 y
- x7 Y7 F- o! [/ J y- b& X I! i9 K- use animal\dog; //a
6 n W% e' T: r# M8 M1 [. L& G - new dog\Life(); //B" k0 o( I& Y$ ]7 Z$ z4 H
- / E* x9 f+ h% N9 r# x
- use animal\dog as d; //b5 S1 |% F& r B# o# \
- new d\Life();
复制代码 ! y# B5 c2 E) t! @$ d
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
. A) E/ }1 \5 ?) s& v3 p4 F+ W/ F通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
1 M4 U: p, v: [( c( {+ L& o相当于 , W# u; s6 | e, J8 d- X
2.namespace后面不建议加类名,但use后可以。
3 j% E$ B& }) G& y- //name.php, @% R) M7 G/ m( K/ q, g
- ! a% F1 i+ Q( S+ _' A3 B# b
- namespace animal\dog;* b) \5 m' \+ Q% D
3 x. k1 U, A3 G* H- class Life{6 v0 N3 Y1 k. E; d- u% L
- function __construct(){
" n! E" J3 c$ F9 L - echo 'dog life!';, M2 [) y1 ?) r8 R+ v% c
- }
! t3 ^7 I) w% i6 Y) o8 G! j& t - }2 n( Y8 C* M6 q2 T' x
- G; s O' X. m6 i: V+ B- namespace animal\cat;, L1 w3 i8 N6 I( R9 W. ~/ e1 c( s& U
2 m0 |* |- ^! O% p8 O- {' Q$ _- class Life{
" F. D+ r1 {4 p$ d& |5 L - function __construct(){' [; E' A# V5 ^# d0 n
- echo 'cat life!';
K$ @6 M9 W$ M* V9 K. h - }% v$ d, i) q s6 ]1 t( k
- }. P) E* e) j; _
- - a$ n' [& n, R/ H! m
- use animal\dog\Life as dog;
4 V3 }, J( y9 H- u - new dog();
复制代码
1 q* `/ a- }) m" [) x如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
3 Z% _0 t" t0 E% v8 K9 c n因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php- s* \8 _5 `" M+ j
- U5 M9 o" H' x. i! W) X) |' O- namespace animal\dog;
+ `. f' t7 x* c# I+ B) ~
! ^* P( }6 N5 m' J- class Life{7 O. b$ Y" A- V! q" _8 r
- function __construct(){0 {/ h' [% V- |. i: v* T& _
- echo 'dog life!';
, g* }/ u* Y0 f5 t5 l- n* a - }
9 V3 C+ \7 E) D1 N# c - }
8 b# k# S- R& l- o% P3 F. v - class Dog{. z2 u1 r6 M% y7 m0 Y2 W, `
- function __construct(){
9 S4 A" `( F0 F+ t% y - echo 'dog in dog!';
0 Q) `/ j+ k+ x) J2 r+ }1 g - }
( k3 y9 v+ }6 M5 R! A- z - }" p6 u' E. H( N5 n' m! J
- $ s: X h) q; f! U$ e' A: i4 e
- namespace animal\cat;6 p+ F" M) G1 R0 M
- % _9 y& H* P8 ` m0 x
- // class Dog{2 m; H$ w( K3 ?" [0 d3 Q# p7 c7 ~
- // function __construct(){1 P5 M5 p/ {2 P, g$ G t! ]
- // echo 'dog in cat!';
5 j$ B2 k2 F0 F$ q9 J$ Q, ` - // }
) L' t) r6 W& j+ T - // }
: ^8 o. I9 S% ]; d# S6 G- D - class Life{
+ S4 N. P# R6 f! K* M- X/ P - function __construct(){
4 E7 Z6 f4 ^) Q! g' n4 O; X( Y - echo 'cat life!';
& E9 a9 U, L; I9 l# B; P - }
. k' `/ D$ z3 N; `, x - }
/ c6 t% F0 h: z* v/ x% l" j
% D3 k/ C# x6 q4 c$ n- use animal\dog;
8 P# c0 v* c* B - new dog\Dog();
复制代码
5 J3 {9 I3 o- U2 M) R( C如上,使用了 ' \9 G' ^2 v# f* ^. n$ o
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
* A1 ?" v( J, z2 z简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
% M, _! f+ j# o5 h* K
2 z: p7 `5 ]% I) w$ s. q: d. h9 ]2 B
1 w9 ]8 f! w [" R9 Y
0 G& n7 s4 ^# X* a" ^: }4 ? |