|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
& w6 `8 o8 Q4 F( D文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
( t. F6 ~4 Y! N& e2 Q& k2 b& H% T! p; e1 ]
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
6 }0 A0 N0 o, a' K% f据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 2 D% y/ v. Z+ f i; h( }4 Q8 O; ^
结合使用方法来进一步理解它的使用目的吧。 2 O3 h5 _# } e' C/ k3 F
8 |( k/ h1 e0 G+ g
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;( L F; m% B" {8 f
- namespace One;* H0 A0 M& k2 S. J5 d
- namespace ONE;
复制代码
1 V% q" A" H K0 P0 J d0 v5 ^" X8 A8 A如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) , M% G$ B9 h1 P- P$ T2 Q- W
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php ; ]; S1 Q) J- E
- class Person{
$ m" l) l0 j9 P( k, ]* c$ u - function __construct(){
0 \% P! s( @- N4 e' g7 y - echo 'I am one!';
$ g% M$ [% V0 l- ^4 u( D - }
3 u7 ^+ B) t9 E2 d) A q3 B' P9 w' f - }
复制代码- //name.php
& C, d. r/ ?; n7 N: r3 O - require_once './1.php';4 Q. F: c! e7 R+ s+ b2 P# ?$ Z
- * Q$ C0 {5 F$ H
- new Person(); //输出 I am one!;
9 p' O$ S% {5 ]4 S2 ` - new \Person(); //输出 I am one!;
复制代码
4 I) D( R& W. U7 _, S, j2 ]3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php$ q" T, w8 t8 C& s4 j! `$ Q0 |
- require_once './1.php'; G+ }* v: @8 U7 z6 d. e" S: |" ^
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
' N- Y5 O# t' @3 L0 i/ m" \4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php " d' e. @* K# |; A6 s% K, @
- namespace one;1 h1 n2 ~% T8 M
- class Person{
6 G0 o4 |( q$ c$ Y5 P - function __construct(){
) E. q B; m0 \/ _0 g# Z1 W - echo 'I am one!';
( N- w* E: d0 Z5 r& @6 r - }6 k) h1 F) ]0 u: X1 W/ Q
- }
复制代码- //name.php" m: W! i; u. k; ^( M! M
- require_once './1.php';% Z( f d6 M1 p- m* O) \
- new \one\Person(); //输出 I am one!;
. o/ P0 ?7 x d- |$ `1 x7 F" H - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ' c! W1 _6 m" J I
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 : M. J1 r/ e: Q( {# Y- }+ m
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
2 U @& C" P3 }9 {- //1.php
% j, T# k% m) r5 s3 z4 }2 `0 N - namespace one;
) z8 ^/ E. D# o m' @* m - class Person{7 m m& Y) T: O( b
- function __construct(){
6 r$ _* T2 E6 I3 P$ D - echo 'I am one!';+ l5 B. V8 g1 A, s6 K
- }( K7 G1 \, a4 K5 F+ x% z$ k
- }
复制代码- //name.php% x3 ?) G# E1 Z: H: e' v% k
- namespace test;/ u1 ?+ M y3 W9 B( W
- require './1.php'; # |7 D, ~; d7 j6 Y" D+ c, ]3 s
- new \one\Person(); //输出 I am one!;
. S; b+ |: P" \8 X - new Person(); //这里结果会是什么呢,猜猜看9 ^, S1 C, n$ s
- 最后一行结果报错:. w" ~: G/ o" W( z2 t U1 K, ^
- Fatal error: Class 'test\Person' not found
复制代码
# v) C! Y/ T3 [/ g {
8 V+ g3 B# i! X' Q4 }首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
# r) Q: j% u4 t/ g$ t# T, }' a结果报错: - Fatal error: Class 'Person' not found
复制代码 " j) o' I! o1 _; l2 O7 ?
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php- u& B/ I& ]3 |9 P) Q3 \3 A4 L
- namespace test;' K9 R. O7 G9 g7 |/ ?" N; i
- require './1.php';
( q4 ?7 x( O6 h( r3 P% A' W1 `
j* T o" a* d1 j, L( Q1 d- class Person{
$ _4 `* M" \' f( y, V. z2 [ - function __construct(){/ d$ C2 J# C: O Q
- echo 'I am test!';
3 U" n2 Q) a8 W3 j( I - }( J3 b/ c% ^- u
- }
2 o, d8 m# r, O/ {2 |8 n2 G - 4 w9 J) \0 A, {4 _; p Q
- new \one\Person(); //输出 I am one!;6 L. s5 A* {& N$ y0 I% r8 N V
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
0 k: p) V( w6 V+ H1 W9 [ I1 L最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php, R6 ~4 n: B% [8 Y1 Z6 p$ E
- namespace test;. e% @( B0 E+ c& ]% o2 N
- namespace one;
; G/ @6 [9 Q" S3 ]4 b( ?- p - class Person{
' u; ~ X& m- p - function __construct(){0 D# B' y Q* o' F" Y
- echo 'I am one!';
1 l1 \# i9 C" z3 j( W6 w: x: V - }
+ ?" \, e8 R* ]8 N - }- A+ i- ?/ V) F5 z
, x* N# |2 U: v' S9 w$ u- class Person{' }, b7 x6 _' Q/ P# c! j: s
- function __construct(){
* |4 Z% _+ | Z) R" q - echo 'I am test!';
9 M2 ~1 Z1 ^% S) |1 z - }
% t/ H! U7 j2 K/ ~5 g - }
复制代码 z( I0 ?! F# |0 T7 I: j6 I% Y
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 ( Q6 X4 U6 ?, i2 m4 d& O
看来简单的把require理解为替换,在这里行不通。 0 t0 M( @: R% R! ]3 Q/ h: ]# [
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
, V% ?! r f6 j- //name.php
* I. ]6 A# n+ U( {
5 ]3 h( v8 G9 e+ l- namespace test\person;
2 H: f, T% c3 P5 B: u4 i( `4 B5 \
% {$ m2 Q' U' ^) d- class Person{& X# V6 a4 T; G4 J4 m9 E$ `& M
- function __construct(){1 b6 k e! g, G! P4 I% u C
- echo 'I am test!';" D. ?: ]/ _0 v& c/ [" S
- }/ b5 H2 h$ a5 |- r1 y+ w# o4 M" k
- }
a6 W' Z% l; E$ c% T - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
0 w) L; U/ W$ `2 [) Y2 S7 ~/ J; }不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
4 {0 ~ y B: U7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
) Z/ y% o0 J j( V+ n
% v) J+ Z! o, ` H2 p- namespace test;8 L( [2 C2 o/ t0 `
- echo 'zhai14';/ L: f) Z; M+ `3 w1 E5 S' O3 z
- namespace zhai;- t3 }9 D! K8 d/ c/ M
- require './1.php';
复制代码
" m; k4 N8 J, a% H$ \* h5 Wphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
: J- h) K& [: k# g$ I# ?use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
3 d+ M5 b% l; T" f; ~3 p% T+ j" y- //name.php: q; P' h8 N) ~+ u
- % {, S2 F& ~- u
- namespace animal\dog;2 X5 B/ y, k& [4 j' ^8 ]6 v
2 Q! J2 h) Y! h% f- class Life{
: m# a. Z. h: I - function __construct(){( `1 P0 U( J5 j# a( {4 F! S
- echo 'dog life!';
1 u# f# c' |) E; T6 Q8 H - }7 O6 ?5 R0 h/ j' v/ m
- }! A; M- W3 B* ?% c, _; G
- $ }2 S( Z3 Z9 c$ f# T
- namespace animal\cat;
, H' t- v2 E9 Y v& Z- l
/ c" |% m! C! a: L0 L- class Life{7 L. @ z, w# p2 T$ \" g9 F
- function __construct(){+ V; C/ o- b2 x ?
- echo 'cat life!';8 e4 e8 Z& d$ l+ E5 K
- }: p \. D' t- m4 E: {9 e* Z/ U
- }; D" U4 Y- H/ O, Z
- # F f6 `1 p. L' U$ d& j# C5 h
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
- C: i3 w' [9 X$ V- X/ P3 V1 w, \0 w o5 e - new \animal\dog\Life(); //A
* u! s' ^ x* E& g - 0 `3 E5 O% k# m$ \& B$ y' {
- use animal\dog; //a5 Z' d1 C4 q' N9 e2 T0 m! L; P2 w
- new dog\Life(); //B- q' ^- i8 c, {0 c
9 `3 _6 Q, b0 d, |) [- use animal\dog as d; //b
; k$ H4 |) J: d3 T V - new d\Life();
复制代码
' I* ]; s: N4 `5 ^) H" D通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
! \; {; g! V; Y( Z2 ^: I. D4 G通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: # c0 D+ D0 x' E( A ^% b* b7 b
相当于 % c: D: V* |' @# R( m
2.namespace后面不建议加类名,但use后可以。4 `, H1 q8 _/ _ y+ x) Q) k p
- //name.php
8 q- K5 l' z' ?5 k8 b/ i
2 u+ ]: K1 N9 z2 T7 p/ M( ~2 d- namespace animal\dog;& Y+ D3 E8 @- W5 C- w& {3 B
- ?+ T6 _0 ^6 _1 Q* e0 F3 i1 t- class Life{' n/ W( A8 n2 e" C0 |
- function __construct(){
+ c, ^; ]6 G0 b2 c6 j - echo 'dog life!';+ `$ ]* x( Z' z3 b; L; ~1 c) I* j
- }
' }9 Q9 {4 a- C1 j. e - }: H0 u1 I3 ?/ D: y' b. \
( X, N1 `# d4 V7 c* a7 S L5 N- namespace animal\cat;8 v( q" u6 p1 G0 P5 w6 }3 Z, ~
6 g$ J( U# H+ { i% ^3 m, ~- class Life{' l* S0 r( l% G
- function __construct(){
! S% h! v) @ N | - echo 'cat life!';% I/ _4 U }9 Q2 n$ R* Q! \; g. R* S
- }2 j! F% O {2 t$ K# i' M
- }
L9 w6 _4 r! {
# y& _6 z# H5 @- use animal\dog\Life as dog;
I" q) e8 Y& ~ - new dog();
复制代码 4 f9 g& i8 F0 x
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
- G2 ~* f- w1 H5 `0 L因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
% ]8 f! p, D+ h9 g Z) m - # c* ~" q! a+ l$ e6 y" d
- namespace animal\dog;5 v% ]8 z# F; K* r
- : u% q" y, L( N2 g& B
- class Life{
) t' U0 f- w: q7 W( I' d- e7 ] - function __construct(){4 Q, h! H' b/ o- d* z" A) f* {
- echo 'dog life!';
* m# m9 P" Z$ U; p3 ? - }$ ? `/ I2 @( z3 g
- }/ G, v2 a5 T* u1 n& G
- class Dog{
/ {: z4 a! J/ g9 L, x& M - function __construct(){
- j9 H' Y6 Z0 x% \5 q - echo 'dog in dog!';5 P4 D, z) E3 w8 S) A
- }% _9 D/ G0 L! |' p! j% r
- }
+ _: ?. \# l0 J) Y \2 j - ) Z: J. h# ^1 B0 s" _8 `
- namespace animal\cat;
* z3 c9 ^: c' g$ e; e
7 d9 J& D2 U3 j4 D7 [% C- // class Dog{5 Y- ]8 R3 I+ ~+ J3 G. V3 h- _
- // function __construct(){
3 d, Y( a6 S* H - // echo 'dog in cat!';
+ A% B9 M4 @. ^7 b - // }: f) {' n8 a- D- T) X8 J) f
- // }" H2 v' _: Y% ~1 j# ~5 N
- class Life{
# |/ V: a; W. ~, y& C" Q1 O" b/ _ - function __construct(){7 w J( {/ _; I' I7 n* ^
- echo 'cat life!';1 Q0 D7 G9 ^( ~$ G4 {/ L* R
- }5 ]5 V0 E9 s O2 t' \) F$ [: s
- }
, Z$ Y' r' C7 b4 Y9 \
5 t& |; S1 D. Z2 {2 j5 ~- use animal\dog;
! N" ]) h" h7 x - new dog\Dog();
复制代码 2 b$ k1 k) G C7 D5 V" x0 v' o
如上,使用了
3 b4 B& H& }; ~, ^cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
6 C3 e( R! q2 n2 k6 a+ N简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 * F+ W9 g7 a1 x
/ x9 G) W: X+ O1 R( j: c9 u
3 Y6 E! ?& k: M7 j" w& `( `( a( U. f
; `) G, e ^/ Y4 P5 Z' ` |