|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 " V# Y7 K$ ~3 V" ?
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 9 V) w2 z% Z- M
4 T5 ^% |# Z' T1 Q使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; & o3 ~, G9 e& m- ?9 Z0 o
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 2 i( I- P( C2 @
结合使用方法来进一步理解它的使用目的吧。
. b- U9 a0 f7 ?6 [3 ]1 p
# e8 D$ e& [5 e; {namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;$ ?. o. C2 |. V# p7 ^; S
- namespace One;4 C8 f! n( {# X3 }# _% T$ h* w0 M& Q
- namespace ONE;
复制代码
# L" |; P* g" {4 r+ A5 `如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
3 ~! ^2 D" L, {2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php ! k5 D, ~% V; u
- class Person{
* ?/ Y" d! W: @+ |0 f( p - function __construct(){
8 R" e. w% N7 w8 M5 i2 H D - echo 'I am one!';$ b2 K, w6 K7 ^( O$ M( E r6 Q& |
- }
* W6 X- G7 I5 l8 ?; |, M: ]4 M1 A - }
复制代码- //name.php
W+ F: i/ q+ d, I5 X! ?+ @ - require_once './1.php';: ~0 P1 k- T* s! N1 x! J
- % H. f9 ~( Q( v$ D
- new Person(); //输出 I am one!;
9 _% o( j% R% R( X/ h - new \Person(); //输出 I am one!;
复制代码 : p7 g. {6 [- ~: S
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php; x+ u, H: t! q% d! J- O8 _
- require_once './1.php';0 X; R* z. h- J. \3 A
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
4 e( i9 x0 |2 b; U' ?2 U- v! e4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php # F' J! P' y1 T1 h( L
- namespace one;5 G9 ?1 F+ X( x0 Q! U
- class Person{" H3 u( Y7 ]4 L7 |7 O
- function __construct(){
. U" g5 o( ]9 p - echo 'I am one!';: i- ], M5 [* d( P7 _
- }4 L! A# Y, m8 o5 I% L9 t4 ?
- }
复制代码- //name.php! d' F7 s. ]% F4 n! W7 d5 [
- require_once './1.php';" @+ f- \* Q( b* |* o) Y" q3 ]
- new \one\Person(); //输出 I am one!;6 J" W9 z$ _$ W3 d, ?' ]6 d$ C( Y6 D0 N, D
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 6 d- O( J9 N" Y) i
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 $ z( n+ q* Y- @4 C- Z
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
8 F8 n, Q$ e! p5 N0 V0 A- //1.php
9 G: ?4 m; l0 G5 L. V# E7 | - namespace one;( w3 H- l) h1 w+ C
- class Person{
! u+ `7 F+ W0 ?& X6 {7 }* A2 H - function __construct(){
4 q; Z! `: E# G- z3 j& V7 e - echo 'I am one!';
4 g V) j \! k# |8 \/ c8 y( U$ q - }3 k+ g# G# ]) ^3 Q% M1 K
- }
复制代码- //name.php
1 ]' K ^ ]+ v$ \0 | - namespace test;
0 w2 a- K8 j. E- x4 g7 X5 f - require './1.php'; + K% i# K' h" v) N \& x
- new \one\Person(); //输出 I am one!;
8 q! T, C* g6 _+ M" I" u f6 g6 i3 s - new Person(); //这里结果会是什么呢,猜猜看% T. }# B2 l9 S( p, }! C
- 最后一行结果报错:" ]5 j4 q7 K8 H1 f# `
- Fatal error: Class 'test\Person' not found
复制代码
& q) b: J1 o2 \% P: j2 p' F5 m+ p, h/ S: x6 `
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 0 i/ T/ L6 C& c; C; C8 Q9 l1 y
结果报错: - Fatal error: Class 'Person' not found
复制代码
) V! F) N6 t# \5 s! _接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
, }" W! o/ P0 x3 M1 o5 x - namespace test;
. ~- X" G" f' C+ M. u# x. G, @ - require './1.php'; ; y" p0 n: J0 l; |
# c7 v; k1 ~ h) ?! w- class Person{+ I! O7 E3 I! |( ^# o/ o9 T
- function __construct(){
5 k9 @- g( J0 g- T9 P - echo 'I am test!';1 d+ g X& A0 m0 A
- }% q8 l- j" g& S3 p7 e6 ]6 W8 c m
- }
1 U! h* a/ }; A0 E/ N' a - / v, A4 s' S4 l& j9 _, m1 [
- new \one\Person(); //输出 I am one!;* s) k5 @' M# n6 z* {5 N4 D
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
3 ~5 X3 \" P. m9 [; G最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
& V) b8 j! y. h. W - namespace test;
0 `8 O/ W; ?2 m$ }4 F& X; R( f& f$ b j - namespace one;7 W% ]9 Z @4 S6 U' `5 [& w* @
- class Person{
* y1 y" ^: C0 l7 K1 \ - function __construct(){ g& W. k' V9 R( V# t1 n- X: d
- echo 'I am one!';+ _* m: l- ^0 S) r+ n9 \
- }
0 O# P/ ]+ w, c6 o* K - }
& x9 \8 W. }- m7 g% M* r
: A. e/ L: g/ M$ i- class Person{
' s% I5 c0 e/ `( [0 K |. Q6 x& u) m: k - function __construct(){
. d* ?2 g* }/ R) m - echo 'I am test!';( M7 j3 U8 G* L, V1 |. |7 |1 K3 P2 @7 B
- }
! J& {% I+ Q; y. r9 e& M# x. h - }
复制代码 ! u( j [- ^( r. X7 y1 O2 k3 `
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
! o" q3 v* e5 f看来简单的把require理解为替换,在这里行不通。
9 N# x% g2 b% `* q: d6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
9 t) {. [4 W. m! o- //name.php) p+ {% m& _6 b4 x- ? Q/ [
- $ A) Q" e% w6 x7 t2 \) w/ N
- namespace test\person;
P( t( l3 V7 f4 s& ^9 A - . R" M6 A8 y' ]8 i1 l& T3 a# U1 l' f
- class Person{2 M# @4 S7 V. \
- function __construct(){
0 `! b5 o( y' x7 s Z/ \ - echo 'I am test!';3 G5 h- A& i5 y- ?' H4 p4 p
- }
7 o7 j/ W0 d) |9 @+ ?3 R' D5 Y - }- c% T. l, }' y
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 1 s; Z; Z: Z7 h3 \# y
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 8 {9 {2 u- n$ e# E
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php1 g! d ^" r" k% Z1 O
K# t& U; R# S' Z9 p- namespace test;5 b+ T& u9 ~: }4 B0 e
- echo 'zhai14'; _- y( q; @6 h2 }* @
- namespace zhai;$ c d) C% c% z1 x& R
- require './1.php';
复制代码 + O3 W% C( d6 \; A
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 2 v7 J. K+ G7 q
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
7 Q n$ }% A& k N- //name.php3 E+ `4 l( W' l7 M7 C: w
8 H7 x# Z1 n( O9 e g- namespace animal\dog;9 V; G- e- |& F. C: T5 z1 I# @* w
- ' s7 u' U2 e: \3 \( H- s
- class Life{, X# h1 l0 F H& l! Q/ q8 {7 @
- function __construct(){
# f6 _7 [1 l& e5 Y - echo 'dog life!';
6 |! y6 n; ]+ i - }) m' A. A5 c! x9 c
- }
: P1 O2 B2 s3 O$ t9 ]0 d2 l( t
3 X Z1 b0 [" }- namespace animal\cat;& z2 J1 g2 V# g: |1 Z
- " v2 P9 B. ]! r/ j' j! M
- class Life{
- t" O5 t6 r: N& F: N/ @ - function __construct(){, I1 F% U/ N0 d) `: S( O
- echo 'cat life!';8 ~: G+ ` w A0 ~/ X* H
- }; A Q4 ~7 g }+ E8 p9 C& u
- }
0 R# y7 N) _+ h3 m4 D6 k
( v7 B+ P* p2 D5 T- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
, ~5 p& @+ u& } e, O4 P7 y - new \animal\dog\Life(); //A
2 z3 \" P6 _1 f# U. J" b, |
* i$ k& `. v% _$ \2 r" p3 [- use animal\dog; //a
% [ w& L& v4 i6 p6 X a$ G - new dog\Life(); //B
2 [# R' v1 B w( X3 m
0 T, u$ @# u+ t; V# d- use animal\dog as d; //b
# j. |- M9 o$ F2 { - new d\Life();
复制代码 ( d3 h" U/ i& S" l8 k& Q
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
0 S! Q& ^8 J$ U) F* c/ N通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: ! i8 W3 B. M2 `/ E! H
相当于
$ `- }2 s4 Z$ M2.namespace后面不建议加类名,但use后可以。) `/ M, }4 w! `& x5 T z( x
- //name.php7 t" i) n3 Q0 g8 L- I5 j
t' L q! F. P- namespace animal\dog;4 @1 n4 q* f$ H6 _: s
' {6 Z# y) q& i7 x! w* y- class Life{
7 @+ x5 F1 {% u6 V S - function __construct(){- ^8 Q t0 B# X0 B
- echo 'dog life!';
. {) J6 h3 s$ H: h" p: u6 j - }
! F5 C, l. Z, g# f# Q - }0 x% Q3 w) p" Z& p* Q2 X* ^
) s" _& A7 E, U$ r4 L. o- namespace animal\cat;. A( G3 ?1 s0 d, m ]4 L8 e
- & V: C7 d2 w a7 E2 f
- class Life{
. |3 t. N4 b q - function __construct(){
: c( E6 X9 d t) `& f - echo 'cat life!';: R+ A6 G" F+ K3 o3 W
- }2 |& F* n9 F/ r# q# r
- }+ j) E" \' T0 M
- G6 A3 j' d" A# P# r
- use animal\dog\Life as dog;
9 O: i* o Y# L8 A; j% B - new dog();
复制代码 7 ^ |+ u+ N: z: {! L5 o# v. H3 h
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
. S' W- J+ r) A9 l$ T9 x因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php1 ~# l9 g* H( }. O( r
- ' Q( R: g. H |$ O A" j
- namespace animal\dog;5 f, y2 {3 ]9 }0 \3 k4 Z L
- , ^6 t( a& M C4 F1 ]
- class Life{5 A% e% R/ Q+ X1 @4 i* z8 S7 W6 c. N" Z
- function __construct(){5 O5 E' b& G7 G) o r5 B6 Y
- echo 'dog life!';
4 v/ c* i8 j/ ?- v7 R5 w - }
5 R" H/ k. h. t, [/ h# l - } A! U/ I* D o( F2 q1 v! S
- class Dog{9 }) P" X7 ^. A! I( f
- function __construct(){
' K" ]5 e4 w0 K, D2 S - echo 'dog in dog!';
6 z, ?" Y9 s2 {5 q% G8 v - }9 |$ L/ A, \4 H x. t/ b6 e6 _
- }
! `5 I, s& u. Z - # x; u3 @' \: S' z- O
- namespace animal\cat;
, |- u+ u$ `0 k( c2 _1 a! n - ' z% b4 D$ t+ U4 M
- // class Dog{
* v! s& l7 K" Y& _7 K/ o2 e Y9 [ - // function __construct(){ t6 P2 v9 P2 ~8 Q7 V% [! Q
- // echo 'dog in cat!';, l7 `4 u" J" H
- // }0 v0 y1 e8 _8 O0 r7 [# B; ?& n
- // }
# x% w/ }0 p, [- K: C - class Life{
7 Z2 z2 O/ P/ T E( b4 y) M - function __construct(){4 S8 |* p* n/ ?6 Y1 i# k8 N5 _
- echo 'cat life!';0 m6 N, n# `8 @0 Q3 N( |
- }, ~1 m p' m- J+ `# S3 J; q
- }
, }4 ]* i( j; B+ d' b, a - ! w& a8 Z" U7 t' K4 ]; B
- use animal\dog; & \+ f+ Y* a* n. W/ R5 w
- new dog\Dog();
复制代码 }0 z+ ]( k) _4 |: ]
如上,使用了 0 T3 o/ E5 A: v; h' }9 l
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
+ q' A1 B3 Y2 \/ `" `! M; L( \简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
( H5 k( j$ O S9 m1 l- w1 g/ e: m+ e, l8 |8 q" A: i6 `8 `+ n
/ N4 i& S5 ^- ^
6 T- |' f% ~) W# o2 E2 K' Q( f& L* \% b
|