|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
/ S7 }" X$ Y) N3 H0 l/ g" Z文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
0 d- k3 T( M2 N0 d+ v+ k5 q4 H/ F) _9 e
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
) D8 C$ {" A- ]5 }; e* u据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 0 o& ^8 z) [* p4 o- i% d
结合使用方法来进一步理解它的使用目的吧。 c& P6 v# U5 h9 X ~- _8 M. @
9 ^! h$ ?6 P7 E
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
) D! a. j# \, E7 k. q% e+ k - namespace One;
7 J" h- T4 j6 P. W3 V. f- C. n' ~ - namespace ONE;
复制代码
+ M( M$ \( W/ j1 S: ?如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
y! E8 @) r G h3 d* O9 c' G; Y2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
9 S( G% J1 x8 f" \) U, E - class Person{
' L: _% z2 B S' O$ m# Y/ F - function __construct(){
. d) W: m. j5 H - echo 'I am one!';
# H; f, Z, `9 }" C( ]9 N4 T" x - }
2 \5 v, \, H- L* c - }
复制代码- //name.php
( L7 G8 ]4 S- R9 j2 B5 v: ? - require_once './1.php';
3 u$ b" x$ j+ {" @0 I- a" H
) n) k$ W- E% c% V- K% l- new Person(); //输出 I am one!;, q6 v' I( T q6 b
- new \Person(); //输出 I am one!;
复制代码 . b7 l: w. c: k, }2 A
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php, x& C$ n8 k* n- ~$ |
- require_once './1.php';9 E h: q( v9 D& G9 v4 ^6 b2 @
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 1 q% R8 A3 D: e7 P! D& M- Z) w4 r
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php $ [1 [+ h, c) ?
- namespace one;
' n% S0 b9 n9 z- c2 V - class Person{
# R6 O% O6 Q% E! E* X- g# Z - function __construct(){
; n$ ^" B7 z, I/ K. w - echo 'I am one!';/ o3 E+ ?1 z$ K& ], H! X% n7 D! V8 Y
- }
* m$ c' S4 P0 k- R - }
复制代码- //name.php
/ a2 f$ { U( W$ x - require_once './1.php';* v# W' }! g/ \
- new \one\Person(); //输出 I am one!;
2 Y9 \8 R. q, z, R* Q - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
( s$ \2 l |1 k0 o可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 % J9 ~$ G4 C8 e5 _0 P. o- l
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
& ]# Z( U7 z! g1 _& t5 d. E- //1.php ; T& z X( @/ E1 B6 @1 H% r
- namespace one;
, r+ z/ b3 G: ~4 G; |7 k - class Person{
- Q5 V5 m4 c: {/ U1 z: u - function __construct(){
q- H9 r! ^3 \% J- N; ^% G$ Z1 n* o - echo 'I am one!';
' E$ }/ \% l% A. C - }
8 _) F2 q( L) y* h. J* f - }
复制代码- //name.php
2 {& |5 u: _' b- W: ~ - namespace test;& b* G4 W+ x8 O R4 x1 k$ g
- require './1.php'; 7 ^$ W9 j ?3 v* k4 v
- new \one\Person(); //输出 I am one!;
9 H l" P3 ~" `6 H& ^9 u8 S - new Person(); //这里结果会是什么呢,猜猜看* q2 k' |4 `# S% z( i! u+ m7 t
- 最后一行结果报错: r/ g. P& A5 B2 G
- Fatal error: Class 'test\Person' not found
复制代码
: u( a5 B2 k% H% M* G
0 R& ^, `4 Q9 i; P首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 ' d+ |/ G6 l$ ^ ?) L# `
结果报错: - Fatal error: Class 'Person' not found
复制代码 4 [* g# u/ `0 y+ N; W% J' j6 } [
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
4 `/ n. ^2 t0 x3 q1 [6 |/ N - namespace test;
! N* b" \8 z- U3 ?/ L# z6 s6 u( } - require './1.php'; " V9 t) H+ A3 T! n% b1 n3 _
- % \5 J9 u5 v8 r& z5 b4 f
- class Person{7 G: J, a& }" C" Z* D
- function __construct(){! M8 C$ x- c3 Y3 G# ~# n
- echo 'I am test!';! G' _# T2 q9 f; n/ H0 R* x5 E" M
- }
2 K) d( g& R9 Z2 C& M9 w3 M - }' ?6 o9 o) Z2 j1 t* T! f- b1 g& C
5 A0 a; m! p3 u5 {; S- new \one\Person(); //输出 I am one!;$ Q& Y3 Y5 P( Z- a( [9 z
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
( t8 u- ?! D8 L最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
: K/ h, p o' ? - namespace test;
; _: n/ w3 L) m! E9 @ - namespace one;
! G2 }1 i3 h' x& J - class Person{
4 }2 U4 l8 @3 W - function __construct(){
% R& c$ v1 Z `, M4 ^0 _ X0 Q - echo 'I am one!';3 R( ]. f; m' m9 U8 X2 f
- }
2 ^7 e- b+ L" w - }
" h# \3 D ` |/ B k1 W
7 @+ ^( M, H7 _, K0 U- class Person{
% G8 ?) s$ u) f. d5 @# a t - function __construct(){
" P& h. {- u7 i4 ]. A - echo 'I am test!';
8 V. `; o2 s9 J; V - }
8 v @, q( z* n- a& W* L* f7 M - }
复制代码
" Q/ T- e% D% F4 |无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 6 W* s9 m- K% U) i
看来简单的把require理解为替换,在这里行不通。 7 k+ }# r# f @, }9 c
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。7 q* E) a% z# R
- //name.php1 a) o, n( @/ v$ L& Y' Y: e
- - |% T @' R/ h. W6 T6 }
- namespace test\person;5 m2 ~0 s( j m3 U2 }- m6 }
`) P+ I, w+ Q ~2 C; \5 ]- class Person{
, O! B! G# w0 ~5 O( o9 s& G- A - function __construct(){
) r9 z: M# A* ?: D# } - echo 'I am test!';
) v; Q4 `% s2 f( W& Y - }& N1 ~2 e2 W! ^5 W4 @
- }
' d; z5 Z+ j) g( N$ s# N - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
4 o( @7 U$ h( I+ n9 Y7 ]' n不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 4 t j7 o# O/ B& n/ r
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
% X9 p8 s, B/ P3 J& ? - 0 W( u' v4 `6 }, p
- namespace test;
' D" d r: W$ Q: y, | - echo 'zhai14';! u: M9 E, q; d& F" I5 j# S6 w) f
- namespace zhai;" l! [) g; j- ~: f
- require './1.php';
复制代码
; r0 H; v& v* d/ D: |% K2 }3 Qphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
2 W; U j, C0 v/ O, e) kuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。8 X! R, O) S" G7 M( n/ k# u7 }
- //name.php
& K5 L( [) ]3 M/ z7 x
/ w. [+ U& x, K+ E. b- namespace animal\dog;6 p% f2 w8 R8 u1 U3 {
- 4 S6 X1 p/ k2 f5 T
- class Life{
, W2 d4 ?# b1 m' n- ~ - function __construct(){, e! m3 S; T- r) d
- echo 'dog life!'; M1 S' }1 b8 k j; x* A# w' ]6 h$ `
- }
. N6 c' ~; V; q2 Q5 ~ - }
$ v5 ?8 d k' G$ z - , W3 W- S" s1 P# m V6 q7 r+ o% N
- namespace animal\cat;5 i3 Y+ P J7 W4 Q
5 X3 E' {) Q7 E9 t. R# o- Q% k9 `- class Life{! G; `) m7 X' r2 {4 E
- function __construct(){' i: l5 t# @( R) a0 y
- echo 'cat life!';
5 W& t4 ^, V8 S/ t+ |3 X! A+ n - }
' H) C. ?& z) E% v8 E8 I3 r) p - }( k% e; k% G( N" K$ e
1 V' V0 H6 \: D! q7 A* p) J- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间+ ~* x9 L9 g1 P! M F
- new \animal\dog\Life(); //A
, j& r0 Z8 B: @) f - - o E u! l7 E3 {: ], \3 B: I8 n" r
- use animal\dog; //a: G" Z8 e0 t2 h' Y5 k4 w( |" E( V4 k
- new dog\Life(); //B
" T: i' d) ?; V. z8 O- q
3 o- s9 T6 T$ _1 d. i0 `- use animal\dog as d; //b
: u4 z/ M v) l6 e+ G* R* g - new d\Life();
复制代码
' E, N/ o4 u) Z( {9 b! G+ m通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
) `8 t- t/ O! m( J, V. P$ B4 F4 v通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 7 Z- k& Y$ s. ]% E) y J3 ]
相当于
( ~- _2 g7 `) {5 c( T1 h) i _2.namespace后面不建议加类名,但use后可以。
" B% b! Z' s! \3 A7 C4 a- //name.php
+ o' Q2 f5 H: `) x3 d& t5 h* C Y- l - , z( e# g! w: J5 B' P$ Z0 x
- namespace animal\dog;/ B6 H1 [" G2 @$ N
- $ O% Y- y' U0 V6 t: V: r+ I
- class Life{
) d4 Y' N: ~" e" I% R- n9 J - function __construct(){( O$ T' Y0 `5 ~4 m7 s( ^% G
- echo 'dog life!';$ ?6 j3 O0 z/ d' S! Q) {7 g1 F: I
- }6 j' m. ~6 R7 S L% U, e
- }
4 |0 w4 S& ]: R3 _0 ?* j# C% C
4 z8 k" l- R# W5 _/ S" ?2 g- namespace animal\cat;. [+ _: E" r# D. P0 Y1 H8 V6 ~
7 Z. I, D# m/ O/ B! \( c. ^& f- class Life{
; Y9 `4 N; x- } - function __construct(){
; {( U, F; U" Y$ P0 b - echo 'cat life!';' d. l Q8 ` G7 `% q
- }
9 n2 m0 y1 ?. h$ t3 T7 c8 r - }
2 U$ @6 O, L- G3 O& }8 W( m; c s; m - ! S6 Q4 a, _, r3 \1 I
- use animal\dog\Life as dog;
7 X5 x S$ W$ D/ K7 h( A' u - new dog();
复制代码 2 r9 [8 `3 @( Y! f
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 9 \- S& m; u% |( a% K5 p2 }3 G
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php* p' q! M1 D5 X+ o& h5 B& Y
8 _8 s$ j; i1 `/ d- b) e- namespace animal\dog;
* i, M# d0 x @" d$ c( d - 0 s6 a. w7 ^6 v7 [8 \6 |' x6 m
- class Life{& j* c. h# m* N5 B: M
- function __construct(){
& q! c& a2 u6 B - echo 'dog life!';
- H5 x: t$ W6 }0 J) `5 f! a; T7 R - }( k( q6 e9 g. G' O) M
- }
Q+ N7 p1 w+ c" x, Z4 q/ \ - class Dog{
4 B+ Y& D) B& ]* I \# ` v: \9 I - function __construct(){/ d& B {8 E/ {, p5 l3 Z3 n7 H! Q
- echo 'dog in dog!';
; V" U9 o" F" @/ F- I. u( C - }
1 Q- Z+ F3 A1 H! o, T, o( a - }8 A6 \5 q9 x9 m* B/ q
- ( X$ t) B* x/ \4 {+ T& E
- namespace animal\cat;
9 @$ K3 n$ Q+ R6 Y
3 T2 Q s, h7 r, @$ p" D. g! ?- // class Dog{
, E! v& z6 l( G' z - // function __construct(){' {# {& i3 e0 u$ K
- // echo 'dog in cat!';
3 a, F7 ~! n4 b# x: Z" J: a - // }5 M, F0 W- S$ A) V4 E- o1 e) q
- // }4 ^2 C2 `9 M V$ k$ \# G* b6 r
- class Life{& |* J1 h8 q3 G) q( x. a7 F: d" p
- function __construct(){
9 a% L( `: N$ x3 X- h4 v - echo 'cat life!';3 ] W5 O. G9 K/ `: E
- }7 U; _& W0 b1 O3 h
- }
3 e e8 c9 ?* D6 @5 ^& o& B3 c
! @3 o3 D: r9 l' B) S! Z2 Z- use animal\dog;
7 _6 G$ p( ~$ A8 F9 K2 q9 h - new dog\Dog();
复制代码
9 }+ l3 ^9 E' q& H" r) Q如上,使用了
5 b! D- {- V+ i1 k$ B* C5 D" f& b/ vcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ; w* a O/ N. ?5 ~ c7 Q! C
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 * U6 Q+ `3 Y1 s
5 Y( q6 E1 O2 m% u! d- @. H
& E _) {1 X6 Y6 t. o5 Y4 n+ R0 r9 q
m! D1 O) h8 y, V1 A1 I
|