|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 4 R/ R" S/ b1 ?7 `6 k
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 # C$ m5 _& P' P R& B+ a+ |( O
# w9 |' e5 i( a& p- X! ^4 I使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
" K. Z" r$ K$ i$ M+ d据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) - m1 j8 ?' |1 A* y: R. v
结合使用方法来进一步理解它的使用目的吧。 + N5 [5 ?1 Q- ]% G3 o% ~* H. h
$ V2 C* R: H; L* R3 G C) u$ K
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;. C, c' Y+ V- \7 h+ @! J9 r
- namespace One;
5 N5 d; I/ T9 p2 ^2 w9 E: m: R7 V9 x7 z - namespace ONE;
复制代码 3 y# ~" `1 A! H f1 G" c
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
% ~' n- i7 l4 q& o, R2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
$ w' f7 m5 K8 W; ~; M- K - class Person{
) m, f. T5 _: d" u6 h' Z6 _$ h - function __construct(){
/ S% T, u! T& m0 C: M8 K. l - echo 'I am one!';
; [9 G+ ]2 h; P- w$ U# ^3 ` - }
, s3 X6 n1 H1 ~ - }
复制代码- //name.php* d/ G" q$ E: N6 Z' z q
- require_once './1.php';" M" a; @, x% e( _; J3 ^& X3 Q
- + r# C: g5 G$ l+ g! i" b7 f
- new Person(); //输出 I am one!;" e6 |! Y6 s! _% [: A
- new \Person(); //输出 I am one!;
复制代码 1 U: C9 s w, C, \/ U
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
1 `, L# b4 _0 F" y+ X - require_once './1.php';
5 ]/ O( i8 X% B - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 + E3 J0 Z: C; Y% }- A
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
+ r- `2 b4 J$ ^* w V/ V$ L$ P+ G w - namespace one;
1 F* i( Z- R$ j& E: l# X - class Person{4 o- V0 y( L( l
- function __construct(){* ~. t% z& x' R! R7 |' a' p7 \
- echo 'I am one!';
3 F- n C8 J* F6 c, |1 @4 ]! o - }+ _8 O" a: }$ ^
- }
复制代码- //name.php% ~0 c# ]( o% V* g
- require_once './1.php';* U$ a7 \: n5 C% ]" J9 @& E
- new \one\Person(); //输出 I am one!;# P% e+ b1 x" e K
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 4 y5 c: y; h3 s. e
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
. ^, y) T+ ~+ \' l/ K E5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。# U) e" M) I! M, `. B2 H& n1 f
- //1.php
0 Q9 J4 r6 L, m. }7 G - namespace one;( y1 ?; j! \* m
- class Person{' w; ?- J" P* k: r
- function __construct(){
O' f; W" ~! C" ~ - echo 'I am one!';3 |6 B ]0 y2 [- f8 d0 u6 h* n t
- }
' {$ G) ]9 F# Q8 l - }
复制代码- //name.php
( A" D: D4 J2 P0 ^# z( o - namespace test;
. j& O7 i# b/ \& f( k - require './1.php';
: T3 N0 d6 Z- w2 N5 H: x - new \one\Person(); //输出 I am one!;, J7 X/ p( e2 _& e ^
- new Person(); //这里结果会是什么呢,猜猜看; R) L, h7 K) Y$ ~) _# l: [
- 最后一行结果报错:
$ m5 s" \: d7 o* K% ^* t& U8 L - Fatal error: Class 'test\Person' not found
复制代码 : [) a' ^9 l0 ?0 y& i- M" I W/ e
$ d6 v3 S1 {7 Q2 u4 J- a
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
" {/ S3 J2 f8 o" {: H/ M4 a7 ~结果报错: - Fatal error: Class 'Person' not found
复制代码 9 Q m8 f& A/ X
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php. i4 }/ l1 w+ |) a
- namespace test;8 R9 f# `. h2 `" ]
- require './1.php'; 8 l/ M4 D, K/ `' G+ T! [
0 T1 Y4 A# m+ e4 _, ~$ W( i6 @ O- class Person{) `3 _( c" b% z: I, d. ]
- function __construct(){
% K: S, P; O6 o5 [; c" v! V/ S, T - echo 'I am test!';' S3 i2 L1 |1 M5 q% ]
- }! H. i9 K" q# e# A' U- N7 M" C
- }
/ g; H' t4 H0 ^* \5 z
. b; O" u+ s. D- new \one\Person(); //输出 I am one!;
5 a' O% V8 l" h5 u! N- ? - new Person(); //这里结果会是什么,自己猜猜看
复制代码
8 U D+ @3 N3 g+ t" L最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
% n& r: s( X+ m. g3 R- A/ M - namespace test;
* J2 L0 G9 f1 s4 U, o5 ^ - namespace one;1 P, V& M4 t2 r
- class Person{. y2 |" N% m6 P. w. C
- function __construct(){+ h- P& h$ \% o6 b7 d3 \
- echo 'I am one!';: o; p: t, J* q7 ~- K% H
- }8 z/ h" |' }9 `9 }9 d) }
- }' ^; P8 ]# g6 S; C
- 5 V2 P) u. b% w# v. u) _
- class Person{! I6 p6 C2 _3 }: M( L
- function __construct(){
( q& ~! F0 ]& u6 s% c2 J; H7 R - echo 'I am test!';+ b+ o& ^5 F; U$ t0 H5 Q8 c
- }
) H6 H O% {" c6 r( ^: B - }
复制代码 J8 u% s4 t2 N6 ~% U, q1 e& o
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 7 Y1 S. w) F1 ]- l' K* s# @- \
看来简单的把require理解为替换,在这里行不通。
& K8 U8 b! t( g; d6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。7 n H0 f: o. \
- //name.php# a3 {% W2 S, J9 M r8 [
- % F9 N2 N7 @8 q' K7 I+ x9 w4 u* @
- namespace test\person;
1 ? K1 k8 f$ ~0 d
2 E7 G3 t" X% y- |- class Person{
6 s# u. h2 ~2 E' l6 A - function __construct(){
' z$ _% l$ }0 a; W& K - echo 'I am test!';
6 L1 m/ l& _ a5 A. d1 L - }
; v% ]: G. Y: T$ i' Y4 j - }1 h0 d l/ q+ w6 Z' ?1 p4 k7 Y
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 0 h4 K$ y. z: D! U" h5 {7 F
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
; ^" @1 l5 q& [4 B; G7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php" \ n. o2 K. |6 ^0 j
( ]' C' L5 M0 w) \; k- namespace test;6 m/ |# n0 _1 V
- echo 'zhai14';
! M* Y2 ?1 \7 y9 W! @* J - namespace zhai;2 D! |3 _0 R2 x% f
- require './1.php';
复制代码 0 s1 d+ b( B9 \- H) `
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 6 B' Q2 j! @7 W: R) x; I
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
% D; ?9 Q7 b+ U9 w$ Z; ~- //name.php& H2 ~2 q. c# d
- 4 s! z+ A6 ?% H' G" U
- namespace animal\dog;
0 K4 g- r2 k' v' } Q1 n. S# ]8 L - . z) ?. j) l/ e# d+ m& V' N" e
- class Life{
7 s+ w0 r' S, X- k1 `: d& t" k6 C2 I6 T - function __construct(){) K ]! y$ S. O3 ]$ v
- echo 'dog life!';
0 o7 w( [& z+ I' J - }- J/ B" u/ |, i
- }
& K0 k% N n8 b3 H; u
/ E1 H9 B0 y3 r7 q0 v2 j6 z* K9 g- namespace animal\cat;( z6 }3 x! \8 d
- ) g, Z# i# W. L) U
- class Life{
! x5 k g* G0 d5 P - function __construct(){
2 g+ X Q9 K8 f1 Y - echo 'cat life!';$ o9 K/ ^2 {) K# {
- }5 Z, O1 P- e, `
- }5 o7 ?0 L# }) i2 m& R0 R1 [
( M( n: h8 W2 l2 V! |) D0 P- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间! ]+ F. A3 H* ]
- new \animal\dog\Life(); //A
! w( J3 B- @; e% p9 Q+ y! K. o
- Y- O0 f7 ?" v: { M, J k- use animal\dog; //a9 @% Q, J' G# X' t/ A. `
- new dog\Life(); //B
z. T0 S# Z2 V
6 `$ S4 C: r# p- Q# @8 d- use animal\dog as d; //b
$ M7 `9 H& |) O$ g1 y; Z - new d\Life();
复制代码 ! t* o% q. |+ t1 {% @8 C
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 4 M$ U6 R" I5 \# |
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
- d5 c& q# Z' R7 @% i相当于
9 i, V$ Q. r0 g2.namespace后面不建议加类名,但use后可以。
" b) Z, I' a% {0 W- o- //name.php
3 n8 ? @2 z* I8 [+ F7 }
6 C5 a& ^/ p; D- t& n/ K- namespace animal\dog;: k8 |/ w; M2 R+ [- c: R+ C- d0 b2 W
) m7 n: w3 \+ _. V' L5 ]- class Life{
8 A7 m- y8 r' N- V) s - function __construct(){
w# x! t; S7 V - echo 'dog life!';
; E: X- i/ F( D - }( k$ M6 M E4 u* \% B
- }. F' p2 }" I Q4 `" u# c; ?
- : ~9 \9 o1 e( F* v
- namespace animal\cat;) c; V; o8 q4 M" h: k2 Y. N% D
- 5 p( z* R! [* I1 W4 m: B& W
- class Life{
4 W1 W! K$ b ] - function __construct(){6 p% f; @; E- y- ^
- echo 'cat life!';
2 g' f2 `0 W n* t# u: H0 h - }% M% A( e! ?' y2 X1 K) ~+ a! P
- }) m. i0 Y/ o8 P. ^; q( B" |. _! `
- ! V+ t g5 o' W) x- J& k. l
- use animal\dog\Life as dog; ( M+ f1 n# _1 O- U1 \) F8 n" Y: D
- new dog();
复制代码 0 h3 c# B( ?1 q( t0 u
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
7 D1 w# Z) I8 M0 w5 h因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php+ ]4 t. @& J4 r
) y% ~$ Q- u. B D I% E- namespace animal\dog;
0 w* |2 T" z5 B! @7 ?4 g% f - 5 }% ?& j0 x) _4 R
- class Life{& k* _# E/ C" C8 U
- function __construct(){
/ {3 U, [ R$ N8 f# a! Y+ @ - echo 'dog life!';8 H [- R3 j0 t$ p7 A8 _3 m9 A
- }) y; V8 _6 {$ z( B- h( c, [" B6 }
- }6 S; D) F/ V7 V8 } z1 ~
- class Dog{
, B4 }) ]6 X$ k7 i7 v5 `( i - function __construct(){' Y# q4 F. O* M
- echo 'dog in dog!';
; O( h0 ^+ u0 Q+ w1 Y - }
! ^+ {9 T7 S0 g# Q( D$ b) A - }$ Y h% U. k; I" J8 I3 c
- 3 s r: }) z9 r% o6 ]' J. M- C
- namespace animal\cat;. q& r m# Y% y% A; z6 f& F
2 @! z3 ]& d" B7 I4 F- // class Dog{
4 R7 t0 v6 _% K& Q, a7 Y6 N# H - // function __construct(){; c' \7 ]# m1 H3 y+ M
- // echo 'dog in cat!';
3 g- T& _8 b, P- s& y - // }) r7 T( F. f, W: X* P' F& Y. b
- // }
( ]6 @+ Y- X- u8 G# ? - class Life{
4 F# p0 c! j _1 x, c1 F - function __construct(){% v( f! n9 Z+ z/ \% l
- echo 'cat life!';
* x8 T; v6 o e+ F( t7 v! W7 q - }, ~6 y" K- u& `1 O6 t
- }
5 Q& P7 m4 b* d6 p+ J: i3 `: H - 7 t( U5 D& @( c& b8 O3 j4 l
- use animal\dog;
" Z% q/ O4 R9 v( V5 \ - new dog\Dog();
复制代码 2 Z$ H! |9 a0 P7 \
如上,使用了
7 i( m- R j+ Hcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
; K; Z/ S5 l' Z( F简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 " R) z% \; ~0 v& v* I7 n4 I! n
( v1 f: Q& I: Q' ~4 j& X& r# S( _; n: D
3 c9 Y3 S9 O0 X" v, q. w- `" c
* [& m$ e) Z/ k; Z9 R* R
|