以下皆为本人自我理解内容,如有失误之处,请多多包涵。
+ S$ u8 _# ^. F- E* L$ A: `! W9 C文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 : F5 V l! ~9 F
! d( e0 x! ]4 t# Q4 t' O使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; ' L$ Q2 Q( Z, V& F) w! n. z- h
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 3 }0 M) w- ^' [5 g" ~# B! _* Y6 K
结合使用方法来进一步理解它的使用目的吧。 ( q" r4 H& T+ \: S( @& R5 D
! l( I. s1 D5 Bnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;& Q. O& Y$ Z) K9 ]6 L
- namespace One;
5 X3 @& k+ l3 |; q: \ - namespace ONE;
复制代码 / h4 L% \3 v8 W- `/ U% K1 v; ?- e; O) M
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) + s8 L6 I/ T0 E+ U: }
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php - E" t4 N8 _5 {2 M1 N/ _0 \
- class Person{' K f7 P9 g0 l% }6 P! U0 m# [% c
- function __construct(){
0 l3 D9 T6 U: g1 c - echo 'I am one!';! `* j% x3 ]: D% x9 n0 O) i; b
- }; E/ Q: ~- p% r
- }
复制代码- //name.php# H. k5 g: D" b2 \) C
- require_once './1.php';4 ?5 R: F- S! N6 I. c/ P) F3 ~0 K8 {; s
! v; u9 D7 k5 F- new Person(); //输出 I am one!;4 ~2 s. Q# s6 R- `# ]4 R
- new \Person(); //输出 I am one!;
复制代码
( o$ h$ z- O; W! ~3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php8 Y; C0 v8 g( l& T% F" b: j a
- require_once './1.php';. ^: p7 d1 d% B# \
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 4 f4 q) o, E" K# w6 W9 `
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php - R+ x( \. b' t: N
- namespace one;
% v! {7 g4 T" ?! B2 M5 N J - class Person{
8 L3 B) w" p: H& v2 o' U - function __construct(){! E4 j8 ]% l' c! T$ g1 K+ k; J6 m( p
- echo 'I am one!';
/ u( f$ F) i. v* G6 @ - }
; V2 g2 W. }' ]& c V - }
复制代码- //name.php5 O2 N$ j; w) X) |) V9 q
- require_once './1.php';
# w1 x4 P' O1 b) H' T - new \one\Person(); //输出 I am one!;1 f3 x, X/ ?6 ~- O0 j( U3 }
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
+ h" C7 [! y$ B I c8 R9 _可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
2 [' C7 n! R: ^9 n) T; j# H2 c5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
* Q9 n7 B: N6 R- //1.php
- I9 ]; a2 L4 s: k - namespace one;, j+ X8 g2 f# V. ?0 ?( P( q
- class Person{
! ?, m' Y" \7 P* q+ ?. h, X" @8 n - function __construct(){0 m7 {3 d% y/ L1 p0 N& \
- echo 'I am one!';
- K. v7 l4 m7 j! N - }
5 ]! q$ y* Y) l8 f% \: o6 H( D - }
复制代码- //name.php( |+ s' c6 K1 \: O- U
- namespace test;7 [" y' G* V2 j% q$ Y, Q" y
- require './1.php';
, t# P% _: `5 t Q# U - new \one\Person(); //输出 I am one!;
6 Z. s5 h2 g, F* }6 A2 { - new Person(); //这里结果会是什么呢,猜猜看
5 E3 t3 q; y/ K5 C# ^' J O - 最后一行结果报错:
6 g3 a1 K" K0 X# U, V - Fatal error: Class 'test\Person' not found
复制代码
( H" ^4 d2 N7 I* r! c; k$ _
6 e V; P% ~7 U首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
$ E7 _) p; |( v" W0 d结果报错: - Fatal error: Class 'Person' not found
复制代码 ( X. [! ]/ v& S7 d8 s7 w
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php- U. [# n/ C Y3 C1 A" i
- namespace test;) A7 A _7 b, W- n9 k3 I
- require './1.php';
4 A- @) ?) Z+ t* l+ o5 z0 l - # ]2 y2 V, U" R& _
- class Person{: r/ @( `4 z. f4 q7 w* Y; \
- function __construct(){& g" K, |6 }- o
- echo 'I am test!'; U1 y, f7 M( Z, \
- }+ \$ U3 @3 H+ S
- }
/ ^: _# O( ?' |1 _5 Z - - {: j, I/ J( Q+ F( v
- new \one\Person(); //输出 I am one!;
) U& Z0 w2 _, s; H# M - new Person(); //这里结果会是什么,自己猜猜看
复制代码
2 @1 A3 d. J) A9 ]9 k) }7 z' y最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php( W0 k8 P9 F6 U- c1 @
- namespace test;
; U2 u$ @ x3 L( t d5 H - namespace one;
% y9 k1 p E j) } - class Person{
' n" n, N9 [, r A7 B - function __construct(){
, F4 U. j* B6 K) t2 T/ ]+ Z - echo 'I am one!';
( Y- S/ {: ]0 v8 X8 e - }
2 I4 F' O( {- f: L! o+ H - }& I# [$ C. z- s% g% U% U+ x s
$ y7 Y' D$ C5 H2 O7 P; m/ D! M& T- class Person{; ?, {2 { `; r% [ l' I
- function __construct(){
9 w$ U8 ]! N% e9 R! `) g5 D0 @( L - echo 'I am test!';; w5 c/ Y- `! S& j) i
- }
8 |* d9 m. P( [2 P# \ - }
复制代码 2 O( u) H# e) o0 ]3 K6 K0 w
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
5 j; ^$ g, l B2 c3 d1 E) E看来简单的把require理解为替换,在这里行不通。 - F, l5 ~; B9 H4 r2 j# v" x
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。+ Z: C. z$ V1 Z S3 D% q! s- ?/ u
- //name.php
6 H* _3 a% o$ q6 Y; T6 i v
5 c5 ^! p+ B4 j% N4 {- namespace test\person;
% x0 o7 O3 b0 s' {
' s* G( I. F* s D4 K: g4 y% n- class Person{
( i0 g3 k; K, y! b - function __construct(){' o+ a+ i2 t6 E
- echo 'I am test!';; P/ v7 S% i7 q7 s9 }) l3 P. [
- }# i2 y$ X. `+ Z' y- V
- }9 ]! p: t, F+ t
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 9 g/ N5 X, e* Z z3 M& ?& ^
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
$ q3 N8 v+ H, d2 H7 ?! t/ m$ ?; \4 ^7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
0 X/ a! N. J% W# Y# }
7 }& x# x1 ^: R# O5 r- namespace test;5 A6 h$ @9 A5 o5 i( R
- echo 'zhai14'; _) M M1 g5 ]& N( v
- namespace zhai;
/ U% i9 a: u+ S5 P' d - require './1.php';
复制代码 1 B, ^. E3 U0 ~9 O3 ~ [
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
6 T/ R6 h- D! C5 kuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。: j7 ?- T0 x% K
- //name.php
: z% f- M9 P5 A3 n* z. Z% D
- [2 r z9 S& n. a1 |" x; b- namespace animal\dog;
T, z' p9 I3 E3 [ - $ ]4 F4 v2 y# C# J* E' ^* B, ^
- class Life{$ {* N |6 K( R8 V
- function __construct(){' b3 I, k* s3 h9 \
- echo 'dog life!';0 x* b; _9 ~4 J8 x, d$ _
- }8 q3 ?( R& ^1 l3 K0 E* A
- }& G1 w8 K+ Y$ ?+ \2 Y! {
- 0 t& F$ {1 ^5 H$ k3 J- Q. H
- namespace animal\cat;
+ L" k' s1 W1 c4 e
/ E* Y* L1 g7 D3 ]- class Life{
# ]% K( h [) V8 N; s2 \; W - function __construct(){8 `1 I V+ v+ v/ p1 o+ i+ Y! w( D
- echo 'cat life!';
+ \5 ]. M* @$ ]9 r8 W; q - }) i5 k& {, y6 e$ x: z+ G/ I8 \
- }
& o) V& R8 w$ d- |5 M1 y - + A; |9 t( j+ f9 D' z$ f( A5 g
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间" G: b4 Q) x% G
- new \animal\dog\Life(); //A
1 [$ Y3 c0 n! O" ~6 b+ g. I - 0 Y4 F) F; [6 R# x6 e) D
- use animal\dog; //a1 Z1 v) J/ G) n6 u9 z
- new dog\Life(); //B& z a/ S8 \( m" [; b) ?8 L/ _0 P2 G' E
- R; Y( `7 R+ L- use animal\dog as d; //b! q# l# _: ?! Z0 w, E
- new d\Life();
复制代码
1 V" {3 j. ?. i Q2 I/ z6 e% q, i通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 ( [1 t: k: T3 J2 B5 b+ {
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
& y+ s( u+ |- Z3 V5 u! t7 Z0 |, |( V相当于
: @: R$ @. K2 T. d ?% O+ M2.namespace后面不建议加类名,但use后可以。
: a2 r F( ~( c. [- //name.php; M. m' a" v1 E- d1 u S
3 P4 e% _- U5 n9 M3 s- namespace animal\dog;
# q$ u1 f; p% F* E3 s/ Z
, P: c g3 u% X+ E+ p- class Life{
; }' d" t# C L* T7 J3 `4 z, v - function __construct(){6 E& I) S( J* u1 M' U5 h; S" I
- echo 'dog life!';
- O8 q$ o# z- u* k - }. P* D# N7 M. d8 q7 _. E
- }
0 }1 R8 W; r/ g8 C - 1 Q6 S7 R& g0 d* n9 y
- namespace animal\cat;
5 R' D2 ^4 w2 t+ o
5 _+ q- J/ e9 F3 u% ~; X- class Life{; }. F/ S( I! A: d5 @8 n8 ~/ L; y
- function __construct(){
' O% C5 g& ?+ N( j* |, C0 | - echo 'cat life!';4 t$ v6 T; o+ N" H0 i& m
- }% I1 g9 J; H, `* L( P
- }
; o2 D! T+ I6 @/ g: O9 b7 G
5 N1 o$ H6 A+ e2 T- use animal\dog\Life as dog; % c: f+ d. t1 G8 X& L! W0 w8 e
- new dog();
复制代码 / {1 }1 W3 w" r& D/ c
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
! J1 P* E+ K- N+ {* \因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
; @9 \3 F+ J7 {3 }
; r* `3 Y% k2 F' v }/ P- namespace animal\dog;
" n8 w2 ~- @! I- c0 g3 h0 M# |
7 n0 o" |: [. v3 [7 ]- class Life{: b" E+ r! j3 Q7 C% t( _" W
- function __construct(){: s, P% B9 f) v4 ?, l# m e
- echo 'dog life!';' w3 N2 f( I# ~/ R R% G
- }" c% V, E9 ]0 s6 D3 ^
- }
+ N" S0 v4 e/ [& m: @ - class Dog{
1 u' f% W+ u; r- [. g" `; w - function __construct(){1 w9 s9 E( k3 D9 G& h) U
- echo 'dog in dog!';, r# P9 y/ r: h( Y6 o
- }
. p9 P- O1 B$ N+ s$ Y2 l - }
. ^0 P/ x) p% h, L
8 J" g) v" u+ i7 W$ S6 _- namespace animal\cat;
& d/ h8 Z5 X( s( Z8 |, x0 t
) V% ]: a8 B5 C m* R2 q- // class Dog{
7 ?" f, O$ J# q w% N6 d+ s - // function __construct(){
$ l' X l) G( r0 C% o L2 G, W3 O - // echo 'dog in cat!';9 T! s3 e" x1 C$ B, D" U
- // }
# @6 d* f* W1 p8 e7 b - // }1 ?* ~1 {) T: x/ X6 G8 h
- class Life{* g8 Q' O5 H6 u" J# w
- function __construct(){+ P/ M' W8 R. Y9 H
- echo 'cat life!';2 l" y% F1 Z3 c+ t. q
- }# H" K0 C9 G) P; r {1 Z$ }
- }
# V( k7 v$ b6 q9 Q3 }8 u" j* E' j- d
g$ B% d9 t( k5 u$ i( U e+ i- use animal\dog;
; g5 ^% ~( O5 s2 w- Y1 T - new dog\Dog();
复制代码
6 ? n! x: g; k# T4 Q0 A8 i如上,使用了 3 E }* ]" F7 z
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 j) X0 S& [# `+ I: F$ p
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 . ^' X5 K- E' a4 }5 Y
( t" J4 J D" n3 n# G& R7 z! t- V8 U g# c
9 L M5 I, ^& S$ T* w, v
( m: M8 f) n, f4 n. m0 p
|