以下皆为本人自我理解内容,如有失误之处,请多多包涵。
* P) t; L5 {7 J D* }+ S2 G. l5 O文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
5 D r: V8 H0 B. `; |( }4 X4 C2 p0 T3 s! s
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 6 y2 N% f6 n2 S. ~% f2 {
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
3 ^. x ^& L( q0 W# M结合使用方法来进一步理解它的使用目的吧。 ! j* }$ O# r' c* b3 Z3 g% q$ {. g
( q5 G) F. p+ n0 v3 p" x: Bnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
p. q0 ?% l0 g \. ^2 W - namespace One;
X$ X- r2 X) M# m. ^3 t3 d1 x1 v - namespace ONE;
复制代码
% `$ t# t9 ^6 O; \1 I如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
7 Y* D( h2 T, z2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 2 G/ v% C/ V8 q1 x# T7 J- u
- class Person{
! N5 _: s' g3 U& T2 O" W - function __construct(){
3 S" \9 j8 u, P' q - echo 'I am one!';
/ T, L. d; j7 f( M+ @* R6 Q - }
# R/ O% Q6 \4 X - }
复制代码- //name.php
1 K1 `# _& o3 m" X' l - require_once './1.php';
0 V& J0 e6 w& _ - 1 {( \$ E3 g5 W& N2 z
- new Person(); //输出 I am one!;1 \8 }8 U* I* f# ?* \; D1 j% e0 a0 \
- new \Person(); //输出 I am one!;
复制代码
; k8 n1 j4 T: s; E: Q3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
& ?0 ~9 E( C! V& b8 R ^ - require_once './1.php';
2 K, e9 U- m' E - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 # Z, `2 `4 |" X" g% `5 B0 h
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php ( P* i4 I9 r" Z9 j
- namespace one;
3 R# F* N) J( k/ i C5 L- a" m - class Person{1 }! a$ {9 |0 d/ x+ H* q8 s) x1 j; r
- function __construct(){
/ w' ]# |4 A0 |! G - echo 'I am one!';1 C: y, V5 s; n
- }% n4 K* ?5 Q6 I
- }
复制代码- //name.php0 y1 e+ q+ i2 N4 N2 t* ]
- require_once './1.php';
, Z" M. }1 Q% u+ k - new \one\Person(); //输出 I am one!;
2 [; \, E, a2 Y+ ]; G - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ' e% B1 ]: O2 p6 g
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
: D5 {; o$ q/ ?$ n8 F5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。1 U, z* k, y0 V; K
- //1.php ! p' q6 n" B1 U! I" l
- namespace one;1 n! ]5 e, Z. g7 A v1 B
- class Person{! o5 f9 G$ g; l9 f
- function __construct(){
n- j, P2 W8 i8 ~% C: i8 J - echo 'I am one!';. B0 d: Z, F4 @# Z; i
- }
l- C% N6 @; s( k0 b' ~, X - }
复制代码- //name.php
% ~; o7 T' k" p* s n/ W - namespace test;7 M. c9 }6 O* x: ^$ }
- require './1.php'; 2 Z% a3 n# k @' V, f
- new \one\Person(); //输出 I am one!;
' s8 I- v; O4 O7 v# y - new Person(); //这里结果会是什么呢,猜猜看
& l3 J# o+ T; q4 ^; U4 [8 O# f - 最后一行结果报错:$ X5 Q- r. {2 |) X
- Fatal error: Class 'test\Person' not found
复制代码 0 Y9 v2 B! V! H# j1 ~
" W1 w" D/ L, E* `
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 8 S9 W$ L8 ?5 S/ T
结果报错: - Fatal error: Class 'Person' not found
复制代码 * g' z0 b) ^5 w* |. F4 Y
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
+ _7 R& O2 P5 y - namespace test;
) \6 g3 _% P4 ^6 Z v6 W& P - require './1.php';
/ u8 a% ]6 P$ Q7 \, T2 K - % P( k# H$ U$ z, |- B6 u0 }3 \
- class Person{
( s# o# M$ E- L$ o& @ - function __construct(){
0 G! B$ P3 O# w$ f' `. F/ g - echo 'I am test!';
1 b6 i7 I, C6 \% @4 A% d" H {/ Q - }! d' j; y4 }; o/ F. D
- }! k3 n2 E# a& T! N+ x/ N
- ( _* A2 e j# u- J* m: c( h
- new \one\Person(); //输出 I am one!;/ T0 j$ Y4 P3 f6 U( G
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
' Z7 s0 _$ c1 ~% ]( a, S: m$ q8 O最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
3 z n8 G( Y2 ^3 m3 b6 w& K - namespace test;
1 y# _8 `% j- ]1 ]2 M% k - namespace one;
/ Y0 T9 ~3 j$ s2 R2 | - class Person{
0 N8 L: l, Q. J6 {4 |# s a+ A - function __construct(){
% O: s; W! v5 `7 p - echo 'I am one!';
8 Y. C+ ]+ M' G- M+ C# g' X - }* \" k; d; e2 z( u( E' V
- }
+ H$ }5 b2 d0 L a. \) V
) j% L, L p! C& p- class Person{
/ d, F9 [* z$ ~7 [& v - function __construct(){& S# q N8 N0 Q- V% b- R
- echo 'I am test!';2 M* t. V L1 H
- }' n* [' ^. n' q
- }
复制代码 1 B7 Q2 x( B% I
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
% F( z! Z% w, s2 B% M1 f4 C看来简单的把require理解为替换,在这里行不通。
1 R: a$ F: A% ^8 r9 J' h6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" p( n; d( ?+ b8 ?. q- //name.php8 |* j0 e0 H& o f) q0 @6 C
) L7 G' v+ S0 H+ o1 C3 G& _9 l% A- namespace test\person;9 S" q5 m% p! [6 ?
- / e9 f7 Q% u3 ^. \$ {
- class Person{7 s! \. m7 j+ H* \8 l' L: d+ f
- function __construct(){# Z. V: K. [: f1 U1 j2 I: ]
- echo 'I am test!';3 q7 ~" q) i7 k+ K# g. }6 n
- }
; H* Z6 o9 J5 J2 V - }1 v: F; G9 A- x
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
# ~2 N# S% Y" z. \不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
% N% m$ q5 {1 t0 F6 _% {7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php F5 F* @- u3 Q
' t; C9 p7 s0 H* i0 q+ }" m. [) ^- namespace test; F8 R# f3 Z" P& K
- echo 'zhai14';
/ |! H6 i; f7 y - namespace zhai;
7 }: y, l. ^) u: | - require './1.php';
复制代码 0 d& r- R4 N0 ^7 u4 l0 z
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ( R4 t) Y$ i* X# |$ H
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。/ G: o, t2 Q5 f, H
- //name.php
* b1 U$ V! I& u- |, e6 _ - & h0 m0 s9 x1 j2 M1 [" x
- namespace animal\dog;9 k/ {. Z4 r0 N2 E
2 y$ l0 N" `$ j- class Life{
0 r! d) p2 S% |7 q/ F& c9 d - function __construct(){3 M+ t$ l( P+ L7 ^( E6 J s" U
- echo 'dog life!';( W/ Q, ~! x( u+ n( f; U5 i; S
- }# Q9 H; P g a0 ~
- }
4 h# A9 V! k B! w - ' [. c. r6 S- u6 I5 W, Q' M
- namespace animal\cat;: K! w! z; T4 c3 Q7 J' F; t
- ! S) K" w9 |$ [# a( L
- class Life{
! {1 S: [: j3 x' p' V; K% I- T - function __construct(){
% ^# n. g$ _- H! p* w$ @ - echo 'cat life!';& ^) g/ T( B" j* L2 S6 P2 |* ]
- }& t! w3 N T1 S- Y+ O
- }9 o# O1 J8 t- `+ Y; b3 R0 W; @4 Z
- / n- X! t0 D y5 w) s+ [8 B$ Y I$ |
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
$ E+ n: M6 D% h P - new \animal\dog\Life(); //A( o0 B* [! H* I# R) ]* p4 m y4 l
7 V0 h, ]% J* g5 Z: _" ]' b: B- use animal\dog; //a
- F+ t# p) {! u3 B; Y - new dog\Life(); //B5 F* P( m B( j- n
- 3 d2 ]& R# \4 u
- use animal\dog as d; //b5 _0 v- Q7 O- v
- new d\Life();
复制代码
( T' N4 F; R: H* D. c通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
; t$ {# r' T- V; f9 _通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 0 G7 \, R- ^0 G# R
相当于
# k& v0 m. T2 l3 V. g2.namespace后面不建议加类名,但use后可以。
% L5 j* f' K2 ^ ^$ D# g+ \- //name.php; n, V, C+ E# i1 b8 K
! i$ j- \( [# C$ @- P2 k$ n1 S- namespace animal\dog;
! \" c, D+ m( C" f) Y. m - 6 f; t) Q. y( n8 x- P8 b
- class Life{& F2 R( U0 M- ^7 C9 }0 t
- function __construct(){
. |9 z3 D: v4 G9 r8 {: r5 ^. b* y - echo 'dog life!';
9 @& j. j* ?# R) o' `! q - }
+ S; i# t, l* }/ H) d - }
: a' m; _1 d" e1 t2 y2 F - & {4 o6 O0 z+ b* L; V: V2 y
- namespace animal\cat;
3 M1 c2 U; a5 s* E$ X0 S# `
+ G, e, i- Q' o" C+ K8 R- class Life{4 H# s0 ~7 k1 _6 E+ N( f/ o
- function __construct(){
3 O, ^& E$ N$ ~5 ? B3 U - echo 'cat life!';
) V# J5 q6 H& r - }
, H. m( G% @; A' t - }9 g( y% |# U/ P6 ^
- $ d' Z) d3 F- u/ [
- use animal\dog\Life as dog; " H7 p7 |( }& C: v) [, g ^
- new dog();
复制代码
# A* ^. P9 R" h, F- }- X+ G如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 ' g% w, `$ V2 s( k H. x- [
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
+ W( F! p( G" q [& b - : e: h( h1 ^% {; R( @8 W6 ?& ?. l
- namespace animal\dog;7 c+ Y' l: K; d% h
1 N4 F- \0 o7 l8 Z- class Life{
# r- \" O3 y; {. Q - function __construct(){
0 H+ n6 t) B& n, Z6 Y4 [ - echo 'dog life!';' j# |2 m# R% }* L* Y2 R# z. r
- }
, G" C4 x1 M6 o- U- }9 g# l" W! T5 M8 i - }
* I) {2 V3 D" z+ @! y$ _' h - class Dog{! z; Y( f$ S1 G6 \0 ?* B$ G
- function __construct(){+ P# H# `* D/ y$ [; {
- echo 'dog in dog!';
) Q& W% N: p4 g0 W# r2 m) D - }6 @: w9 H/ ^" Z1 \
- }
( [- s6 @- }! {; G4 ] h& U& B
3 R1 g3 @$ L3 m* T& C- namespace animal\cat;8 a# y# p. C- }3 }" s9 @
! P7 R6 [, m4 y8 [# q$ l( i" D- // class Dog{
# e4 f4 Z; S7 G" x( L N/ Y - // function __construct(){
/ V: \, `/ ~. X% q - // echo 'dog in cat!';: X, T" K& }+ T1 f
- // }
! |+ T* l) M, P7 R0 m% y6 d( _ - // }
( b6 r( k) e3 \6 M3 r0 q) j - class Life{
( c# R8 F. t# c* r4 v% Y( Y- I - function __construct(){( |+ A+ w! f- d, c T, i8 R) o
- echo 'cat life!';3 m3 j, ~1 X4 G( i
- }/ Q0 S: [7 h. i+ J; F# p
- }
# k2 L1 V! t5 ?1 c
8 t) i4 Z( l& D- use animal\dog;
5 Z9 Y5 h0 q2 p/ {* \ - new dog\Dog();
复制代码 " V8 {5 m9 j% z, k4 a
如上,使用了 $ C% V6 K" c8 C0 m
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
: b! ^7 y$ Q: f* @8 F5 ?# O( |" B4 t简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 5 e# f; G9 J2 y4 ^: Y* `8 F
7 F1 d# Q) O1 c1 _8 v# |* {$ K$ Q! u2 c6 c }2 ]0 ]
5 Q9 o# ^+ n% Y$ P
( }2 i% ^( t# g- z |