|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
: m% B. h5 }/ \/ T; h, r文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
) M) E+ i1 G5 n3 E9 R+ ~; t1 f7 _ k0 E0 O% x
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 8 g6 H8 ~% l6 d# ^/ \: o& x
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
% O* t2 r+ q: [- G: m) i结合使用方法来进一步理解它的使用目的吧。 ! h5 V6 [% H( x* u( }4 B
3 c9 n5 f' T6 R6 i6 z3 dnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
0 B3 Y6 J* C4 o$ M( |8 Q - namespace One;% m# Q6 O' b" r* j
- namespace ONE;
复制代码 # i a9 u! F& x, |+ K- @, ]* P
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) % [; R3 M4 n) l" Q7 [% r
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php : _+ B* V6 F$ r0 h% L3 g
- class Person{% `3 {) H, C F4 H( Y* @, w
- function __construct(){
6 C- o6 \+ @. F - echo 'I am one!';
! g8 R- x! O5 r! j) {6 I3 M. `% _ - }: z4 [9 G- ?- @8 b: x( l- [
- }
复制代码- //name.php
7 b: A2 R4 ^- c$ B- P8 D2 Z - require_once './1.php';
7 Q9 f* X1 M' j$ b: @
5 }) E* V& z) U6 O" S, K- new Person(); //输出 I am one!;
( \1 H3 c5 T u9 ^1 W3 S - new \Person(); //输出 I am one!;
复制代码
& L; `, Z+ ^- W( C; T) t3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php; h% W3 \) R" X0 S- b
- require_once './1.php';
" O/ ]; v6 e- v9 P- W4 n - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
" Q4 Z3 ?4 x* {' |4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 3 Y+ [; q' o9 q$ ]8 c. z+ ?
- namespace one;: _4 V# W& x2 A, U |
- class Person{1 f$ ]5 E$ w. G4 k4 {6 a W
- function __construct(){1 z. l/ M+ i. ^; Q$ q* u- S
- echo 'I am one!';
# q# B0 M# q- J$ i - }& r) [* \3 |- M$ Q, w: ^* C
- }
复制代码- //name.php
5 J1 ?4 k* y/ ?' p1 H" l% w+ Q) J( p - require_once './1.php';
- o9 d0 |5 o& V ]4 U" i* g9 J - new \one\Person(); //输出 I am one!;. O1 k- P' y# E4 p; u8 A' V7 }
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 4 ?: v) r, [' k9 u/ w
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
4 Z' b: ]: T- L" F9 T5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
* d o2 C- B2 U6 V d' ^- //1.php % m4 L; K( ?2 g- ^. b% X
- namespace one;; H# G4 O% I. q/ l2 a' _
- class Person{
; j; u* n# U+ ]) M9 b8 q& h, P - function __construct(){
# q3 K) B; I2 X0 o1 q9 g - echo 'I am one!';
) `$ V* @- u; |- ^' Z* Q" M) h - }
* m" A0 b1 \1 l4 z; @ _+ _/ M - }
复制代码- //name.php- r5 Z: L( e0 b2 R8 |/ V+ m" V( {
- namespace test;' a; \6 G9 G- W
- require './1.php'; # ?! h% r2 e# M% x: \: J3 ^
- new \one\Person(); //输出 I am one!;
4 a9 n( `* }& U. \0 B0 ]6 Q/ p - new Person(); //这里结果会是什么呢,猜猜看2 k3 ?& K) M5 s6 |2 C
- 最后一行结果报错: Y, `3 J3 N3 U y7 g
- Fatal error: Class 'test\Person' not found
复制代码
5 H6 {9 \" h% Y+ M$ w7 v" d8 N( @
$ X8 m/ p; A4 ] ^4 M* e+ k8 ^3 H首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 * _" C+ E- \2 U- f8 l
结果报错: - Fatal error: Class 'Person' not found
复制代码
. ]& ^; N! h* T接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php0 R+ _% g) @2 F1 r# t( C
- namespace test;
! z d( j. X; t% A+ i2 Y4 R, Y - require './1.php'; * w% p4 ^( y) x9 ~3 k4 U
- , N$ R7 ]6 {+ R+ E& V0 b
- class Person{
: \. d* F& @7 N1 o5 `( { - function __construct(){1 D2 x- a3 A4 l' n% E. b5 l' h- M3 W
- echo 'I am test!';
) c* k Q- H6 l, L5 }4 W - }* Z) H3 D6 W+ K( e7 q0 f# r" W
- }
- p$ V3 a1 |- T( U& z( Y! u - + y q7 M" R! o% j1 O: ~
- new \one\Person(); //输出 I am one!;) R! I; v1 D: G( u0 L) J4 t2 i
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 " p1 O/ X5 [% ^
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php7 | ?6 P: B, a4 ~- A1 l
- namespace test;
1 F" F$ q6 k. @7 v% n - namespace one;+ ^) x8 \2 z: v, l$ m6 ~( D
- class Person{7 @: Z! H9 T% H* Z$ H* N* w7 t( ?
- function __construct(){# t3 K- i+ W& \) F! U. \: B; z9 t
- echo 'I am one!';
7 h1 F' z( u7 z8 S# h - }
5 L4 j! K: i# ?9 s; W/ W$ w - }6 v/ U" `% O& n2 S
- 1 L/ j9 N5 Q. n7 r; g9 S; c
- class Person{' D9 H8 y. j. v
- function __construct(){: x @* m) w- h- l1 a0 Q5 n$ f
- echo 'I am test!';
Q% L5 k' K. }6 _4 | - }8 E! j/ ^$ F7 ^! k
- }
复制代码 6 R8 }3 C" i$ O
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
$ Z! J* J5 D7 R看来简单的把require理解为替换,在这里行不通。
4 M) U# Z; \. j x- M6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
! |" o* `, i) c) R8 [- //name.php" |: }( c8 Q% a s
- 4 t! y; D7 O( `5 |( ^6 o
- namespace test\person;& V6 ]7 o* R4 o0 ^2 F9 T2 B( B: V
- . w5 a8 D. _# `0 L: d' ~
- class Person{
$ Q$ u1 N- t: a% s, L& K9 B. J ]' Y( A - function __construct(){
# K' q3 J# \7 o - echo 'I am test!';
, x# X" [7 C; T! X% E - }6 t2 d- P. J$ U: Y5 X8 y( C
- }7 S+ g- r# F/ `6 |1 b- p0 F9 g
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
; j8 ?, z1 A) S4 M不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 , N' Y; R: y7 k3 f! S4 C- l
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php% S# `1 y$ c' `
7 g+ a; u" r0 c9 e F# [/ x5 u- namespace test;+ M9 U" P" I' g+ I
- echo 'zhai14';$ {. m. U) d. u8 z% e4 \
- namespace zhai;4 ]" c* Z. m! E4 P! u a
- require './1.php';
复制代码 * P, J; ?1 J% W9 t# l% {6 s8 \& `
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
% C! f+ v2 b+ U: N& T- guse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。* H8 b, F. `$ Z5 `! i/ v" ^
- //name.php) B" J8 |1 r) U! B3 U) Z1 T, t' G) [
1 d+ @( s& c# g( P) }- namespace animal\dog;/ A, N: r4 R6 `
- R2 l1 B% R$ v; O, g, s) k
- class Life{
F4 H) \2 ^9 p& a" g - function __construct(){ H2 T! O. n9 j( t+ C, u
- echo 'dog life!';) P4 P" c% Y e& }- l; a/ ]2 ^
- }) }8 s8 f% U% I2 S! o3 D
- }: E- o F4 a5 C& J9 P/ l+ H$ B
- & k1 N. F2 y. V5 o- M
- namespace animal\cat;
4 w# e1 t2 O9 F+ z$ M* f# J
/ A/ x- O) T& H* t$ x; i- class Life{
) ^; W" A; t: h, n* v0 y d - function __construct(){ j7 C! E6 Z" q2 N
- echo 'cat life!';; s0 h2 ^$ `3 v7 v' _
- }0 f( x' V& l! X' \4 F U( n4 m
- }
, W1 Q% N- e# Y& `: Q - : N% R4 `7 i2 e5 x% a; ]
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
; q) w8 F7 b! C. f* T q - new \animal\dog\Life(); //A& d( b% T. ?1 \2 ?! m6 X8 Z; J
" q& i# C" H' L& B/ j- use animal\dog; //a
; D [3 Y# R2 |6 P - new dog\Life(); //B6 g: a$ H3 S+ W( h1 L
7 b/ ~: {/ I7 W- p- use animal\dog as d; //b5 W' \8 e% ~' w/ c' V H
- new d\Life();
复制代码 $ t/ V) A2 F* e
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
5 Z1 r; T( _8 v6 z! I- `% {通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
% m4 Y6 H% h9 i. L8 ? r/ W% L相当于 ! Q S. U- b. q1 K
2.namespace后面不建议加类名,但use后可以。) R2 V) { l# P2 y% t, p+ b) s1 n
- //name.php. A7 z7 S+ w; ?
% J* k: t0 B4 S5 z z- namespace animal\dog;$ d7 A7 v" a7 ~' T1 ?2 }
9 a! w# }8 i8 N4 M/ |) |- class Life{! t) j% f5 r I3 V6 B# A! ^+ q
- function __construct(){) b5 ^3 }' u$ z5 _4 c! o
- echo 'dog life!';
4 b) y! I3 r: g9 r; M. n. { - }! f* Z: z; g( ^6 a5 c1 e
- }
# P0 J, U- `0 Z0 [% e$ r - , |3 j4 ?% U8 J2 C9 G
- namespace animal\cat;, S* J1 z$ s- z6 n+ u; q
- $ Q& ~% t* ]$ D
- class Life{0 p4 R) i& v0 n% ]5 e: F K
- function __construct(){2 M$ W+ E5 }- x* z/ {1 ^* S3 }. T" O
- echo 'cat life!';
* o$ F0 W+ ]( J) j0 q+ y0 V - }
! X; i1 [9 j. j% z5 {$ | - }
1 B# N1 o, K, c- j) l5 |8 u
' |" \) _7 q: Y- c m" F5 s7 `- use animal\dog\Life as dog; ( g5 M9 S R# [1 a
- new dog();
复制代码
2 ?% }% B6 k* b- D" Y' }! [如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 - k% B q. q. g% y
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php9 V. o6 i O( B" Y( q
6 m4 i) }- J' V! {: z; d1 @- namespace animal\dog;0 `) K$ r/ c9 P' }, A
% @5 N- y) f0 X5 S, V/ K- class Life{: \. P7 T0 o1 ?8 P# J- U/ |
- function __construct(){
( w7 K; r+ h% k4 g5 v - echo 'dog life!';( k% d( h. Y9 |4 I6 y A6 {2 C
- }
& l5 V- A3 B$ [2 p0 w" Y. d - }
7 B3 a( g% X u1 f$ B$ P5 X - class Dog{; @9 U' C% g+ r( J4 L
- function __construct(){" ?9 d" k ^. k; h% [
- echo 'dog in dog!';
7 a& ~2 o1 ~- B& J+ R - }
( S! [$ K9 b$ D. c- s - }, S! y, r% o, n0 v3 ?* n, e% o
+ D) I: P. a3 Z4 L/ Z0 y$ k- namespace animal\cat;
! I" c' a2 J9 X: @- J9 L4 F7 k. ? - 8 o. I u- r/ z. e$ Q
- // class Dog{
8 K9 L7 u4 F. Y, x6 [! X( H6 @ - // function __construct(){% p( U* m# A4 F& `: f1 v( F9 L! v
- // echo 'dog in cat!';
$ Y6 v8 r6 N/ s' H - // }
! u2 i) I7 n: Z2 V - // }' I, d8 Y6 ?* Z- F( ~
- class Life{
0 x$ ?5 Q ~, f4 W! |& b - function __construct(){+ {4 o7 i8 z' Z' e) ~
- echo 'cat life!';
, |' f* d# ~& |% z* P' ~ - }
4 k1 o2 Q6 N/ ]2 R - }
: i. _/ t m9 I& V: B+ U - + |" v) `" M' \4 p! u$ J
- use animal\dog; ( @8 L7 Y' z+ S- }, [# M* t
- new dog\Dog();
复制代码 % U6 _8 V. _0 K4 ?( b
如上,使用了 ! j( L" X2 }& J6 p; G
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 2 w0 e3 C }5 h' |3 G9 L4 [
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 5 g( w( e7 B+ S. B( l- B5 T
$ _- @ O2 B6 l, O0 Z+ |. E
- L! w0 n: c0 ~& w0 o
9 F- W. L" C- V# d7 L# P2 w
0 X+ V: U6 O0 U2 r/ O) B1 }% G
|