|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
: t; i+ D1 G, L. K文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 + Y1 `; g* u+ }4 E% k3 e7 o3 R
# V& g6 c$ {% \' J
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; : D% E3 q5 f; Y& D% ~; b1 P) G
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 4 u d1 v' Y) b3 I5 h9 j1 w
结合使用方法来进一步理解它的使用目的吧。
. ]" X" |5 r/ |$ \0 N8 O2 }7 \* J+ @5 \8 {
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
/ g+ P) O4 f' Q5 o) X6 R" R - namespace One;+ S! I/ B7 X2 U3 U
- namespace ONE;
复制代码
/ }, U0 T& B7 J如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 0 a E! @ I* \$ [8 h! Y% e
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 5 z* A. f6 K# a8 h$ W/ q
- class Person{- H6 Z# j7 [2 S0 V$ h: N4 W
- function __construct(){
% R( v8 r0 E! v L6 q - echo 'I am one!';0 W- C. a2 k8 D5 q- ~5 B
- }: M8 t6 d4 [6 z y- H' Q! F
- }
复制代码- //name.php
2 U/ j2 ` @' M/ P - require_once './1.php';
1 o4 \. q6 e3 t% u9 J7 o
/ E# D4 H$ y- p: e& W( C- new Person(); //输出 I am one!;" L S9 @0 L [
- new \Person(); //输出 I am one!;
复制代码 * ~3 b, N O; j0 c0 Q+ S
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
/ j% y! [6 q4 a1 D9 } v+ N1 v3 h) q - require_once './1.php';. X0 M$ ]; A" ?. X: m
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
9 b$ p# l. b; q4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
: W# A* c3 w. x9 f; [2 x - namespace one;; U; w% L4 U6 |
- class Person{" y) p6 t: }9 }
- function __construct(){
$ a" N) b1 a) W! ~% E - echo 'I am one!';
1 A, e7 V: r" j I' \- Q - }
) ^. `: l& D0 B3 v1 I - }
复制代码- //name.php
: I! _$ Z& T; ]( ^3 k7 P% r - require_once './1.php';
7 ], g7 Q- a9 N# `1 _! U1 ] - new \one\Person(); //输出 I am one!;
' @9 _7 Y. G( R u. p - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 , M3 d2 c, s( M' _$ [# H& W
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
4 u7 R% g0 T4 e0 W* u- F; z5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。4 L) X0 W( i( S5 _% Z
- //1.php " H m8 |7 H- M1 W3 s( V8 M( j
- namespace one;5 z& }, L. a( g. _& R8 h
- class Person{
5 y, u+ n- V# v5 _5 b: r/ e - function __construct(){
0 N2 t- S) [3 {1 P% _ - echo 'I am one!';
) h# @8 [ S* r$ A5 E; ?" N - }
: s7 @& o6 c0 p- H7 S4 g - }
复制代码- //name.php
2 S7 I( N4 O4 y; P - namespace test;" v' v+ j8 C' u( l
- require './1.php';
5 i0 {3 Z5 A' q# n: @9 ] - new \one\Person(); //输出 I am one!;
- I N2 o ]( f5 u - new Person(); //这里结果会是什么呢,猜猜看. `& a2 o' b d: K6 ?6 y9 O" _
- 最后一行结果报错:
* `4 W: j( z' v& O( G- f2 P& j - Fatal error: Class 'test\Person' not found
复制代码
- O- _5 h. ~1 {2 q4 V
- Q2 a: n8 U' P! c/ q7 n2 _7 F首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
9 t7 E) b6 E& [( Q结果报错: - Fatal error: Class 'Person' not found
复制代码 5 a! ?! `( R( Y1 O9 C( j
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
9 c6 f* D6 m# K! b( M4 \" H - namespace test;
1 @( l `2 W- i* s - require './1.php';
- C% J0 g1 x% D4 I
3 A _, \7 ^. o& G W- class Person{
W5 E" J+ I9 P: i. \% N0 p" S - function __construct(){
# J8 B; N& q+ U* V0 v7 ^/ U: h' N - echo 'I am test!';% V7 j6 `. Z. \
- }' L( M$ V4 b9 x" h: x' [
- }
- E, V7 U5 _. K, {6 G9 i: [% @
, J, N8 s- u4 ]! [# C7 o0 E9 r# V" E- new \one\Person(); //输出 I am one!;
5 u0 f# s! J0 ]: Y' u% u5 {/ N7 k - new Person(); //这里结果会是什么,自己猜猜看
复制代码 6 ~6 L" n6 _9 v3 C9 L
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php. ]- {( O b6 v
- namespace test;# ?$ i4 e7 U! b
- namespace one;/ K) P' _% m- F( O. P8 ^
- class Person{
; d* c; h5 L; W v( Z6 A" F - function __construct(){4 j& A% S8 \. G6 T
- echo 'I am one!';/ @! p4 q+ X" n
- }
: f6 Q/ g1 ], e; F - }- b( [' F! H# A) ~( i
- 1 I$ @0 ^# a6 a& I: \
- class Person{, n& J; r8 Y: k- G- k8 L& Q4 }
- function __construct(){
5 L: F9 L' `" |& \ P - echo 'I am test!';9 l8 t$ O" L5 l( J
- }
3 h. z1 [! o0 Q, K$ O4 b# ~0 }; x - }
复制代码
7 {+ @# M: o5 [3 z无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 - V+ U3 z/ B% ~4 Q
看来简单的把require理解为替换,在这里行不通。
/ y# f; ? l2 I6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。 a: N2 O8 A3 G2 h
- //name.php3 T2 |+ I9 d9 J2 v1 P/ \
3 G5 @* l2 T( e. M1 _- namespace test\person;
. g% `' \! A& V( R
' g, p: Q4 q; a- class Person{
: ?* `# t# x W& t' p - function __construct(){2 x3 q H; _9 G. k& K) z- F
- echo 'I am test!';
0 N0 i0 t; Q4 A. v5 I+ A - }
) U* P' B |8 q6 b: j* n - }
' W1 C' Z# ?) S# I# o! \6 c - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
2 B; |) e/ W7 E$ ?不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
8 k# V' _: C7 r( ?, ]7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php$ k4 P$ z0 [% N4 G5 w. y
' W, T5 n2 m% v- namespace test;
$ g) @8 ]0 P& t; y+ i$ ? - echo 'zhai14';
4 `: Y$ q! y, K - namespace zhai;' O0 c, x2 i# v; O' | W
- require './1.php';
复制代码 & i+ ~ b" t& \8 E( i+ a
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 & z/ w- E' |) u3 z4 a: ?
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
" h+ c2 b4 A) [- M0 {. n- //name.php
; ]: J. J. \! u9 T2 [( f1 G. y
0 _+ c* Y) u7 k% Y% m s- namespace animal\dog;* r! [4 s) ~6 n1 q: N- A3 `
9 V0 P; P$ x, m+ n$ d- class Life{
0 x Q' F( ?: ?* M: k - function __construct(){2 H* L; z% o* l( ~- t9 f
- echo 'dog life!';
% K$ h w& W, b - }" K4 V5 R% s% c, _, B6 O
- }+ i. e- x# k' A9 u6 F! a
- L( }/ K. i/ ^3 |% b$ n) p, q- namespace animal\cat;
1 |( B4 ^9 g- ?" L! V/ N/ ?
* N5 V$ S/ z! p$ z- class Life{. Y I _; H4 ~) G* L/ f8 o6 Z
- function __construct(){
+ E x5 D+ X8 { ~) T: g! N - echo 'cat life!';
/ {/ u2 ?# P/ s- k% K ?4 \ - }$ [# Z, Q3 f7 V+ \
- }
# c' E0 u* I5 R" T! p) ~
# H9 c, \9 W5 N: |- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
- q9 s: G$ W( z# Y; U# E - new \animal\dog\Life(); //A% G& I$ Q/ p3 u. i
- 8 ~2 o$ H1 M% h% ?! Y0 x# I
- use animal\dog; //a! z% s! P2 j) s) g5 ? `
- new dog\Life(); //B
. O* j$ Y0 j C1 Y/ d: p9 _
. Z* K6 J% t, C" d" M7 V, c- use animal\dog as d; //b
2 B! u" X4 D' q% _- h, p& N - new d\Life();
复制代码
( j% }1 L$ k w& k2 K通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
Y9 w% T, J! w# m通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
- Y7 E, C1 {6 @, C( s3 H K% a8 w7 M相当于 ! r7 I) \3 {0 x9 c% `9 _+ | ~
2.namespace后面不建议加类名,但use后可以。
: q5 K2 a+ w# ]) A- //name.php
' `; z) Y# ^8 d% h
% k6 ]/ s: G& c, ^( d& n- namespace animal\dog;
9 B2 F a( f3 D8 ]; ~ - s1 `6 r/ q( y' V
- class Life{
% \4 J E; N# k) @ - function __construct(){
5 c1 A' m( _& D - echo 'dog life!';
5 O1 y* S5 v( ~" ~ - }' C& o% ?8 z }, n$ G% |
- }
; z. J: `6 Y4 c! h2 a
m7 Z- S7 L7 f, n$ X7 M- namespace animal\cat;
! C- H0 U: Q: z$ ? - ) V- N1 b5 J6 u9 C2 Y% S
- class Life{
/ {* M9 V, M7 q( @ - function __construct(){; P' r! d- B9 ?8 k- D
- echo 'cat life!';
6 N2 R4 Z; z( T - }% l. I8 F9 q1 I' \- ~1 \1 F
- }
0 h* O5 ~6 L+ d$ X2 A - 2 [! I {/ \2 C8 m! k7 k7 J0 k
- use animal\dog\Life as dog;
* `% j4 ~ J" o) u4 ` - new dog();
复制代码
) m0 g" X6 `! C) U V" Q$ F: R: o如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
8 E( M$ M' _: r% E& k因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php( e5 p( ?. o' f: }& n3 E9 O0 v
( l4 r5 z4 x7 L8 J- namespace animal\dog;& y0 q4 X3 d" M5 K2 }
- 3 M/ b5 Z! O1 l
- class Life{
1 ]! u" c1 I: ?, v8 ^ - function __construct(){
( E* b; j; k1 u$ n0 H! e4 M( z - echo 'dog life!';% l9 x1 b( y9 Y7 b" M9 E9 {& N
- }. g1 A# j9 c- }
- }/ R, `5 h7 }" L0 U: q. f
- class Dog{
2 }! h v9 `" M/ ^( H$ \/ J5 X - function __construct(){
' [/ O) _( g! m' E - echo 'dog in dog!';
* m1 D3 N, I9 i" M$ D4 L - }7 m$ L) M+ U3 j w0 j' i- A
- }5 r: f3 _: V4 h5 l: ~; [& ~
, B! s, p2 k. Z5 W# b- D G. d8 n- namespace animal\cat;
7 Z) z7 c; L) ^1 Y& o; k( v - # H7 {: p9 C& q6 s: ~; }8 H/ g- K
- // class Dog{+ i6 }$ h0 A" h# t
- // function __construct(){/ r* \, I# X% M8 b6 l n1 P& o
- // echo 'dog in cat!';5 q3 x! p( g" W: q% I/ i9 K0 l* w
- // }5 \! L* u( z8 x% }, g. G* R- e" o
- // }
8 _- ^ H( [' e7 p6 d - class Life{
+ x/ z. L! ^& o - function __construct(){
/ {& z; r- H, `( ?' j; Y4 a) G - echo 'cat life!';# Q% Y* P$ \# n8 f9 e" Z$ y
- }/ I6 D. A6 K5 U J& g& Z/ C$ h
- }
% s+ _0 T8 m/ d/ g+ B6 a8 k) u - , x$ }5 n+ q% A' D$ A
- use animal\dog;
4 n& G1 _+ `5 B( O# B% h - new dog\Dog();
复制代码 # S4 n( f! X J% M) {
如上,使用了 / t! P- [0 B- Z: L- j ]
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
2 x0 C2 w% _2 z5 r3 S* s简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 5 k G3 J8 N. B4 C; r; q* {1 `
! |+ U v1 h' A' U! r x ]) M( k: ]- F
6 i$ P q, p4 y# w& ^8 }8 f2 U
& {# \* k5 i$ E' f3 y |