|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
' w; I4 M& I: l \文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 0 R6 U E0 Y5 O" g3 O# \# T
& [1 V! [: h# S4 M8 |) N
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
, D( `% J& D+ n& H1 `据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
+ m, I. H' V2 ?- r结合使用方法来进一步理解它的使用目的吧。
& G& {9 |9 U' Z8 w# s
8 n' M r( e1 `namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
# e$ m+ [* h q0 p- n% t - namespace One;
6 F" {# O6 M* x1 e, B - namespace ONE;
复制代码
8 e& t3 g# j. U6 S" I7 \ a如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) : V# b, f+ Q C/ O& X
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
3 v0 A# ?9 t5 _$ C# f5 Y - class Person{
, k: ^. v+ u/ D6 q - function __construct(){! y' J& v+ N9 l2 ? _: j
- echo 'I am one!';/ p; Y5 w/ k+ R4 D; ?# Y. k
- }
3 H+ ^5 y: V# F, [; v. o - }
复制代码- //name.php
5 Q6 Z2 I$ Q0 h - require_once './1.php';' c' g f4 i5 W* I
- / o4 S( `1 t9 k
- new Person(); //输出 I am one!;
# ]8 B. G) @) g# a+ |& X" Y - new \Person(); //输出 I am one!;
复制代码
" F3 d% `' w( ?; }# q( \% A. O3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php0 Q4 E+ X" r2 E* {
- require_once './1.php';
. f8 J: N% z" j( `2 x - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
; J! _% n1 W) I" f8 S" b! s4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
" M3 U$ y! Q' I; N - namespace one;
6 @( J" y/ W) M - class Person{5 }7 v' D! c8 g1 X
- function __construct(){3 z! }& F5 l9 g6 M5 D8 Q6 z
- echo 'I am one!';
4 ^( _$ b1 t( Z: c' Y, M0 K - }
; O6 j% D3 x$ H9 f) b - }
复制代码- //name.php- U- i3 b: p3 Z5 m5 X% r
- require_once './1.php';: Q; m$ w# P5 @( r2 D4 @9 J
- new \one\Person(); //输出 I am one!;% e. D( f4 t G
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 & ~ G0 {: V0 x* M
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
! @3 U* {! E" G5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。3 E$ }8 W9 F# M' z" w
- //1.php
7 `# O, {1 E7 h' J - namespace one;
5 ^1 c; a! Z, H) Q; P. x - class Person{
2 ^; W8 k4 p6 ^% ?7 S - function __construct(){, u/ x; j$ r% l) a% |
- echo 'I am one!';
& I$ ^* f! d4 o! `& h8 Q - }! y* t4 Z% O4 ?# N' f% S, V
- }
复制代码- //name.php
5 @; L! S3 e- P6 D o8 I5 l - namespace test;0 p- w `% h, L0 m
- require './1.php';
$ K2 V0 j3 o, m i - new \one\Person(); //输出 I am one!;2 I9 y( n0 r3 d
- new Person(); //这里结果会是什么呢,猜猜看7 {4 r- t: v, F) k
- 最后一行结果报错:
5 Y6 | F9 H6 K5 e - Fatal error: Class 'test\Person' not found
复制代码
" e8 H& L# q7 s3 T/ A% n% g) _$ J4 J2 Y- \; p( F% d
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 * X8 o2 ~! H* H, v6 D' h
结果报错: - Fatal error: Class 'Person' not found
复制代码 - P9 }5 |7 r- S% o
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
& |5 ^2 n2 _- L0 x; s - namespace test;
# a* N5 k- p! X - require './1.php'; ( [& `1 _ @: s
- % E7 d$ Q! ]) s1 Z1 E" [
- class Person{9 Y' U/ ?6 R" @0 K
- function __construct(){$ f% H* `4 S# ]9 x) o" q$ }
- echo 'I am test!';4 j. `0 ]0 v5 f' y
- }
. J! `) \# @' ]' j - }+ |1 S' t' t! d' W- g
- * \7 d& t; ]; o7 \* W
- new \one\Person(); //输出 I am one!;
7 b! ~% z( |# X - new Person(); //这里结果会是什么,自己猜猜看
复制代码
$ _) k/ h! g# Q, r最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
3 y d9 G' K0 L& ]) O5 R; l5 n; d% W - namespace test;
2 N7 B) ?6 R7 N4 q: _ - namespace one;
) X) w2 g2 M. Q/ F. L - class Person{
- ~+ m8 z& f0 ~; n0 H1 S$ U - function __construct(){ J2 a5 L" \5 f5 j, n4 X
- echo 'I am one!';
i1 z3 P) V! q$ `; s1 B( f9 T( f - }3 t M+ A/ ^: ]6 u1 C$ F
- }2 m. _6 y! R$ c2 m) }" V- L
! a) A& j" N8 l/ [0 ^4 {- m" R9 D- class Person{* h6 V& |, p" B) H2 {
- function __construct(){
E# d4 k; G6 K0 H1 ? }( }* e - echo 'I am test!';% j' ]# X1 p- Y5 C' A& t1 u! y
- }
3 m8 q: P( c3 x- ], g8 Y - }
复制代码
+ J+ R5 H. D* `& _1 ~- \0 {无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
& y7 b1 S- f8 X+ d看来简单的把require理解为替换,在这里行不通。
0 ^# m1 f2 s1 b# |2 ~6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。 T/ _6 Z1 I1 [
- //name.php; f4 o5 c: O+ F2 c- p! V* i
- & P4 s! J: z' S
- namespace test\person;
) j6 C! i% f1 h- R- z& M3 [
8 R, ]5 s: A! X) i4 {- class Person{
: }6 D9 a( n4 h8 n! z& Q. w$ P - function __construct(){- R9 l0 S4 G3 t/ z; N4 [
- echo 'I am test!';
9 H. A* q. |: ^7 K) O - }5 n8 ~ y$ G2 \' b4 b* @
- }
6 q% P/ L! O, p+ ~ - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 3 e( R ]2 f( @; z& l/ n+ R4 B; r
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
. ?( C5 {# q2 U) z7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
2 {# q, Q3 E4 V! }& D& l
5 _$ V% D- |; r+ G$ Q2 p, C o- namespace test;
5 u% Y1 g" d6 H/ X5 I* \: [ - echo 'zhai14';
4 T; M6 @- I% }! F( a: d - namespace zhai;
B @! m( ~, V y3 P# l* o# ^ - require './1.php';
复制代码
# A8 C' G( e, C* {php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 " p3 K# o& d. l+ a
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。, P3 `' b X+ t, ]* R3 f
- //name.php0 o1 u! G! P; J5 L. H- u
- : x9 E# j3 H9 y0 Y! j9 J$ Q
- namespace animal\dog;. T- @4 E2 R, w3 m+ @
- * R. M+ j4 r% u1 {9 B
- class Life{
. ~2 C! r. _: G - function __construct(){
: K' L( \6 L o+ ` - echo 'dog life!';, E S/ o2 ^$ H( v6 d7 d: f& A
- }% ~5 q) h1 F5 r7 z5 V, u
- } c; q! i. d" z( U
& Q+ }- t; {- h0 @/ w+ k- G* X. q5 a- namespace animal\cat;
- H" f5 v6 S. q _% L% Q
5 v/ p z, O0 g- class Life{
6 N/ D1 N, J3 u' x - function __construct(){; b1 r8 g4 u% I# T# ^& f
- echo 'cat life!';4 S! J# O& S, b7 R
- }
7 W0 W l( @* S* [ - }) o1 L2 D# `0 Y. ?# [2 w F3 i9 E
- ' q" e ^/ Q0 ^8 U+ z
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
- m1 f+ N& ^$ g1 b; F/ J - new \animal\dog\Life(); //A4 o: r9 a. ~3 Q7 e/ {+ @" y
( O8 n7 z8 T/ R) p5 F; l- use animal\dog; //a
$ i: Y1 L4 c. ~- o; d) V3 Y - new dog\Life(); //B: \ A% S8 C. R: }) c7 N
8 v9 P4 B( r- z0 h% @3 Q- use animal\dog as d; //b8 R8 I4 g) p2 t0 n3 i4 C9 D
- new d\Life();
复制代码 4 B; V' B5 n) E
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 3 ]( M9 x* z; `
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: - e% T) L# e& y* O( y
相当于
+ a) r4 b' h8 |/ V' Y9 r6 i) j0 r2.namespace后面不建议加类名,但use后可以。- K W- @, ^& n, m$ v
- //name.php
4 ?4 v- U4 ~% P$ j# o6 ~1 Y4 s - ) [6 C1 C; @% x$ g3 k. E& o2 i
- namespace animal\dog;. m( J7 \/ H+ }2 ?: ]: B# C
- + B4 B- U7 i, w' E+ _) `8 e4 y
- class Life{$ a' `( B2 y) L% V
- function __construct(){6 f& _6 ]9 d/ F9 U; j" {& h% v
- echo 'dog life!';' y6 \% S2 b2 L* H
- }
; k& I; W5 m) M1 Y Z& i5 i) w - }0 ]/ b9 J; x/ Z$ u' T
. i: ^6 u2 G+ i6 v" b, c# n- namespace animal\cat;
* b: H1 j' W/ W( f) d+ @% s* O - " A. [# b% I; v- e+ e& u9 P6 O
- class Life{ D# @6 H& _" l, x
- function __construct(){
% \7 o8 U0 K! S% c7 o f - echo 'cat life!';
8 q4 {+ x! ]6 a - }
5 Q* X% p3 c0 Z m$ S) f: | - }$ p" H' L- L# R6 j5 R# n
- 6 ]4 S6 Z2 Q0 T" i
- use animal\dog\Life as dog;
- p' q6 I- I4 P4 @5 ] - new dog();
复制代码
4 ^; _+ Q) \+ C& u" F F如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 , r3 A/ R* b8 A
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php1 N9 E- g! B) J; K
4 a( l5 w5 y* s% N, ~, k. ]- namespace animal\dog;) |$ `4 ]( a$ u
; u3 n4 B0 q% w# A' L- class Life{6 I# g# i+ h4 S ^0 y
- function __construct(){* ^" D" X; k. N/ c+ s6 p& ~
- echo 'dog life!';
& q' ^9 X- b( f0 s* R( r( m: }- l - }
( s& l# r0 ?; a - }
! n, Y0 p! {6 |+ k6 \ - class Dog{% a8 K# v" Q% i1 o. u
- function __construct(){
2 q, b5 @! e$ k: q3 b - echo 'dog in dog!';+ V. Z) v; m# X! y6 a* c/ b* c2 v* t
- }
- `* w8 n) @1 } N - }
% l% i3 E2 l$ B$ T% `
3 X8 o" P/ F( V: `7 j- namespace animal\cat;7 W5 o$ Z K8 P! m' e" H
- 2 M" V6 ~8 E+ ~0 g. E
- // class Dog{
4 C$ o$ U/ p9 ` - // function __construct(){
3 H7 r, l2 W. j3 q% m - // echo 'dog in cat!';
" F8 y, d6 y' p, ~9 N- | - // }
4 J A, O1 F6 y8 \ - // }
$ k( {8 b0 M# A& A! x' } - class Life{; @# i( s( j- j, _6 U6 q& a6 I
- function __construct(){
1 ~% \. _' ]( E. v0 ?$ y - echo 'cat life!'; ~' R. _! _$ I( b% u5 O! t0 R
- }* V! J+ `* i8 c/ n: s% M' e5 _. @5 u
- }
/ a' E" [ ^0 ^8 H* n& J
6 |! C: L9 H+ r5 g) M" _% [- use animal\dog;
, D) J. f) w! F/ D6 n' f - new dog\Dog();
复制代码 6 P( h: ?7 c; q, n) L+ p
如上,使用了
( C: j7 Q4 p0 M$ G5 @* D0 F$ Hcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 # c4 J9 d5 R9 E) I6 S
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
: ^# ]3 J+ \4 D, |% L* ^0 d6 f( v7 _& s) t; D O# W# |
+ F& a' A! I- j8 a9 |3 H. x( Q1 Z- o; c
' i( O& i' r) @' y' } |