以下皆为本人自我理解内容,如有失误之处,请多多包涵。
5 m; D& { B' Y9 b文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
, ~: b6 G6 z. s: z( s# N$ }) T
+ O. D o9 N; g( U* I( m1 N# P s使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 3 Q" c2 N- [; ?, x+ o2 g8 o
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
6 \5 }$ c% Q3 k4 ]7 o# K结合使用方法来进一步理解它的使用目的吧。 1 X3 C# p9 ]2 s0 O
' m$ z4 q b; |, n+ Mnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;% {3 g" O. h7 M2 o) p1 Y
- namespace One;
" G6 L" n' [* w* H. Y, D [ - namespace ONE;
复制代码 9 P" V+ t5 a' i
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 8 c" y k0 [" n
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php " t0 }. \- x) \, i
- class Person{8 Y4 d! B3 o% j$ Z$ f4 N1 w
- function __construct(){
2 {9 W1 C/ q( G1 P# o2 M. W - echo 'I am one!';5 n. u! D/ J; g' U3 P6 b
- }' @' a y* L4 i* s3 v
- }
复制代码- //name.php" i* R- v% m9 [/ h; E( Y
- require_once './1.php';" z' I3 ^' X; C- V2 n$ i' p, S6 i
- " b: ^ ]5 I! G6 O. P" w" L9 V
- new Person(); //输出 I am one!;# ^( X2 A' t' k7 l2 |) \' r8 D
- new \Person(); //输出 I am one!;
复制代码
/ A b7 M |) B3 k! M3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
% ]* `' x, G( K. d. \4 S - require_once './1.php';
# H+ W; B7 B7 p# G9 b" J - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
& G N& p) m1 Z4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
( ^* b1 y o: V1 c! [4 Z - namespace one;
9 K3 f5 X! u8 m* Y% ~ - class Person{0 }/ G) V+ Q" N% s; O6 }! h y7 y
- function __construct(){
7 x8 K8 y9 i" q+ m& D! V - echo 'I am one!';) l7 ~# s0 H6 h8 J; Y5 ]+ j) b
- }8 R/ _- J3 @9 L& B0 b' ~
- }
复制代码- //name.php
7 g9 x* m, o1 h* P3 H - require_once './1.php';* B3 `3 D3 w# L
- new \one\Person(); //输出 I am one!;9 D p6 D7 g& J( }3 L0 U+ ^ q
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
9 W! H3 C: e3 T- U4 e+ `5 }可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 - a# P* M+ D+ _; w% V! v
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。) z' a) _9 t1 ^" o) z, r3 p5 u- B
- //1.php
$ [) ?/ t+ o$ l4 N( y7 k. Z - namespace one;; X9 P6 @% e1 ^* f9 C5 J. e
- class Person{
9 Y+ A4 g. ?% @# |4 t" { - function __construct(){
, Y1 S8 i8 G% c - echo 'I am one!';4 ]$ c3 w* T( [
- }8 f; O: W3 R/ ~7 O1 i
- }
复制代码- //name.php6 t, a8 _( @5 @1 ^% ?1 D
- namespace test;
) c9 g4 F" E3 b4 O: A - require './1.php'; ( f3 g( p! F, H" z3 ^ w1 g2 U/ A
- new \one\Person(); //输出 I am one!;1 t, k5 {" |% ?. s
- new Person(); //这里结果会是什么呢,猜猜看5 i4 D0 E; ~; z0 b; e% n
- 最后一行结果报错:
8 G$ P, A: d/ x; p: \ h' Z4 _ - Fatal error: Class 'test\Person' not found
复制代码
/ ^: |7 H& D, h1 T6 L* [# i7 }& ?/ F% }
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
5 M4 M: Z( w, Y i) P- n' u( Y结果报错: - Fatal error: Class 'Person' not found
复制代码 0 {0 f3 ?7 {5 A
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php. x9 D; P0 N" M! i' ]& ^, a
- namespace test;
9 n. M0 G8 y+ @4 z. e6 C4 a - require './1.php'; : c ~1 |; U+ R7 B1 H1 P. H
- 9 O1 K& X/ ]8 v Y! ]; Q
- class Person{
% d+ K* C! w9 b1 ~6 j* j6 h - function __construct(){, x. Z( D3 r6 G: z! j
- echo 'I am test!';
1 I# h( g; I/ X k - }+ U: l1 K! [& ^9 K5 v" M
- }7 F0 t* U6 Q8 x" {8 i% _
- [8 e: j% G* U4 f& H" R+ m+ Z9 g
- new \one\Person(); //输出 I am one!;* G$ G* c) }9 ]# {0 o
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 [7 Z/ E3 c' X% _1 ?: Y9 p8 P( F
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
) f& B4 H. P+ t% a - namespace test;! ]- X3 A0 ^7 O
- namespace one;$ z0 |; c8 S3 ^* J
- class Person{9 C) [; P; G8 M% {
- function __construct(){9 i. y% k: X, Y: f% I9 I! t& y
- echo 'I am one!';, L- O/ y9 p, ]7 [' m
- }- W) t5 n/ |7 N; h
- }! t7 o8 ]- \6 Q
- h$ o" }+ c _6 w# P
- class Person{1 W$ D A. M+ t |; W
- function __construct(){
, m* S+ D2 ~) i) T' Q4 `0 q - echo 'I am test!';
: S( F. `3 m2 x }+ W! j - }
8 }3 i2 g. h2 P- J - }
复制代码
! W: T' j, ~4 A% w无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 7 N+ N" t' t3 V& e
看来简单的把require理解为替换,在这里行不通。 , c: R, m9 O1 Q1 g- h
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。8 C5 I, B$ p6 |. t
- //name.php
$ A2 X- [5 ~- n9 ?' K- k' c - / ~: D) e6 P; [
- namespace test\person;
& _0 H. d. p2 ^8 [! q
$ U1 \- ?8 b$ E- class Person{
6 z: W& c* c! b( b# ~ p" o - function __construct(){
$ {$ s+ c& ]- y3 {/ _7 I - echo 'I am test!';
9 C* I# J- \- |! L6 U" ^ - }
6 ?. A7 M0 O9 w4 M - }
4 P4 f0 P7 a( y8 L* l6 O o - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 ( h0 T. B; U1 M
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
- ^ l7 Q- i6 I7 {6 u5 X7 @7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
& W( S8 K# Q/ ^$ C0 Z - 5 q/ p1 M2 |' B1 E6 Q# X
- namespace test;
. X3 C* R4 ~+ ], U3 t - echo 'zhai14';- x% w: f- _7 V* J4 r( i( Y4 l% _
- namespace zhai;
) k& y& A( B/ \ F( j2 I - require './1.php';
复制代码 ! L8 Z' o% V8 D+ j2 G
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
6 c V& u8 {# M4 t# y2 @( _4 wuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
7 C- Q, q" \; e8 n1 D3 @- //name.php
$ l" |% z# I* W: p" m* U. d: D
, n2 w1 p7 u/ P- namespace animal\dog;& @3 S5 L( o7 B& [ c+ C
- & `; f: j% L" J
- class Life{
' L/ K9 P& D! b: B: m$ d4 J - function __construct(){5 f( G+ _ h8 U( ~/ L( P
- echo 'dog life!';
+ r) H- ~* f, p m. s - }8 G, x. e- j, D! @# y# g
- }8 i# L/ Q" a) W& P( t& M! k$ q
; e- I8 C# E- Q3 t! |1 ]% L4 G @$ l- namespace animal\cat;
4 `6 o/ t" ~0 R+ }7 }+ P' N0 U' `$ o& N
3 P: }8 s) e7 s" Y+ M- class Life{. f9 f- m, F$ y
- function __construct(){% i, F2 ~: M# g! R. `* B1 T
- echo 'cat life!';: M' A9 U. `5 P4 l8 x+ _
- }6 s D. r6 Z- Y: S/ h) i2 x
- }
. K7 c2 j0 L N* \/ x9 }. f% q9 L
9 r$ r0 @6 G$ x, G+ M- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间3 V; O, p F3 K9 j+ Y% N. ?" ~8 K3 E, C
- new \animal\dog\Life(); //A3 N: e6 n5 Y7 H* y- T6 j9 e0 }5 g7 W
4 Q! l6 G* ~4 Q# N0 r8 k1 m N- use animal\dog; //a
+ Q* p) R2 E# m* N; u* T$ t - new dog\Life(); //B2 u y( A/ d2 l
+ ~! ~3 @) B% A# `6 B: R+ f$ o K3 \- use animal\dog as d; //b
' T8 D! {3 O/ p/ p3 ~ - new d\Life();
复制代码 * \# a2 P6 y/ ~+ s6 }1 {: x
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
! H6 N$ g3 o* H) ~" c8 t通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: " s& X/ k8 J6 e
相当于 ; e, Q, l$ X6 i3 g$ j+ H
2.namespace后面不建议加类名,但use后可以。. ?& }1 V5 x. \4 ^' J
- //name.php$ E5 S7 b% D3 \, l. r$ W
% ] F) l) Z( V* {- namespace animal\dog;! g' c) O. X* Y" I' z K6 V
- / B3 ]) P1 c u/ d# i
- class Life{
k& H5 p* ]) @9 }. K8 K3 L% ~ - function __construct(){
! d# }% C9 A4 Q& F7 G2 u: H - echo 'dog life!';
7 C" ` Z: ?9 D; \3 I - }
' p H' q/ S; r$ ^. k - }
5 v& x9 `9 ]; K) g, U5 Y - ; [" e9 h; }" V2 a4 N
- namespace animal\cat;
& t9 P3 O4 y0 t
+ V w. H! U. w w; ?) X- class Life{
; @/ N, ?9 q% H0 V7 Q# { - function __construct(){& m9 W8 t0 F% u/ ~( q' V Y
- echo 'cat life!';
0 v B3 W" k; i# n2 Q3 ]# V. r - }
5 L6 B" x& z. y- W% f% a V' c* b - }
3 X$ B) T5 I* E - . i: k4 k: _% g! g4 M" ^' J$ M, Z
- use animal\dog\Life as dog;
5 ~* T) t; E, n/ z& T- b9 h; r - new dog();
复制代码
+ K7 N P. w$ _, O如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
: k. d' G+ M! d3 o4 M+ z) ]9 O因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
# m: y/ R; G8 z7 j
" y: |3 I7 X" ?3 _- namespace animal\dog;
' }7 O$ ^( u0 O) [& |) |1 u - / e: }# p1 |3 P5 x4 j
- class Life{
0 j- r- x& D5 k9 O; Q5 J - function __construct(){9 \$ ~& S; _/ z7 i. j# V( n H* _
- echo 'dog life!';
& r* k$ J7 F2 Y" t1 u - }
# m5 v5 S8 s( q( G; P% K v9 z - }
5 ?- J% P# z9 n& G1 Q6 t - class Dog{
* d& T& M0 X+ q6 G* c - function __construct(){
% J/ Y3 t5 I, ]( g/ ]- U2 n$ V - echo 'dog in dog!';1 Z% {; e+ C$ F' R& K. g
- }
* {+ U' [3 e% ~# ] - }
7 ? r2 r9 g% r0 w5 A
4 o* W' m3 U. e( e6 d- namespace animal\cat;
/ E3 Q' Z" ]$ |
+ T4 H. @6 s2 q3 C* J- // class Dog{0 x. x" r0 Y2 Q+ d
- // function __construct(){0 N3 g" ~; _% q' O4 z8 a4 \
- // echo 'dog in cat!';) {3 v) A' G: S1 L- [
- // }
, z) H8 f" `2 N) U - // }
3 a) Q1 @2 W0 e& D - class Life{
0 F* V# L6 Y% r) X! k; ?8 f! t" ] - function __construct(){
8 P; j7 M$ R) Z: T& c - echo 'cat life!';
; a e$ U7 G2 K7 |' t - }
1 w5 p4 O/ u B4 K2 p( u - }
9 i. R5 a6 B1 i' ]1 |( J8 x - ' p9 T0 Y! U Z) ]5 m
- use animal\dog; ! m5 b; b3 {7 j; K7 q
- new dog\Dog();
复制代码 7 M& z# I1 a: i8 D0 u
如上,使用了 , h/ G" z: ]- ~' o/ z* n/ D
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 # v5 t; _! E- ?4 P
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 6 Y1 R- }5 J0 R% c! g1 c, g
6 t; H9 [7 {3 W4 @* w8 T
( a* e) |: l# r
- q( Y" H5 H, J C3 v A
* t& P8 v( X* z! a* A |