|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 9 X5 k! r' d9 f& S# p
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 ; r% {: W# j2 o2 i( J
' i' j1 ~3 r, B( z使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; , ^6 h4 {! V9 J8 ~* [
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 5 C/ t, \) d& u; o1 e$ o
结合使用方法来进一步理解它的使用目的吧。
, U# a r# e! P; b/ {$ J9 ?! n) Y) ` w$ m ~# H2 z; U# f
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;* d7 [) d) K0 |# n5 z
- namespace One;0 G s6 M$ ?% [6 q$ Z3 Q: e
- namespace ONE;
复制代码 % n* X/ s T% s7 e9 Y, c" n
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) # M" @' y: {( i9 U
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
- L, q4 g) @7 B) \ - class Person{) x1 K. K Q) ~
- function __construct(){5 r( ?+ j9 c0 P5 ~9 k
- echo 'I am one!';
- q* B7 s* p( b4 d) W6 x$ N9 ] - }
d$ c6 T+ B6 }- p - }
复制代码- //name.php
6 s! D$ |+ e% p: [% w7 j - require_once './1.php';; Z* k } x: X/ N% L7 R
- & C# h+ l: }' ^* k" K m8 T3 l
- new Person(); //输出 I am one!;3 }6 l: L! b+ F/ T! g, D
- new \Person(); //输出 I am one!;
复制代码
4 X/ J* b1 E- M& ~9 K" m) {& I3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php8 O0 ?1 B9 ^: p C
- require_once './1.php';
4 F5 p/ y6 b: w' w; G - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 5 f }) B3 C7 f$ h u
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
, y E7 A/ e+ L) F0 }# p+ H1 q - namespace one;
?# |( x0 |% g, [* ?5 V& } - class Person{2 q! W9 B7 | q6 R; h, f- q
- function __construct(){# f5 d6 G! @! `
- echo 'I am one!';- {. P/ o! n2 J* k
- }! J/ a3 i" L) L a) E5 O) h
- }
复制代码- //name.php
, `1 a7 i. N w7 |& E% O8 }) k( w& ~ - require_once './1.php';
P; A w; q; @, Y! T - new \one\Person(); //输出 I am one!;
: a+ |% h8 e* l" V: f2 U7 _ - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
! \/ @; K7 g, B0 i( l6 N可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 / v1 l5 r# }% p( b, }6 N. v
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。! a8 o) |+ `. z! K3 ^
- //1.php / ?5 j5 X5 j8 q, H! |4 R
- namespace one;4 D+ ?5 t+ q6 Z- ]
- class Person{
% Y8 ~ _8 d/ p$ h - function __construct(){
7 ~& U8 N0 w$ D - echo 'I am one!';( r" M9 a$ M6 a1 j8 m5 h9 {
- }9 f' o9 t) l9 x7 ~/ z. g% I( ~ K
- }
复制代码- //name.php9 C) O5 [5 A8 Q- @/ C
- namespace test;
! c3 h ]; c( S: p6 v. m6 ^ - require './1.php';
7 l" Q# I# }9 I7 v7 l; P - new \one\Person(); //输出 I am one!;
+ l7 L7 a J3 j/ p X7 ] - new Person(); //这里结果会是什么呢,猜猜看
o( X+ z- C- V5 ?7 R0 e - 最后一行结果报错:
8 ?4 C" E% W* v3 p9 E1 z+ Z; F - Fatal error: Class 'test\Person' not found
复制代码
4 }0 D8 h% {2 x. c$ U( q( n& e. r7 g
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
9 \( o# f4 D! l1 s- c! p' M f结果报错: - Fatal error: Class 'Person' not found
复制代码 $ }' n$ E# }" d& N1 ?/ c8 i
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
* R2 A) R: P$ u, S+ V - namespace test;' }' a: `# S) U& I4 W \# b
- require './1.php'; 4 O0 q9 X: \4 B% N4 R- Q9 r
- 4 g5 p) z, ]% [5 r* B) M& ~$ p! X
- class Person{
! Q4 [2 ]2 t2 P - function __construct(){
' s# J" f# M, w: q" P5 i7 [ - echo 'I am test!';
( G' k+ S* |" l8 G" `& H. q6 ] - }
% j5 {6 I- @) y* W9 S - }8 ]; S6 J& d- m" L
' b+ `4 M9 v: {2 l& D5 o8 C) M. _1 ?- new \one\Person(); //输出 I am one!;3 C" J; R4 P* ]" [2 M9 c- p
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 * C4 C' T9 Z& g7 Z
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
/ G( S" Y# P: |8 @0 ~2 v - namespace test;0 d0 ?% _1 e0 f! d$ j; w: ^
- namespace one;
" h8 q" _2 r5 p2 U$ u - class Person{
; P$ G- |% f9 U' M4 g) n" G - function __construct(){
# c8 s9 E9 g% F1 J4 |, [! u# h - echo 'I am one!';
2 K7 q }- x: [# u - }3 ]( ? @* |" ?5 p. F6 k M
- }
2 U S0 T3 i+ g6 z9 \2 ]2 i - ) q3 N& x; ~+ ]9 F7 K' I* m: r
- class Person{
3 U# X$ t2 K" a: S0 D - function __construct(){% U! j/ }* `& k; v
- echo 'I am test!';
! w n2 W2 h; f) S5 y1 J! e - }
8 o; ]2 \, K3 q( q - }
复制代码
- I0 j! b6 [% @无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 2 {$ Y* s% x: q3 e; F$ s
看来简单的把require理解为替换,在这里行不通。
7 }, s+ ], |, @5 S1 g* @ I$ F8 q6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。, T: }- R9 b5 [4 g& ~9 {3 o4 _1 |
- //name.php/ E& t( e- ^1 j" H
- $ U( d4 _0 D! t7 }' t- s" {; q3 C
- namespace test\person;8 [* F& o) E$ |( I& Q4 S/ x
- N: r/ y2 ?% }1 @4 H- m7 R+ F+ d
- class Person{
t- d. M8 ?6 Q" p, j - function __construct(){ j0 N [5 C/ [' K: M5 X; N9 C
- echo 'I am test!';, n* W# U1 z1 H& ?* j2 [/ _7 U
- }
$ J+ O3 c' |/ P* x( _: S - }
: {5 J, s1 \1 c& F - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 3 d+ @7 j2 }6 H" q* k2 d7 g
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
5 ]! t/ M8 K" D7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
: O5 [- @. w- Z( p- P& Z
! W9 }8 z! E- ^, ?- v- namespace test;6 ?4 w) u1 K! [4 @" r! o
- echo 'zhai14';
! \- B# P* h0 X: K3 d; s- G1 z- N* l - namespace zhai;
) n8 F$ B; d8 L8 e! f - require './1.php';
复制代码 4 e& ?- h* x' ?' R/ z' y) c
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 1 r1 f- _: [4 p. }: ]7 F
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
$ ]$ g: w% T( N6 @- //name.php
8 q; s/ c" N7 ` - + F, b1 C8 j: u0 A3 H
- namespace animal\dog; k1 [2 A# S. s% j: k$ M5 U
- ( u/ y( M: ]3 p* U! F
- class Life{4 O( w- @" C# `6 i6 G$ e/ w
- function __construct(){
& B% B& K3 }6 c6 x* N" L# p - echo 'dog life!';
0 C% ] x0 `6 t5 ?6 O - }
2 P) R$ A) f. B# n1 C1 J - }
7 O- L1 r; Y& ~) F" n. _ - 9 Q& i! D; C( O) h
- namespace animal\cat;
( Y: F3 t* I) `1 H1 [9 p
6 {- C0 ~* o0 m& }6 f- class Life{
2 [2 `% J2 A: y& j" {7 t- K - function __construct(){
" U, Y# l8 o: @5 w+ A, l - echo 'cat life!';3 [# H0 K" E$ r6 }- r# N V
- }) T0 {4 T0 W! W* P) n
- }
3 V/ `! O3 R6 p4 o6 E - 7 j, s; B1 m# @: N
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
5 I. I: L3 _6 Z$ x; I3 c B7 J. F - new \animal\dog\Life(); //A3 @9 [) x* a( G; p& o' q
0 M, S2 K# T! w r0 C4 \. f- use animal\dog; //a+ ]8 S2 [" y4 }# ?
- new dog\Life(); //B- Q3 F# {: x I# b7 ?
6 D4 M# B1 Y$ J- use animal\dog as d; //b( o x: G; g2 r: Z' v0 m
- new d\Life();
复制代码
% r5 |* d" F$ U' P6 a通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
, f1 p& [: ]! e7 M# G通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
U b! ~8 T8 z, V0 f相当于 2 U5 W2 c: g2 Y& K* I
2.namespace后面不建议加类名,但use后可以。. \- ~- f4 o' U8 e8 [% A1 Q
- //name.php
; O; P4 F1 D: G/ M+ H$ [ - n# g, L2 u$ M! y
- namespace animal\dog;: ]; O. g1 `/ M {( \. s6 C
- $ l3 Z/ ]+ Z- Q5 \/ B$ W
- class Life{; j: P2 y J/ k; _1 P8 n7 [: A
- function __construct(){; R& B. l4 i5 h% \6 c
- echo 'dog life!';
9 {3 |5 S+ A4 \ - }
5 H* U7 l$ l6 W/ m0 f - }0 ?' P1 r5 @: P c
- 8 a; `% B4 q6 e$ }5 U
- namespace animal\cat;; o- }. _1 a9 G5 n% U/ b
- # {/ \" K0 d7 K6 h! _4 g
- class Life{
# q8 q( g' Q' f3 {/ h: h+ r - function __construct(){
: k$ V# O, r$ y. u - echo 'cat life!';: e) u1 g. [3 r( u
- }
" s" h; K4 I8 w0 o - }
8 l4 K! S. u+ C
. a: j$ `# @, _8 d: m- use animal\dog\Life as dog;
4 [) o6 h+ a5 N1 S) z - new dog();
复制代码
" ?/ E# J" f ^6 m5 }如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
$ D# f- v8 m; W$ U8 T( L因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php) G( ?7 E% s1 N
- ) U% F- Q) g2 Q) y9 b
- namespace animal\dog;
3 `2 z6 u1 w! s. W1 Q
* U, U1 t* o4 W" ~4 a- class Life{
G1 \! ~& ^5 \& d - function __construct(){
1 M8 a) [+ r) G1 m% E - echo 'dog life!';
6 t# F, K2 w3 K3 M - }3 ^7 C) @: e8 e( I. `
- }
+ V1 r$ @& C& f/ n0 L0 } - class Dog{
% G1 V7 Y8 k7 g! V, u& o4 x7 | - function __construct(){
2 g/ T5 k* r9 c% V- T - echo 'dog in dog!'; F+ _" H4 p; |* z
- }: u6 t5 @ Z2 c/ X) z" X0 }( [
- }
, X M1 Z- l$ O+ Y- t$ \ - # y: {% M L, v2 K6 e' n1 f
- namespace animal\cat;
1 \3 ?: d f) W I$ n& ^
3 o9 Q! x; X. a0 w, J- w/ m3 z- // class Dog{
2 S- W, a/ z# o; _5 B - // function __construct(){ } \( b5 D0 |: P& S2 `) Q# R
- // echo 'dog in cat!';
* s# i9 |! }) l$ T9 \$ e4 D - // }( H: [& M$ d% u1 s/ m
- // }
7 g1 g3 y/ i4 q' ` - class Life{ D* D! h; F! `/ W* D& ?7 S
- function __construct(){
+ m O j+ X7 E* z - echo 'cat life!';
1 b9 ~8 A" Q- Y" l+ K/ A! t. n/ Y R - }
: |5 E1 U( ?+ ]) c2 ?) Y+ Q - }% w0 d4 O% q2 P2 I5 E' c
- / Q# I2 j9 x1 R
- use animal\dog; 2 A* u% P& e& s' {4 C# n6 M4 O
- new dog\Dog();
复制代码 + x/ x7 ^; j' H
如上,使用了
8 s- g' E7 j+ l% ycat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ! e) D5 c' @, i" e
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
- x1 X {! M- K, C9 C( }' ^9 I: N; `9 |4 L9 c3 {1 v
1 C7 ]7 G9 T( O+ ~3 z7 e
5 z8 S1 s2 Y2 J- \8 q
! @1 i* |! r+ B4 \) Q- J) m1 Y |