以下皆为本人自我理解内容,如有失误之处,请多多包涵。 & F! |) s$ J4 v6 l+ D% ]: r
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 + ?* X1 K& M! L
% _0 W$ R0 v a; f& z
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
9 R& c! M- t; \ j: E* b# V据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) : k: J9 X9 M, e. j
结合使用方法来进一步理解它的使用目的吧。 4 P" v& U( [" A0 D) W4 W
+ X7 [7 |5 E8 P( q/ a1 [
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
6 M2 |# d- I0 B% l. ^! I - namespace One;' @' u( n6 J3 ^! P
- namespace ONE;
复制代码 1 a0 o" i5 A& e1 q0 ~) `4 ]6 ^
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 8 L% A* q, o- A% K9 U' u
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
[+ O+ w- m2 R* i/ g - class Person{3 @, I ^; J0 E5 U
- function __construct(){ j, h! @! b) f7 x4 B z2 B
- echo 'I am one!';/ C7 ^% Y9 {& G/ q) [0 v9 z. a: V
- }
! P/ l% V9 O A0 f3 g4 Y - }
复制代码- //name.php/ Y: w* B$ H I b# o' g# J) g
- require_once './1.php'; h/ S% }2 f( g2 Y/ `4 P" b$ e
- $ @, A( Q/ m" H S% `. q
- new Person(); //输出 I am one!;9 @- I3 D- i9 y* L5 L5 y, Y# g; ^
- new \Person(); //输出 I am one!;
复制代码
, _2 c+ \% @+ s k& ]4 G/ S3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php( g+ t/ ~5 K+ t& D' g# i W
- require_once './1.php';8 d; h* e4 P, l" b
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 1 L9 C$ Q! g. {+ R. L; F) ~$ l
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php , l2 l' F6 e5 L/ D
- namespace one;6 N7 f9 A( K: N3 H
- class Person{
/ Z o# _+ ^: t' G4 x - function __construct(){% ^+ k: P. Z8 D3 |9 q) R
- echo 'I am one!';
) c; m4 r- t) I( O - }+ i, k/ K; U9 |* `/ j9 t+ ]; o
- }
复制代码- //name.php
6 r0 h4 `% g+ W) f) r$ f - require_once './1.php';
6 l5 G) n1 z, x& b0 f1 J1 g+ d - new \one\Person(); //输出 I am one!;# d0 J( w/ d* T
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
* N: r$ T3 }. i. d3 ?5 r# [可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
" r( I$ |( P8 C( z+ R2 a$ D5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
" Y( O) R/ F& g/ i- ]- //1.php
7 @6 }9 X+ l3 @0 n - namespace one;8 E$ U4 T' H* }
- class Person{& M6 C; u: e* U. e4 {) d7 t
- function __construct(){( @% J) L5 i! |4 I! O
- echo 'I am one!';
# b, G1 ^% a; N) I" X6 Q4 R! Q - }
2 E% f2 l) n/ m+ a/ e - }
复制代码- //name.php
, a7 I7 B% v' P - namespace test;
^0 B; p2 ^0 }2 q, Q" O - require './1.php';
3 b# L" u# J8 _. J - new \one\Person(); //输出 I am one!;, k( t+ l& i# I/ s+ o+ a
- new Person(); //这里结果会是什么呢,猜猜看
: w! y4 B- e: z$ @ - 最后一行结果报错:
c( F4 F. r c+ ?# ]( v; |: L( ^ - Fatal error: Class 'test\Person' not found
复制代码
7 z& D: Q, S c# W* i# p! z& k( k x$ L' U& M- M
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
/ l& D a. j) ]6 Y1 |9 I结果报错: - Fatal error: Class 'Person' not found
复制代码
: r; }& c4 b$ U0 v f: u* u接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
2 k: A! E% v4 q+ F m- b - namespace test;
2 L0 M& @/ h' k- P$ M - require './1.php';
/ J/ O( O0 J! ~ e - 0 h5 ?# T* Z/ h9 ~ x9 b! [9 e
- class Person{
7 ^# M2 b3 E6 S) w G - function __construct(){' ]0 P" x( e( v) |
- echo 'I am test!';
8 c- \ y5 W m2 {/ B - }
v( g) X: T) v; w - }4 c/ n, |2 Q' U1 I% H# Z
- - p. T4 t- ~* }: ~/ ^4 v
- new \one\Person(); //输出 I am one!;0 ?% u+ N2 H D5 P/ N
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
/ v3 I. R: l: J A2 a* W最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
5 [8 e9 |% l' @: [/ I, x% A - namespace test;
6 X7 S. M0 b. z; V1 G0 l4 l1 p: Q - namespace one;7 x; L$ ]- o( \% R) d! {
- class Person{
" J' P) r1 g9 u' U1 X/ _ - function __construct(){& E- t' s2 H. s" z! L% W$ Z
- echo 'I am one!';
9 z1 b$ r- l+ ]# i6 u# @ - }
$ n. G% u0 D/ T% i, v1 f, t# b - }
' A. n, v5 O$ N8 E2 f9 E1 X
% w4 E: K5 P: D* A' n# H! c- class Person{6 y2 l. C& {* `
- function __construct(){
K8 q- g: G4 \% X f - echo 'I am test!';7 l# e7 [5 R% n. ?: b
- }
: `& l4 R# h4 I: E4 t( \; ? - }
复制代码 ' v! O0 A6 r( q' V$ N' T
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 + [% E. G. r6 v6 H- y9 o
看来简单的把require理解为替换,在这里行不通。
& T) f3 Z8 F% u' @9 i6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
- W% u* F* x8 Y5 H- //name.php
) {3 T: o3 I6 D
# N5 j8 Y( A7 N* S- namespace test\person;. G; P$ ]5 `% P+ s: O
! P7 f, y; N( Y. I- F8 y- class Person{
1 b; @& v" z/ q' ?; ^: B% K& f - function __construct(){
4 X6 j9 i1 A$ ?" G1 L" U - echo 'I am test!';4 \$ R8 l$ `* Y/ `& P) V/ a* o
- }5 p4 E+ c: N- {. o: y7 S$ ?) _6 f
- }
9 Z* B4 f( q: c- C( s- } - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 6 d T+ d1 ~0 U
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 9 P' A* w. o+ T" q- H- u W# a! k; [% h
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
( i. V, n7 m3 n$ T - 1 H0 e1 ^/ X) I1 a4 ^, J+ t
- namespace test;! _) q- Y" `& k& L! |; y
- echo 'zhai14';( Q, {4 D: [5 i2 @! @
- namespace zhai;. t: B2 R9 x- s- s$ D
- require './1.php';
复制代码
9 ?7 ?3 Y' L: U* Q1 W* Rphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 % b/ X) p+ q& }/ Q4 n
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
6 C3 n$ n7 \4 q1 Y$ Q4 O- //name.php8 v3 X* e, z1 w' n) n* i
- ) p* n b; D1 |/ [% w
- namespace animal\dog;+ A9 N. G9 R5 W5 M: i. R; y5 |
8 h* _& {1 M9 R0 U: Z3 q& k- class Life{7 q& B5 A7 R6 ~9 `" a
- function __construct(){8 W% a/ i4 h! w0 u) r! Z' K; c
- echo 'dog life!';& m0 }, x* \& i- @- [- m0 c" O
- }
5 Y; Y* U8 ]1 `- Q% d - }2 T4 g5 C& {5 K
4 C! O( x: _$ i3 _% g; R. c: L3 T8 m8 b- namespace animal\cat;* K" U4 [6 M$ ^% |6 ?, ~0 `
- 9 R9 i8 M: J- T* H! q
- class Life{9 z' o# f. \9 ~2 [( l D& I' f$ q
- function __construct(){
! }- x2 M+ O$ @ v - echo 'cat life!';8 q: a' v3 {4 U3 f! B
- }
* P% e2 c9 `. a( M - }
& f6 h% k& N, o6 u
+ x/ h5 ~) ?) }& O+ W d4 L- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间0 N! V+ e! s: l) o
- new \animal\dog\Life(); //A" w% Z, B+ ~1 P( n% G
^+ _- w; [) U- use animal\dog; //a5 B/ q0 x7 X3 s+ }
- new dog\Life(); //B
. f" R- S4 e% y, \. y3 ^9 s* N - ) I1 r/ g: a" S: d
- use animal\dog as d; //b n }& B1 J, F3 [
- new d\Life();
复制代码
+ r8 ^( ^7 o* W1 H# Z% X通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 % J/ Q$ z" b% _! {
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 6 c9 G' G. g/ G5 b2 i# c
相当于 2 u, X0 m- ~* O7 [( h
2.namespace后面不建议加类名,但use后可以。
% j) B: H8 u9 G0 G$ I5 {- //name.php; L$ O F `( t! U4 r! ~% d' V$ D
- 6 F3 o% }! i% X* O
- namespace animal\dog;
- [) |. m; q9 x. R! A- `5 B - 8 A3 }, c+ ^7 n% u. C
- class Life{7 o- a7 u6 a3 ?: T0 I* p
- function __construct(){
. R0 N& H4 P% Z - echo 'dog life!';
; u X$ ~* N- X; W - }
. [6 T8 p0 }6 M0 k - }
( r I" J$ i: T- Y Y' d& U) h - # I" d/ }0 C2 S6 ^9 k" m- l5 s) \
- namespace animal\cat;
1 M$ X, q2 U R" |7 W - 6 A7 U# Y5 p$ A0 ]1 _
- class Life{
" `6 A& o3 F# H7 _ - function __construct(){3 _8 v% |$ y' b
- echo 'cat life!';
. X/ _! n4 M! Y: g; X# @/ T! r$ Z) v - }
$ ~8 b: B: p" V0 b - }) o+ k3 g& s& s+ K' F1 H
( C A, {# ]7 s# ^* k9 @7 g& D- use animal\dog\Life as dog;
4 P. c, {* f# s1 [- T) ?* k - new dog();
复制代码 5 ^0 N: z) Z2 n; \$ c3 c, A
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
2 N. E, C) D B8 N1 R* {因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
+ M& h8 B3 a2 C1 ? - # O! E" T: A3 _" d
- namespace animal\dog;6 O6 x/ [' B Y( G/ x: U4 j/ B
- ' h$ a$ X2 T: ], ?: j6 q
- class Life{/ d0 F' U6 b/ V5 r, ?
- function __construct(){ e! u+ H5 N% F# }
- echo 'dog life!';
% i: N) l" }# `% ~ d3 U - }
% P4 i2 ~* _! T0 s+ h S" Z+ P% h - }; e- U( y' e3 j% }7 F) ^
- class Dog{' O- ]$ b3 S& }5 }) p
- function __construct(){
. R- I1 u$ }1 `: R2 J- t# ] - echo 'dog in dog!';
3 m9 Q# c5 @) ] - }
+ Z# x' P1 T. g9 m8 X3 s - }
2 D1 D+ q6 S; I W( ]' U
+ j; q9 ]9 J- g- namespace animal\cat; x6 }5 \' k8 `9 c7 G1 G
- % p# a: k6 h9 }! Z4 P# y5 E6 c' Y: ~9 |
- // class Dog{" ^2 b% i% m; d9 T# z! T
- // function __construct(){
7 |1 W) Q9 _( T) b/ R" c - // echo 'dog in cat!';
k. r9 ]% B7 }( L8 p" T! \ - // }" j N+ d r+ }+ L3 A) m6 U7 k
- // }
" {! j- \ ?% c) R( M7 F" B3 D: L - class Life{' ? m# Q) @. j) [' c
- function __construct(){
6 k. X. B( X Q1 X - echo 'cat life!';9 N6 _$ I5 k/ z2 x& s
- }
2 m3 }. v" ?# G1 ]) l s - }
3 {! \1 E$ \; \( h
) S1 z, G8 z7 L# t, x+ x- use animal\dog;
" Z+ }( h0 C! u T" ~) V4 K - new dog\Dog();
复制代码
. Q4 c7 j( t) E# [; S如上,使用了
& E; k- N3 p/ t9 i4 d$ v" _( U2 Xcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 8 k J/ k$ z: K: J/ L) L b. R
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
7 X. G8 e+ z5 l' y$ B2 x4 a& g
3 M# _$ r( K% j; c
8 h2 L+ X0 E+ h4 F
* b& R( w. A9 F8 V( J' B
: U) {" t: v3 \. \ |