以下皆为本人自我理解内容,如有失误之处,请多多包涵。
$ j3 p7 S D! G. h7 [文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
3 \7 s* A. {! P4 C
3 G5 e9 @* S) E. Q使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
5 T5 Y ^! p, ^! [据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 3 I+ S% J% g0 I+ s! d1 s1 e/ y
结合使用方法来进一步理解它的使用目的吧。 - Q- E) d4 N$ r: e+ e
+ F& i) ^! Q# |
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
2 D% c- A* |1 w: S7 L% j: a7 ? - namespace One;6 m& ~( L$ V2 |& I& u: [% B
- namespace ONE;
复制代码
, _' ^( N% x8 ]如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) - J3 ^, f" G( N
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
6 B6 F% V$ `$ x - class Person{
3 _; R/ T; u; [# c" Z - function __construct(){
1 U% m* H J0 T8 C% e - echo 'I am one!';
2 c# k2 G0 m: d/ W5 I; B# {4 c3 D5 _ - }
! N6 A- W1 L% h - }
复制代码- //name.php6 T* |" R$ m* N8 \9 k
- require_once './1.php';
) c' f& u0 g- e% J$ N - 3 a# }. p7 n7 _( V7 J
- new Person(); //输出 I am one!;; n$ |" n3 w8 h
- new \Person(); //输出 I am one!;
复制代码 . ?3 B2 U6 [. L% ^
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php' @9 V0 A* Z0 v& c W
- require_once './1.php';
' [- G0 m! P3 Y0 x! c( J% L - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
4 L8 i5 ?# j5 q" C4 \' T [$ j @4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php * G3 K8 ^. N3 G" l# G# T
- namespace one;" \( b! _# a2 r. u
- class Person{
8 d) t2 G/ q5 d' G - function __construct(){0 F$ n" @% i. G6 Y! u/ C
- echo 'I am one!';
+ T" A [0 u6 X. _% U - }
' u1 X# E8 f' J2 }1 f+ x5 v! O M - }
复制代码- //name.php
( J H" t3 K; L, m/ h2 y4 | - require_once './1.php';
" ]0 `; M" A- H4 x: Q4 p4 T0 g - new \one\Person(); //输出 I am one!;/ D1 w" R8 k1 ?3 l( W
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
3 c) l' {! v; t( Z# @+ F; L可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
+ \7 b# c) h8 K3 O6 k5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
7 d" W$ v, }6 a2 [- //1.php 7 k" O4 @: _: E4 ~2 U9 _" x6 a
- namespace one;
& n: o/ b5 x! V) X! R8 e) c R q - class Person{
2 Z1 A* r1 J% g+ c- S - function __construct(){; B) }' W M( l
- echo 'I am one!';
% g. h* {7 g; E! L& ~0 u. a - }3 [1 a+ s% w: n# {: m
- }
复制代码- //name.php- Z, \2 `9 n; h
- namespace test;4 n0 p! A! T0 S5 S+ r/ I
- require './1.php';
+ T* O o+ g. c7 |( a; E - new \one\Person(); //输出 I am one!;! Q+ R5 q' _8 f" ^8 t
- new Person(); //这里结果会是什么呢,猜猜看! K/ y+ @' _( s4 C e# e* F
- 最后一行结果报错:" E% x5 v V3 q
- Fatal error: Class 'test\Person' not found
复制代码
- c) P: u1 ?/ C, C, V6 X# \4 n( C
$ H5 F2 Z1 H, y; S% W首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 . w- J. T( ^7 O+ i5 P& \
结果报错: - Fatal error: Class 'Person' not found
复制代码
q* D r9 p" L% k7 g5 n接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php2 E) d# c/ ^0 Z+ R
- namespace test;0 h6 ~; J" ` |# o; a8 i
- require './1.php';
2 d3 \% g# @ i$ Y
& |/ K+ k6 I( z5 {3 M" a: @- class Person{
: E0 l, ~: R! |8 ^! i, V/ t5 I' ~ - function __construct(){
# i: h* w, [+ d' n+ N - echo 'I am test!';
* h" z4 x6 C' `( @3 c - }
: ]8 S% a% F* F; @7 o4 Z" f - } J P+ ]$ P, l( g
- 6 Q. z7 x% O$ ?$ Y. c2 ^, M
- new \one\Person(); //输出 I am one!;
0 I1 H4 j0 h, h, `! Y - new Person(); //这里结果会是什么,自己猜猜看
复制代码 5 D) n6 D7 [/ [- A% N- C
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php; V% e, o3 h/ k! ]' a4 c, H
- namespace test;
- M8 H0 X }/ W/ @, d - namespace one;
3 I! B& {. j8 x$ O$ L - class Person{
; [6 [% R1 ?: B, F3 K* w8 M5 A - function __construct(){+ B/ d1 }: u- b2 e% e, L7 F! L2 S2 ~
- echo 'I am one!';
, X& _. C% a3 |/ e6 E - }
: p; m. r* X2 h/ D8 d - }
' g# H5 O& g* V) O U
) m/ a. X+ T5 s( | W3 s% ^- class Person{
2 D) u5 l8 _1 D - function __construct(){" Z7 T+ s8 D% _6 X
- echo 'I am test!';
% P0 X9 n8 ^! C - }
0 {/ g r: t& W# J2 |/ m - }
复制代码 % B) ?5 y7 H# `6 m0 J6 ?! a
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 1 f" {4 y1 | J) R& Y, i8 C
看来简单的把require理解为替换,在这里行不通。
& ]! D% o6 i! {. D5 U6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。7 H5 @$ ]" v- u9 w+ B
- //name.php) k' X K+ P$ ?; u3 r& u0 [
- - w$ w( i2 D% s5 }; L
- namespace test\person;
6 F- q3 I+ S0 p - # x; j) X+ j. ^, l6 T- g
- class Person{
x. a8 S. I" M9 K" `' ~9 f* U) Z - function __construct(){6 D2 E# {: T! y+ ?
- echo 'I am test!';* u4 K6 r7 ^8 [/ O
- }
2 H) T/ S! j! p - }# j6 q/ j+ _/ B! x7 a" ]
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 " w* i' K, z# B. P7 x
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
/ X. d( u% Q/ }7 Y3 i7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php4 w2 e+ ]6 e" w1 ]0 h. `
- " U8 g* M% L/ I& K! J7 E. Q) Q
- namespace test;
* k8 S. L0 V- a8 t6 W2 M - echo 'zhai14';; |! l* a A( j- N- h+ r- K7 c
- namespace zhai;" I/ O! {3 n+ c0 l
- require './1.php';
复制代码 . R# r, w9 q& v8 _$ [9 w- i" k
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
0 X/ L* u) n# o7 U4 tuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
2 y$ \" @! ^" E* P. b- //name.php4 x4 Q; G u. R! k+ E. t
9 G' U9 G! Q( ^ l. ]) S- ?- namespace animal\dog;
. \% |% a, ^: O. n
: ~% a$ L) x9 S: G4 r- class Life{( q6 r d& q" H C5 f/ M5 n% v7 I* c2 j
- function __construct(){
" a; w4 ?' S7 }* S, C: B' j - echo 'dog life!';3 ^# I; D( `) j/ D9 y: S
- }
" \$ n- n8 u9 X, Z" y0 M( S - }8 O$ f! ^0 W" L0 G0 O6 r1 P0 W
- 1 V! o) O) R- ?. d6 k' D! ?5 |: b
- namespace animal\cat;- u1 g) G6 { s2 p
- 4 O& `; p% ~* j# @: s
- class Life{
7 ~1 s$ a2 I, W5 b - function __construct(){
$ J* S3 n1 z6 B - echo 'cat life!';1 k8 F# l9 |1 R, d+ F; P
- }+ U- q* v/ A3 W9 R$ P6 z
- }# Q# h4 a9 }' s" p
x( g, L; y& k) H* t, n8 ^/ t- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间8 `: V( `% _1 T [4 N" F) s( P
- new \animal\dog\Life(); //A* K7 F* B: X% M s
2 y; M, e3 K, D2 I- use animal\dog; //a/ C& u0 M1 R# |0 r+ Y+ K% x4 m5 @/ x
- new dog\Life(); //B* z. ^4 m% P2 r! s7 Q4 |
, ^. X! _! n- t; f, i! Z5 j% O( v- use animal\dog as d; //b0 @6 p% k% x6 ~: k; S2 Y( }
- new d\Life();
复制代码 5 |6 M- g1 y5 Z! g) \+ t
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
0 j0 p' o/ `+ Y% m7 K' C通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: ) b, f+ g, y+ A- g0 k9 g; \: F
相当于
1 c2 x c. F5 z- r* W+ e7 O2.namespace后面不建议加类名,但use后可以。# r8 H" ]- B( [9 y( h6 Q$ V
- //name.php9 W9 r `! Q( j
- 9 W" _! V5 I p' X1 O* A
- namespace animal\dog;) b+ A& [$ T* r
- + L5 K) ^. T- h9 F; Z& r; w
- class Life{
0 U# ?( x/ Y5 W. z+ _9 ^9 | - function __construct(){
$ Y1 `7 A8 R2 q- e1 T! ^ - echo 'dog life!';! u8 `& `/ z5 p" S1 P7 y9 `
- }) b0 R: c3 l- h% X
- }6 h9 L O+ }$ B
3 t7 B0 m o2 W( K2 m2 T( L c7 B- namespace animal\cat;
5 K, Q, v I0 o - + X1 i" L& B% A- b5 |& U
- class Life{
6 o- ~9 r! ?4 B/ B, l) }: } - function __construct(){
$ \; T& I0 x$ J2 [: ~ - echo 'cat life!';
1 b, b; ^" z% k" U( d: ?% f - }1 r0 ~0 w! H1 ^( z9 U( p" W
- }
6 N, w" ^; L, |$ l, S. y% Y: h
+ i& {8 w% X2 }, Z7 g$ C- use animal\dog\Life as dog; + ~. A) r! @5 `
- new dog();
复制代码
2 m5 Z, t! x* Y, D7 k9 R如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
' n" A( p! P6 i! D# l$ {" B, T! [因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php4 r# n- O, S B# ]) ]
- 7 c$ P& v1 O3 x a$ [4 U: p1 n
- namespace animal\dog;( { x+ f( z/ \' X1 R$ j( `
9 W9 Q7 k- N3 |# J$ f, ^' T- class Life{
- l9 C) _) ]! T( j7 S: F: l - function __construct(){; E' A5 T, O& p9 U8 M# L
- echo 'dog life!';" Z. f; Q6 b7 J7 Y1 S" v: N
- }
, y* t8 J& h- b! v9 v - }) B& x }1 J0 G; x
- class Dog{
" O3 P% G# k: ]+ r - function __construct(){9 D# I0 p$ [% {6 J3 I5 T% m6 x6 y7 ?
- echo 'dog in dog!';+ _+ o) H! L* U5 N2 K Q
- }
e4 C+ M, a6 l - }
+ u( \! M; x# x6 Z6 \( L
7 h, x/ \8 ~4 P0 H# I5 I2 ^- namespace animal\cat;
3 w" m, {( j0 b7 u6 a& U - + Y5 Z4 I# }3 X6 c4 ?/ @
- // class Dog{
" x5 v1 g% Q9 j, l9 a! g+ | - // function __construct(){
/ s8 F2 x7 |! @( L" e - // echo 'dog in cat!';
* J9 X% z2 Y( R/ G - // }" x2 ~2 `7 Z C6 X; R+ r
- // }
7 Z0 `; e! U( H, p( l5 t! L - class Life{% \9 t/ e5 F1 ^9 f8 p, `
- function __construct(){
2 G. ^+ v1 c1 E$ T6 t2 y - echo 'cat life!';9 Y' j3 y$ N( X
- }+ u/ P+ {" J7 ?) w" N
- }
& q* ?" n1 J- B+ E' s
, p+ O; ]" ?! a) I3 M- use animal\dog;
6 w8 x% u3 m" x - new dog\Dog();
复制代码
/ A% d5 Y, _0 Q8 Q* d5 y如上,使用了
, q7 a/ H1 u1 Q7 F2 acat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 0 H9 @4 M$ t8 t
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
7 t3 a- n5 W6 T O0 C8 K8 R9 s4 B( x' x3 P
3 {$ q% T8 e. f1 Z+ k( b
1 @% y* d/ N* z% Z
p! v6 D' z9 j3 M0 I [% I |