|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 & w$ C! h+ d' I
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
% N# j" Z/ X( h" `. z2 D! R D4 x# V7 e' x- t M) Q
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
0 x" h) n) a: Q0 R& y+ m! P' }& Y据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) % P: g3 a0 O. M; j6 l# z! Y5 a4 {
结合使用方法来进一步理解它的使用目的吧。
% V9 `6 e. ]# @( O4 L# v2 `. ~" |5 j, A" I: w/ Z! [" n0 n
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;: z X' I* H! F/ S
- namespace One;
7 E; M# f% X8 t$ B4 C+ {4 u6 } - namespace ONE;
复制代码 . Z; e8 w: F+ t" a6 G* W: o1 @1 c
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
8 o2 {1 ~/ _; I$ O! a# u. j2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 0 G% l4 i. u0 P7 A4 E. V: S
- class Person{
2 f6 }$ L+ s& f - function __construct(){+ A7 ~ {; Z, a. B( f, Q: a; r, A
- echo 'I am one!';# y) ]& k' K2 F& c# x0 g
- }
# ?( y: v& n1 S8 D. A6 } - }
复制代码- //name.php
9 M+ E( T3 D' f9 _5 t* v - require_once './1.php';* [8 z% D3 E2 d, L+ G% M
- : l; M. k) ~" `0 w8 D3 H. E0 A0 w
- new Person(); //输出 I am one!;. v0 a; _% y; Y. o- B2 Q6 t ?
- new \Person(); //输出 I am one!;
复制代码 + ?* x( d$ b- A% S6 q
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php) F. Q& J3 v! ?/ f
- require_once './1.php';
% x8 v% F3 t+ R" C( N5 I5 @ - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 6 _3 B, u+ L: T6 f. Q: d
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
3 y8 X- n9 E6 l; H - namespace one;
' P, O6 k# C' i/ L* f - class Person{
+ n3 b: o" v4 G% ?8 \4 B% O# m" Z* c - function __construct(){5 ^1 L: L0 h0 X) j) _. ?0 {2 S
- echo 'I am one!';$ k2 d* E4 n# y3 o
- }
8 x3 D# m0 z \+ j/ ~6 _ - }
复制代码- //name.php
5 w8 s) v/ ]$ V; S- Q/ c - require_once './1.php';
5 [) B7 U0 p5 C+ @$ E! P, S* K3 X# A% o - new \one\Person(); //输出 I am one!;
2 o+ X- s0 Z8 A F: [4 p% D( ? - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 9 X1 X& _ m4 ]2 d/ e7 O
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 $ `- G2 ~: V. G2 @9 h, w& q2 p5 g
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。% B' S1 i- s( `- j' ]# l m; Y$ k
- //1.php 7 a: z2 d- T3 Z# ^' P7 x$ u9 Y
- namespace one;" o3 _; w7 |1 ~' N8 F! b' E
- class Person{& }1 ]/ c" K8 X0 ]0 F
- function __construct(){
7 @4 Y' F, I p - echo 'I am one!';1 p% c1 g9 j8 z( {( p1 R. L) {
- }* }% R2 O8 @* ~7 U8 x: `( O" }
- }
复制代码- //name.php" ~6 n- a; i3 R9 @
- namespace test;+ T" k; b& h& s) t: y( n* p
- require './1.php'; 3 F. k! Q1 Y7 Z% V8 S- z2 s
- new \one\Person(); //输出 I am one!;8 W. A2 F% ^ V% a
- new Person(); //这里结果会是什么呢,猜猜看" F, j% c" [% s! l6 y! x) e
- 最后一行结果报错:* r7 S2 P1 U8 n$ l8 a% z
- Fatal error: Class 'test\Person' not found
复制代码
! T' X# e! e H5 L6 U6 X
8 O! }* B) ?: `/ {! H- x9 U: U首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
7 Q# z$ R! L1 u8 w) y, H' P5 F结果报错: - Fatal error: Class 'Person' not found
复制代码 . G7 s7 E2 a0 j. U4 h y7 f u
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
d# x" E8 @% L% T2 l - namespace test;& U9 ?' F a: Y5 X2 ^$ G; n9 a
- require './1.php';
$ _$ T9 U2 I4 a' A
- J+ Y6 | f( I+ f3 N/ d2 u5 I- class Person{
9 A3 D# y1 E: i# a0 p - function __construct(){7 k6 R. Z8 h! K1 g+ A7 B! [/ i
- echo 'I am test!';' A6 y$ F! m' c
- }" {+ C! V" G* E% g2 B) h
- }
. x6 ?- L! v6 z4 ]$ |+ Z2 { - ) x- F+ v _5 ?" {# O( a
- new \one\Person(); //输出 I am one!;+ v: f! V) f8 P1 \; b% @' u
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 ' |, {) t) `/ P
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php! Z" a5 e8 X% g" O9 T$ H7 I
- namespace test; |, L% R+ e0 C; l0 `& ^$ P3 B: \0 o
- namespace one;, g- y8 M+ W; c5 q
- class Person{8 L4 [& n% D$ t% n. G* L
- function __construct(){* I3 C+ I: g4 c$ I/ W S3 E: X
- echo 'I am one!';
3 b4 W% w9 @: i; s- K! @* Z - }
+ I, M, E3 R9 w! ] - }
# p6 L/ g) H7 H' e. O# d
- ^4 ], Z/ E# J5 N5 D7 T- class Person{
. a+ J, @& A A - function __construct(){7 ^! `) ~' P7 R; |
- echo 'I am test!';( C. R7 y7 e+ O- Q' ]& n9 N6 J/ K' q
- }8 ~4 t a* U1 @ ~8 v8 C
- }
复制代码
; x' p0 a% c _; v5 d2 Y0 C无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 $ J& h' j2 F- D' r$ N
看来简单的把require理解为替换,在这里行不通。
$ h% e7 }/ ]* @: ^6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。4 a# w: G4 W" Y" P. ?8 |. c1 R( K' R
- //name.php( {- M3 m& Z. ~1 C4 ?7 a
- # K% }' L* M. i% n+ i5 e4 n
- namespace test\person;
+ o5 r3 P$ p( s
3 ^. v: ~! S+ W8 K) Y- class Person{1 c+ M& B$ w+ o, [" ~2 ]
- function __construct(){% h7 _9 g' ]5 V- O
- echo 'I am test!';' F2 x# t6 ^, s1 I
- }
$ P8 r6 {$ Z2 s: u9 t - }( R. E3 h7 p' g4 _" T& n2 a' d
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 + t8 B6 W+ f) d: W7 ~6 R
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 & A+ t6 k$ i" y Q
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php5 N# H0 H# m% G' U; i
- 1 J ^) [: a" B3 q$ N
- namespace test;, l% L' I% Y* B8 T
- echo 'zhai14';
. m0 w- V. e% W, p @ - namespace zhai;
' V% H( Z, {7 j. i9 m3 v - require './1.php';
复制代码
) G l' B, n- H- ~! tphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 8 J+ q3 S ^" N! f! ~
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。5 E/ A5 R* U6 s
- //name.php
: s4 k5 n! ~& D3 N& n
' s8 c+ _! c* p! T- g6 `+ {- namespace animal\dog;
9 D6 n# e( w y" V - " E4 R* O' {- D C: J2 q3 {5 h2 a' M, L
- class Life{6 f" r6 k3 O/ L6 ~) r: O% l; h
- function __construct(){
: r1 i* m0 i5 A t$ k - echo 'dog life!';0 q& B1 i" a8 A' \2 g& E" a
- }
. W& f% z$ O/ K( c - }
$ t3 A& @7 G( l- r' y - 1 l+ `7 k) u* l% e8 h' M! _
- namespace animal\cat;
8 r1 M& k8 N [# Z5 s: A
' b7 ]8 L$ p/ z) `9 h2 i- class Life{
' |. g1 u% L3 G7 F& Y9 x. h - function __construct(){
9 D$ j! P& ^/ p - echo 'cat life!';
2 M. T5 f/ W7 }5 z! Z5 Y- v - }
4 b) @* Z/ _4 q6 ?6 L* Y - }
7 K: G y$ K3 X2 e4 W - % m4 E! l; {+ ^' ?' Z) T' j, K
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间9 E! j9 Y M# { Q; q
- new \animal\dog\Life(); //A, C% w) _4 e8 u/ W' a; |( t) ]
- & ?$ x) }- U( [2 A. a
- use animal\dog; //a
" I/ b! ~' E8 K1 D - new dog\Life(); //B
4 Q- _( a; H* i' A - " V" E0 d+ G0 c5 O
- use animal\dog as d; //b6 a6 k- O9 c" }8 f: X
- new d\Life();
复制代码
" \. \: r8 Y6 c3 f, p G通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
+ l! J2 L, W4 G: B! @( {通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
" V9 v" ~) {. T5 U! X+ s1 P相当于 4 u5 t; R) J, c' S4 X v$ p3 u
2.namespace后面不建议加类名,但use后可以。
* j" U( d# Z, i; @; b3 f- //name.php8 E5 Q% p# T3 N+ J6 w% z7 z$ P
3 [# E& C( k# G- namespace animal\dog;9 g# s) `3 J9 Y+ k5 y& ~5 B$ K4 i
4 P$ c6 S G" S# q% ~. `! t5 k9 u- class Life{4 ?; F. g2 o+ ]
- function __construct(){- P: x, o( K% r0 r& u- Z5 e
- echo 'dog life!';
l* p& x1 z4 A7 _8 ~$ j" l( S - }! h: G* ~0 R3 k; ]) ^7 G9 R
- }5 b2 s+ i d( R- `" o
- 8 z. ~0 p& f3 L5 P$ ? K
- namespace animal\cat;
3 p" x, Q% L- K/ B; [2 ^* x/ a+ _ - ' K" a5 r5 b8 K) u
- class Life{4 u' s8 W8 i8 c' T2 E# y
- function __construct(){
& J0 C0 O1 J" d/ ~! Q: H/ A - echo 'cat life!';2 L& g: U4 x- G8 h
- }
8 D8 e a( m% y - }8 J' E( c7 [7 F, }+ Q
/ R4 X7 b; z, N# q( F1 t d! B- o- use animal\dog\Life as dog;
& w K8 A& P! D) |5 y# G {3 e - new dog();
复制代码
4 o$ o3 b4 B* W9 N) e0 h如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 " V5 j/ K2 c; i( p- V; m7 U2 p
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
J: c% }! t) |/ `8 \6 ?9 e
/ O$ E7 u8 F0 y. `0 v- namespace animal\dog;; C9 q) p0 h/ B! j) ]# Y% A
- ! D/ j" ~, L1 e
- class Life{/ A/ A1 A* v+ x! E
- function __construct(){" w+ D7 `3 d$ {0 v
- echo 'dog life!';
, l6 z8 p- W0 S) a( ? - }8 X$ a$ A4 C( X1 a; j- Q+ j1 s
- }
# }3 }, N: M6 n! |# x - class Dog{0 x; ]: B" Q, `! u* }% T
- function __construct(){4 T G3 R) n. k" i8 p
- echo 'dog in dog!';
: H* z# V! m+ A- y- w. S! v$ [1 \ - }
9 {: L3 d" U0 t6 g8 G ]( ]$ i - }' Z5 [6 G1 \' C7 q8 d9 I* L
- 8 d" ?. h& ~! q- j' l
- namespace animal\cat;0 ?3 N: E; ~; @. K0 H1 |
- # m% H7 K0 w+ R3 n. W
- // class Dog{1 j5 @% ]4 | ^
- // function __construct(){
2 i( I4 N7 w! h, d - // echo 'dog in cat!';
# v' ]6 L) I# u7 y; e% C - // }
U% `* F, u/ {& h - // }& y, v1 S1 {# _! `% M
- class Life{
+ j5 I& m6 W0 S - function __construct(){
1 B2 R$ f- W" f4 c8 A - echo 'cat life!';- s2 i/ o {+ T; S8 g! I
- }
P( D4 g( M- t# c - }
) G @" U4 |- J, a+ [8 D \5 D( U
' ^6 {6 c$ Q/ ~- use animal\dog;
# f# b2 K' p$ s: R! x$ _3 J - new dog\Dog();
复制代码
$ k$ D! z$ k% c# a: p如上,使用了 1 u5 U- e" w- D2 r( E+ ^7 V
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
& g1 U# q0 b$ I+ I# m& B, [简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
. @1 J) C/ ~3 {- Y" J8 [3 H4 x* i6 I4 k% v
' c1 E h5 c7 N* c( b4 j- T
?+ Z( I1 N& C8 X& }: v6 m1 U$ H( [' W( G- Q- a& v# |
|