以下皆为本人自我理解内容,如有失误之处,请多多包涵。
$ h! c$ F6 a0 k, o文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 3 z: o1 S9 C! M9 y
+ k) e6 @7 y# n) ` Z
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 5 d# i& c' k$ n% f
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) I# C9 u. J6 m( e: l6 a- E# t
结合使用方法来进一步理解它的使用目的吧。
2 Y& o% ?0 W7 h9 \( S& V/ I
2 \% s k. c1 X4 \/ N" f% @namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;6 A: G0 M) J8 |7 Q
- namespace One;
& H# }, y* m$ {2 j/ N! _ - namespace ONE;
复制代码 5 K! }6 c# \; a
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) ) e2 m, [5 C7 ?
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
9 {7 b- |& S( g2 ~% D - class Person{$ R! C x1 B) y4 K* k2 p# J
- function __construct(){
" C$ Y) K) O9 }5 b t2 Y - echo 'I am one!';. \' E% A- r; [# v; V. |' Q
- }
% [; B9 g" v* ~. @ - }
复制代码- //name.php
" N# R5 M" J4 z) z - require_once './1.php';" u( p/ u9 |8 }6 S& E4 a+ y' z9 t
. [' s' G( ?7 R2 g7 b4 D1 L- new Person(); //输出 I am one!;
9 h- Y1 V; u1 z$ l! A0 C - new \Person(); //输出 I am one!;
复制代码 ) j g# x5 Y% O/ B0 l
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
1 J* r( _0 {1 c3 x, d* M - require_once './1.php';
( p2 M: B. q$ v* [8 Q) |6 C% n - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
5 w! {& U9 j* L# ~6 P* r2 `7 ~4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php & ]. H9 {# _" E, O$ [, h
- namespace one;6 f& s1 l0 ]" \* D" C1 w; z9 f7 ^
- class Person{& i0 m2 q V, A, g5 y
- function __construct(){
' f7 D( i' |, W0 b1 L8 j - echo 'I am one!';
5 q* x9 P2 J4 d( u/ O" d - }
& O. z3 m' d9 L2 }& }3 ^ - }
复制代码- //name.php
1 V1 H' n+ G7 g6 V1 J - require_once './1.php';1 s0 k# `# o" u
- new \one\Person(); //输出 I am one!;5 |3 }. o1 O' y
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
3 g7 I: M& I6 K% L- o8 N可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 / m& m2 ~6 U* Y
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
1 D) y% f- W r- //1.php
5 J" M% W: i" e) L2 B \* i# T& k - namespace one;
. g, u$ E7 _4 f- ]5 c" p: ? - class Person{9 z( w- f* l! [) w. a, _
- function __construct(){! V L" z$ _' M1 G8 K7 `
- echo 'I am one!';
! i( Q4 |; @+ }+ [; o( |/ L - }6 n& b) [) c0 o6 ?7 |
- }
复制代码- //name.php
9 v' p4 B w9 m# c" N - namespace test;
$ Z0 H! R" C8 l4 e% h/ e5 P - require './1.php';
7 A- Z8 `' W8 S: G - new \one\Person(); //输出 I am one!;. _4 Z. e5 z3 @- h4 d
- new Person(); //这里结果会是什么呢,猜猜看
" {8 ^8 J9 i/ P- C" H - 最后一行结果报错:2 x+ Y% I' ^1 ~+ K. \- J2 q
- Fatal error: Class 'test\Person' not found
复制代码 ! {$ o6 P f5 ?1 v) a% e8 E
: ~( M9 R1 i0 Y首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
* D) n( k% G s" `: J( J# p* C) f结果报错: - Fatal error: Class 'Person' not found
复制代码 & _9 D) \* F2 f# {2 r% ?
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
2 p& a4 i; Q3 J( w0 W& U6 o - namespace test;8 s6 D) ?2 S5 g0 Q4 H* t6 u2 `
- require './1.php'; 1 j$ G9 i* A3 r! `; X! B! N [- [
- 2 s N/ E, n) j
- class Person{2 p) k: `* m, M! C! A
- function __construct(){ h4 g5 [7 u' v: j
- echo 'I am test!';
: V Q2 K* f$ j$ V1 p - }; p+ P* m1 K; ?' n& a9 @, ?7 H
- }
2 ?. ~1 v6 N8 Z0 S; S& H
& }! x" R) x1 d5 \4 Q8 E, X5 d- new \one\Person(); //输出 I am one!;
2 K( K4 o- V5 ]+ `# H0 b8 J - new Person(); //这里结果会是什么,自己猜猜看
复制代码 / l7 M K6 V& A% n; ^6 V
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php) _# P' F& j; \( Z# F* [
- namespace test;! _) r- b- \1 x5 J3 G v" P' y
- namespace one;
" R! b U9 t! `, c' G - class Person{
O# F' l% S; i9 A( P% N - function __construct(){* \4 _5 ^" P7 Z# ]$ v
- echo 'I am one!';
# v& z' q) z" L1 C - }
& i5 ~' e- d, n* L/ n - }9 D6 N. E; [) W" [( V# u
- ( n% F* F1 R( u6 Y
- class Person{1 I' U* A& Z \8 E1 E7 {
- function __construct(){
* B) y& q) b: J7 r' L) Z8 D: F - echo 'I am test!';
) \% K* b0 l, Q2 p6 w/ m$ O; I$ K3 ` - }; t2 c% R+ w0 R8 \
- }
复制代码
/ m6 e/ r) m- @ O j5 ~2 k无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
# |3 H9 i. o( u, D0 b( B看来简单的把require理解为替换,在这里行不通。
" N4 @% S( d2 C0 u, L: d6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。. S; ~1 j* h0 H e3 W) u3 |1 e
- //name.php( Z+ G2 U6 E3 h3 H4 D$ r
6 m4 N( C1 M7 R: o+ D- namespace test\person;, R2 N. k* G- h- A
- # @5 `- p$ t% \# n" P7 |' s0 j
- class Person{; w. ]+ I5 R4 I! A- J, Z6 X
- function __construct(){) [( @* i/ Q' ?: ~0 r7 p3 A8 ]. _
- echo 'I am test!';0 s, ?6 a$ f9 d e
- }
" y, { |# I5 b5 e6 \ - }; Q6 p* v1 C6 ?4 t7 ^3 [4 _
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
1 `$ Z+ j3 c4 T0 }# P不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
! z; v$ @& H# {0 c* E7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
" q# d3 G) U3 A5 `& L; y - 4 x# {1 x4 q; |; @' B0 C2 V
- namespace test; q5 X! W7 J" Q* k5 g8 J
- echo 'zhai14';9 ]& ?6 ^0 K+ I: j) W7 O6 C, M
- namespace zhai;
, i( K6 o! i. E* k9 ~ - require './1.php';
复制代码 / p' n/ h% {! B' U/ {, v4 ?# T2 L( r
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 / a, V! [; R( ^7 b" @5 p" u
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。7 I D2 H. ]* g& X! \: U. N0 v" w
- //name.php' H9 G# {3 p9 `& {& Y) j0 R& {: X8 ?
5 N2 ^8 r2 L9 E! A. ]- namespace animal\dog;9 Z# o1 N4 S1 }% ^; k3 \
9 h; e1 Z* i& | [' @2 R; v$ X. j- class Life{: g3 Q# p0 c( E. J/ _2 A3 h
- function __construct(){
. }' d4 |, F% d3 M+ L2 X, g7 v& a7 e - echo 'dog life!';
. [" S" ]9 A% m" a. w* \% ~" Z - }: }4 S$ m7 M9 B0 Y1 v' [
- }0 [3 v# u1 h6 w! z( |
% d( S# a6 i; z& s9 s- namespace animal\cat;
, @. D/ g& C, w7 [5 m
2 |$ [4 E- M0 Y; L# c1 k3 l1 v- class Life{6 a. q' {3 j# ~0 ]7 z* M
- function __construct(){
3 c$ k% z( k$ w& m) R* }. } - echo 'cat life!';
8 v- S* W- r, p6 u - }
0 y" m7 z+ t1 O# i, s - }) R# i( c) D$ X1 l; L
1 y, P7 `: i, ~7 a9 ?- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间8 q/ M* K) N1 x- Q% L+ d# n
- new \animal\dog\Life(); //A$ y7 u) F4 K9 Y- q. w! }6 ?3 v, Q
$ a5 S3 P9 ]5 q5 _5 W) N; G- use animal\dog; //a
- n' P4 K& ~9 S0 ` - new dog\Life(); //B+ G6 `0 m5 p5 S3 M
* j3 q* m3 M' o( d- use animal\dog as d; //b+ Y P$ u: g2 y! d8 y4 h1 j
- new d\Life();
复制代码 , q' B$ I! q5 _- M7 p
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
. [( ^/ _3 R/ {- b! V通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 7 o6 Q9 G" E3 H$ n2 L
相当于
5 n+ T* ^5 C2 i* w1 u2.namespace后面不建议加类名,但use后可以。6 n# x+ B' [$ q+ H
- //name.php, R2 _) J' b1 `) `
- 6 F5 J, B. A! h. S
- namespace animal\dog;
. P- r8 m: @8 T3 p: f
4 @# ]! z, m5 j% u# V; D/ j" H, Q- class Life{$ h" u( J1 g* t: V' v0 O& Y1 D2 x
- function __construct(){
; l9 R3 {; J% A! S. b1 r - echo 'dog life!';& m/ l7 r8 I( ~' p3 a
- }$ O4 U: l& T7 _
- }
$ O& @3 e( U; [3 t# L* Q - & {1 f5 O, _' s
- namespace animal\cat;
T; H7 D# A: ?' T
- N5 v4 G( ]% E- class Life{
/ J, w7 n$ M' b! w - function __construct(){6 R- E* Q5 ~( `* ]: A0 \
- echo 'cat life!'; x% T( w' S i# E7 X2 W
- }: I M8 m; D0 [' N- S' \
- }
$ e3 n( b' B; @- o8 [* ~( z - 6 G4 H9 f. ?; @
- use animal\dog\Life as dog; ! v7 k- {/ c( g& e% d
- new dog();
复制代码
6 Z+ j3 y$ a8 S- H如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
7 @$ ?4 J, `) J) S* c因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php5 G' b: C( N' V! G6 b
- 5 U* H8 Z- T \6 |
- namespace animal\dog;
2 D4 v6 m b' u3 G$ O
, H, O0 A1 B s: @# l2 B+ p+ [- class Life{4 l1 q* g$ q4 x8 ~) T# F2 o4 @# R
- function __construct(){
/ w( E- \3 l) n" J& h1 K - echo 'dog life!';
# q1 o0 l2 \$ o3 H - }, ]3 N& {; F# p+ @
- }
7 q/ v2 @% C) a% _ - class Dog{/ D( N9 u O( O- j- `; g
- function __construct(){
) x5 d# F# J5 b; G8 u% v - echo 'dog in dog!';3 G9 l. ^4 ^2 ]3 x# S
- }
/ B! p& o% |; z) X1 U7 m - }0 `% R/ n R4 T; I
" U% C x3 f& `$ E0 ~- namespace animal\cat;7 D& J r @& b3 D
- 1 Q2 @5 u3 F0 l
- // class Dog{ f: h4 i7 }' \* g
- // function __construct(){
3 m+ C7 z3 S' o. W5 n - // echo 'dog in cat!';1 K; d2 x' P0 v) M
- // }
7 B; l, J# n( c, R" J$ q) k" Z - // }! O# W* y3 a+ b
- class Life{( x& z5 o+ q: b, P9 w& ^" M6 r
- function __construct(){5 ]. f: _$ v6 O0 z4 f# h% Y3 g
- echo 'cat life!';% R/ k" n3 e' ? @5 \" p
- }% X. U6 n) S0 o
- }
. O. N* m# v- j P, B7 ] - 6 R( I+ H! L) I' B
- use animal\dog; 4 r0 q! U4 J4 C9 d$ F
- new dog\Dog();
复制代码 , s5 M& h: c. D# U: r7 _: M
如上,使用了
: S/ y* Y- u# h. scat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
! L1 L0 ]3 ~ p. @3 @9 e简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
+ O( U: L( J# N: K8 U9 K" P* R- _6 K4 u4 D6 ?+ ?# ~, m
1 r0 ?# L2 i+ f% x- D: a
- k% D8 F, b! i1 p4 W) d q9 {
, Z5 m2 g2 H ^+ a& c |