以下皆为本人自我理解内容,如有失误之处,请多多包涵。 + ?* y8 J. {! R3 W
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
: k% ^( Q/ B& Q, o! v$ [' A$ Y' x& r3 R5 _9 f; W
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
# n9 P _7 M! c* c" C: `$ b4 r% G: f) [据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
- Q/ g- Q6 H8 l+ d+ m- e/ Z结合使用方法来进一步理解它的使用目的吧。
9 H4 n6 v9 ?( T
: X+ ^, e+ v6 j9 i7 wnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
* |, T5 J5 N2 L- h4 c - namespace One;, B, s8 t+ h/ @3 ~: i. }
- namespace ONE;
复制代码
/ g" K0 R$ d# i- v! C6 [如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
; g9 J2 _- I1 s# \3 Q2 _1 b0 u2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php . Z% a9 i0 I# B1 B( D/ r O: {
- class Person{
$ ^: z( P. r# B0 c* B0 Q - function __construct(){
& m$ d a4 _$ l/ \ - echo 'I am one!';$ ~0 F+ E8 p7 C" m1 A4 b( ~
- }" ^( P8 f+ G [* ~- G
- }
复制代码- //name.php
3 [) T7 e7 k0 n& T& C3 a - require_once './1.php';% Z4 g) `: s% T3 G* T" }
) v/ b3 ~! Q7 x8 |- new Person(); //输出 I am one!;
2 o3 p6 Q _* f t( u; N5 f, I4 h - new \Person(); //输出 I am one!;
复制代码 9 { O! }2 j. V/ D4 A
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php% {. N' C% |1 W# ?( A( W' V
- require_once './1.php'; x" |# |8 E; u2 ?. o" _ J+ l
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
# v$ j' w" |: R( Z: a2 g4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php % U" h8 p' T) e! @9 R* q' T4 X7 T
- namespace one;
" |! \& s/ k- w - class Person{6 S# E0 W5 V/ F' m0 ]: K
- function __construct(){+ x! D6 F, R' F1 u
- echo 'I am one!';
+ E) r" `/ c" O4 x3 O& @$ l% f- m - }/ h$ e i$ v: p. `' u' A& V6 Z
- }
复制代码- //name.php% U' T( G( h: I l
- require_once './1.php';
9 p9 M4 T. O" p7 \- X" h - new \one\Person(); //输出 I am one!;
) {9 j' J/ f! X2 o& M - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
7 V) g, ^+ @) s6 s$ g* h ~, v可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 / T( F" g$ [, Z9 U# R; [! ?+ |" }
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
; d! n" E" a, S( l- //1.php
0 d9 T* `3 h6 j( M" U ] - namespace one;% Z% g) s# K0 o6 Q
- class Person{
, d* I& ^, \4 z" H3 F - function __construct(){
8 l0 k# o! n7 C2 c" L1 }6 ^4 H( H - echo 'I am one!';% [5 g& y4 H0 U! p+ M4 C
- }6 r/ k, C! j% K7 p8 E" t3 F
- }
复制代码- //name.php1 n. h) e/ d7 b3 Q
- namespace test;1 q* l0 n0 I, g- F' U1 l
- require './1.php';
5 e0 H" e: d4 Z* e: U0 ^' J2 b - new \one\Person(); //输出 I am one!;0 o% _4 M7 n4 _. u
- new Person(); //这里结果会是什么呢,猜猜看4 z' V" x; l: }- x
- 最后一行结果报错:$ ]- F7 j' e& K G6 i; \
- Fatal error: Class 'test\Person' not found
复制代码
$ p& r) O/ [* [
! j2 ^8 b- t3 x% d首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
0 a2 L, _* f$ s+ ^( n结果报错: - Fatal error: Class 'Person' not found
复制代码 0 B# @9 I6 r* n: M. @: Q1 n
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php+ E! s8 ~$ _% f" J% B, G
- namespace test;
' z* d" s8 \+ k4 r' k - require './1.php';
" ?9 |2 v: t7 `4 J, ^# J
6 T9 P- ~ q7 s5 p8 _- N- c4 x- t- class Person{
. W) E8 u, `$ {' Y - function __construct(){
3 u8 B9 A0 L3 P - echo 'I am test!';6 q" b- `& q6 q
- }
1 R2 T+ \+ x7 \0 B" D - }
6 B" J" U" c4 U3 b h' r1 B! t/ q - / x9 G- H: P9 d. w
- new \one\Person(); //输出 I am one!;
4 \. k% D5 {( C) M0 X0 B' a' j - new Person(); //这里结果会是什么,自己猜猜看
复制代码
; R) Z% B7 @ C2 [$ n0 w0 v0 a最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
2 @ G: E1 j1 H# A! z+ Q) p - namespace test;& T/ H0 C4 m( z, u
- namespace one;( o! _6 \2 x6 h5 i5 J$ j1 K# e& Q
- class Person{
; a5 h" q- T) A# V6 t% B% @3 M - function __construct(){
# T! S' r: a9 t$ a6 `& _% q - echo 'I am one!';
3 V: \/ [( {+ {7 w - }( z5 t- N4 L- |4 |* R: }! ]7 a
- }
. @6 D, v" \* Z/ g4 x" U) Y1 b4 U
% E7 b( d4 n4 g( ^/ a v- class Person{
3 c# \1 I$ t0 w: n& N, M - function __construct(){
$ u* H* B. k+ [7 E1 e; ]' q7 X* f; [ - echo 'I am test!';9 s0 y/ t5 l! C! e1 i% k- Z
- }/ J8 k+ g2 ^+ L" b& j9 B- O# o$ K
- }
复制代码 2 c, M/ Z% y9 a( y
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 ( A# B$ x+ J6 p" X( l! y/ X
看来简单的把require理解为替换,在这里行不通。
0 @6 V+ d. W ~4 ?8 S& U/ b6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。% |5 ~- \6 Y0 g% f
- //name.php
C- z$ X8 T# v- m
* s6 n+ p' j( m \) a) E- namespace test\person;- |3 z0 s6 G' E' |7 `2 v
- $ c3 o! h5 g' Z. H
- class Person{
7 ]4 k+ H v" Y2 W0 [ L$ Y" J: J6 ^ - function __construct(){
* x- N. G& I: R - echo 'I am test!';
3 X- B' C( Q k7 w7 o q* i - }7 X9 Z/ A! `0 e
- }
9 F4 L% L, C# x) H9 o+ F9 D" g* f) s - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 7 J: O H$ u( A- j
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 7 ]- m8 ]; {" w9 B
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
! E! n8 l8 `) j4 V5 t$ }! l, A
, @$ P7 D" M3 o, H7 u+ v `& T- namespace test;1 o+ S4 |: N! ]; |' Y8 w2 m
- echo 'zhai14';
3 @2 |; h- w& ]; n2 [3 l - namespace zhai;
2 T) m& l5 Q. U9 p - require './1.php';
复制代码 ' O$ O' ]2 r' H7 F+ g
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
" K* S+ Y3 b# p6 luse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
/ j% \7 u/ V+ k: c8 c- g- //name.php9 E7 n5 C7 C- ~2 q6 A4 Q i, f
1 D2 P% v* [0 e8 ^ H- namespace animal\dog;& T, O2 [1 S. i9 s1 r6 Y* `
- * _/ x* T/ @1 ^! D7 G- P1 w" D
- class Life{0 |$ S2 j' w$ X; v' s* Y7 V
- function __construct(){
3 ^' B9 i$ X5 f5 i$ c2 n& Y, f% J - echo 'dog life!';
/ M6 D I" k' C1 h8 I% G! Z8 i - }
+ h4 o: R3 a: u" m - }
$ N. J! r7 K* P- l# V8 I6 V+ N
# N7 k1 U/ K. k: m9 i- namespace animal\cat;
/ P; X, U. q |
! k( D+ k- u5 w. s7 s" `- class Life{2 H5 o1 p- p' D) ~( Z! {0 g
- function __construct(){
- V, W! m0 w0 n - echo 'cat life!';
4 E0 D* ^" v. K/ p6 c - }# O0 t- x+ C# T$ @+ w# U
- }
3 a& ?" S9 p g# W. W3 f" C
+ w$ `( U% u I- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间" t" E7 d, n. `& p6 N- f
- new \animal\dog\Life(); //A3 i$ }; k" M) n9 i3 V7 C4 x7 k
- ; p( Q7 ^: {6 K2 }1 q0 r* B
- use animal\dog; //a
5 E# U x# q7 p% F& K7 ^8 j - new dog\Life(); //B
# t$ u" x6 }5 f( z# V0 ^7 a
4 R4 Y5 ^, S& t# @9 y- use animal\dog as d; //b; l! C9 c- l2 f: n
- new d\Life();
复制代码
: {' x0 c% {+ l: x8 h' T通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 $ ]5 K6 a% h1 ~. d2 \9 Z$ x2 ^
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
5 M; I4 t N, S% H相当于 & U' ]+ P1 U: c) ^1 d% P8 H) y% u
2.namespace后面不建议加类名,但use后可以。
) q6 @# c* e- h3 k9 O- //name.php
- Z- P2 f' v: }% M! C - 2 ` e4 C% ~# W. H0 p
- namespace animal\dog;2 N) ~6 V2 W' {6 }
% Q# H7 y8 Q& w( R; f) E& a- class Life{
0 j4 G3 S' u- \% q% ?) C1 x* i - function __construct(){& S8 R1 X& k% _+ X9 O
- echo 'dog life!';
- j/ a& ?; \: m. ~+ q% b/ ~ - }
+ D4 _9 M4 z0 ?0 M6 x& L - }
' H- Y0 o5 q( c - ' U/ T1 K3 H3 k' s% e) Q
- namespace animal\cat;
/ y3 e- Q" g" a' P
3 A+ Q) y1 ~2 F0 Q8 e, H o$ |; D- class Life{* ], _- f& L" N4 S2 R
- function __construct(){) _- Z7 ]6 o6 q; J. z
- echo 'cat life!';
8 D( h3 M [+ F @6 r. ~ - }
, v/ t. n! U* r5 ]( R: x4 p - }
5 E6 F7 q$ I, T3 W - " W, b" Y1 h6 K. V3 a9 E6 |9 |
- use animal\dog\Life as dog; 8 G! a' b) I0 T* u- `
- new dog();
复制代码
% b @) O. m0 j如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 / e# c6 P' y I9 h" l
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php" a9 }+ z$ [# [3 y( c
7 ], t s: \$ [2 T- namespace animal\dog;0 z: p+ H4 Y9 k/ p K. H: e }
/ o, z. f# O5 {% J j- class Life{
1 [ P" K/ \# \0 L4 Y/ [ - function __construct(){, I7 |) z2 z7 X) `
- echo 'dog life!';0 d: c8 p2 G. F2 B( N( ]$ F
- }: h( z4 ^6 g6 g& ?1 X& t$ H5 C
- }0 Z8 g0 n/ y$ T& ]5 |
- class Dog{
& |+ V* u$ b o& E* J% x - function __construct(){
' f- O% U/ l6 l0 ~$ n: ~ - echo 'dog in dog!';: }& w2 i! l1 p/ q' T8 N0 N, z
- }: G9 X4 E5 e1 v) p$ r$ P
- }
, H8 t* a, ]- e: H" }& J - ) `, } ^; Q9 w
- namespace animal\cat;: X* z4 H7 @, @, s4 a, i3 e
h2 v' j T" I) h& a1 Z- // class Dog{
?3 h8 Y7 w3 J% Z - // function __construct(){
# r7 Z( Y1 m& f1 t - // echo 'dog in cat!';1 l9 I5 q1 Y E1 O6 ^/ Q
- // }2 i8 s+ ~/ q6 Q! k' h% z
- // }( Z7 X4 G( Q, I5 C1 A
- class Life{! D2 g5 y$ I: Z7 C6 H: f
- function __construct(){) F' Z7 n1 ?. {
- echo 'cat life!';, S8 c% q0 J6 O9 G; U6 P. B5 o
- }0 }6 x2 h' X a8 }! f
- } l& ?6 W# M) V* J3 Q" y' P
- : [% j6 i0 F1 J5 M
- use animal\dog; . x2 ]; r! o4 t, C7 @$ C
- new dog\Dog();
复制代码
" N& ?$ l, [+ V' H' w) S- {* T如上,使用了 E* t+ E# Z7 p4 X" z
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 , t9 x5 r4 e: U1 [9 _
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 # F5 Y! A: E. _! V, D- h
% T, j) M: C, c9 B3 z) R1 ^: ?4 ^
2 f+ n! }: ]6 p) d, G' u& G
; q5 n2 @* R0 Q3 G) J5 B
|