|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
5 M& e) I1 ^ ^1 d5 p文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 ) K" M& m. r8 _
4 ]5 N; k" c7 D6 R使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
B$ ]! s2 d' t2 S据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
5 ^5 r- ^% P. L) Z/ l结合使用方法来进一步理解它的使用目的吧。
4 i: x$ g2 k; i
5 u% f9 ~5 e E- D6 N- b- ^ gnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
- M8 x6 L* c# x, _/ V - namespace One;
8 T/ K* p* {4 ~3 s2 A - namespace ONE;
复制代码
% D. v- a: v. d: F! Z如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) & g3 C/ l! M2 l1 G, B w% h
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php ' N3 ^8 l: q* m( l. T# A; w$ m
- class Person{$ n0 w! `. w- X4 j D8 X
- function __construct(){
6 M9 y- [* V+ O2 x* p f - echo 'I am one!';
4 P( e& S: m7 R d% D - }6 Y8 {2 X3 ~# u" y" X6 R! O
- }
复制代码- //name.php
8 O( i( A3 E9 `6 V' v" z - require_once './1.php';8 D' J6 n4 c$ t9 x- h5 G
`4 C6 p; a2 g4 `5 x8 P6 V- new Person(); //输出 I am one!;
" Y# B6 o: T0 R7 i- F, G- j - new \Person(); //输出 I am one!;
复制代码 6 H% {, d. N8 Y- g! k9 M$ H8 I
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php% l- \; r: j0 D0 J
- require_once './1.php';
2 b( q. R$ F. z- l - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 4 l, @3 D' j1 K1 F, B& G' u- d
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 3 K8 {% a' n' v3 D8 i7 X
- namespace one;) t1 G7 E. j3 w9 d: G
- class Person{- K( q8 L! Q. K: f `& v
- function __construct(){% J" \% a7 g, J& H+ L3 T& `
- echo 'I am one!';$ e# } Q; d7 H7 v. _7 z# `) J
- }
3 n* D( Y' L9 }+ d - }
复制代码- //name.php
B9 d' j# T' p/ L4 d& Z. | - require_once './1.php';0 Y+ Z- D5 F- W9 Q
- new \one\Person(); //输出 I am one!;7 }; J; h; Y# C
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
7 z1 ?, x/ n0 _0 A. A可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
- e9 \ g' {( O3 M5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
0 p6 u5 q8 b. E6 K, K' s- //1.php + N/ L5 ?1 a9 q3 K: a4 I7 e
- namespace one;" N6 ]) h$ L! V5 a2 P& A3 N
- class Person{
/ M1 j( C1 q) m; j1 n% Q1 ? v - function __construct(){
, a& i4 _* H; t: ? - echo 'I am one!';
: B1 F, m+ z& h: d# X" Y - }
* o4 \/ F: ~- T: J: U$ l - }
复制代码- //name.php5 L/ D* n, d) z) }* o) `* @( B
- namespace test;
/ A6 C4 @- R" |# A7 g' n - require './1.php'; 3 ~$ |% i f8 n8 z9 W# x7 S5 L
- new \one\Person(); //输出 I am one!;# v& F w, {/ v6 }- Q2 E m r
- new Person(); //这里结果会是什么呢,猜猜看
5 i/ |5 E4 _! n& s- J" x I/ o* i - 最后一行结果报错:
6 Z) k& I7 P; ^9 V, `& N/ w1 w - Fatal error: Class 'test\Person' not found
复制代码
5 C( v' D8 C7 n* y9 l {( p
3 J/ z& Y @. n5 K首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
! }* f ~$ e" k结果报错: - Fatal error: Class 'Person' not found
复制代码
6 V8 ~' I( e/ `+ w5 K" e' i; s" S接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php- |" g& p+ M- c9 Y# D2 @
- namespace test;- G4 l* p2 w$ Z* D! `
- require './1.php';
6 G# A4 z( E( ?# { - 7 x* p2 J, f% t0 o E: I" e
- class Person{
, O4 ], Y9 I7 r9 t" b! }& n* N - function __construct(){
6 \9 i2 j$ J3 s6 n6 e7 Q5 G - echo 'I am test!';; w, i, W! r; Z
- }& z5 F" r5 i$ X( ~0 H+ L
- }3 Z* w: y+ b& M
- 3 t6 h/ N+ j6 J1 S. y2 C5 d3 U
- new \one\Person(); //输出 I am one!;
8 S3 l. E8 |1 o- H7 }! v. S8 f! O4 R - new Person(); //这里结果会是什么,自己猜猜看
复制代码
, i2 {4 k( K8 d最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
8 y; m% {$ b3 }6 p - namespace test;
- c, g: M2 O$ g - namespace one;
4 c2 b3 c7 O5 b8 q - class Person{6 H- I. _ {) x* x
- function __construct(){
! C4 f' _1 @3 I9 _ - echo 'I am one!';8 _3 d# W5 m7 ?5 W& ]
- }+ D6 ^2 g7 C o( r3 k N
- }
3 B6 `$ [! |3 I5 C5 w3 Z - # j4 d3 m y% D2 g/ [/ D, d
- class Person{
* B- O8 B7 L8 C8 o3 s - function __construct(){6 w1 H* F4 c8 d4 k: V4 G4 q `
- echo 'I am test!';% c( O7 y( t. o9 \7 V
- }
$ ?, \/ V+ N7 b - }
复制代码 0 r" A- D1 S& K$ R
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
: A& ^+ V. m- w: [5 i9 T看来简单的把require理解为替换,在这里行不通。
A4 ~' k+ J! g6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。% B' I% |* _& \, r5 f ]
- //name.php
# _& _' W5 b* h; N% I) ^
3 v8 M7 V) c- T3 ]! ?# ~6 @7 L- namespace test\person;
0 W8 r2 a# v& Q% Y3 ~8 X
7 U5 T7 |* ^* n- class Person{$ X9 F3 o( h1 ^0 F R5 Y* l2 @/ A5 j
- function __construct(){
5 |$ o& h" ]4 z) Q' w - echo 'I am test!';
+ T" C( L( _) ?( c - }% M2 |) k. p' D; ~3 B9 ]' e# f. [
- }: j8 P* y" O4 h: a
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 - |2 L) @3 b5 U1 P8 u5 e
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
6 C' _ f; `( h. s! [& b; @7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
) p' d0 e: l5 D: U( O - ' Z: u. Q( B8 [8 I
- namespace test;( Y3 r, x% Z3 l( C) }7 I
- echo 'zhai14';
! P. ~) h" b4 K. h+ |9 e - namespace zhai;
5 v5 W" r2 }- v/ H5 k - require './1.php';
复制代码
2 V" A1 s; f8 Y a8 _0 Tphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
) e- p! s, i# z4 I' N, quse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
! e' b3 @7 n {9 o/ S% @3 r$ u- //name.php
]" P$ `+ E" Q8 S( d - % j' ?$ z1 L% s
- namespace animal\dog;
! n8 {5 z8 ^6 U* j5 Z0 H# L* h' }
6 A, C$ h! |+ }! B- class Life{
# P* l% s- P5 S) D - function __construct(){4 f* F4 R6 C3 l s- S% l, d2 a
- echo 'dog life!';
/ q# H9 U8 F7 m* {0 H0 m) ^ - }) |2 }( N8 o, \! n7 A: b
- }# r" K Q& T( T+ Y4 h
$ g" J* \6 `* C* C/ y1 n1 h- namespace animal\cat;+ p" g" s' w2 j
- : l: U" h& w( G l
- class Life{
& A4 O2 L d" H. J - function __construct(){
& g' \% D, n! N, Z - echo 'cat life!';2 q; x1 \, P; p% `7 u7 F: `
- }
& G/ @6 m; b: M& p) h - }
. f. w5 z* g) ?! b! Q# {$ X6 Z! {2 Q: w - , Y( o) _+ q7 T6 U$ B# Y
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间; s- @$ [9 C/ v2 P0 b. U3 e R
- new \animal\dog\Life(); //A3 x' E( L* p5 W( J) @- r/ q
0 ~1 B4 K: R( y- f+ o- use animal\dog; //a
8 d' s1 C; c0 Z0 Z - new dog\Life(); //B& }4 Z" g9 e j" V
, T) t `7 G9 L. Y8 U1 [6 h- use animal\dog as d; //b9 o% F9 t# b6 @' C! q
- new d\Life();
复制代码 8 X! I) `. Z1 {& r
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 3 P* }+ C+ D4 [: l, s, _
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: ' ]$ F+ {" j. k& U s/ r; h: ?8 W
相当于
( H- V/ b' o5 w2.namespace后面不建议加类名,但use后可以。
# Q, R( U; ~" V: Z# m- //name.php% f0 ~' U2 l4 t2 ^) M l( [' m6 X, _
- 7 ^+ [- n6 w, U' d% T0 L# O
- namespace animal\dog;
' w& ~% i- P- D! n/ Z8 } - 7 R6 c0 ]; p0 b$ X0 J
- class Life{+ z( k: M |6 o9 Z4 @2 `
- function __construct(){
) Y B P+ X E; k& A* E. v - echo 'dog life!';
1 B% X% v) q% ]4 d - }
1 j( ]$ h( A9 F6 b) j. l - }7 g5 z( N' ~) Z$ c
# V6 m6 p9 z3 R% N! X- namespace animal\cat;# G2 M! V8 ~; e0 m; k
- ( Z0 C/ k) T5 i* c/ P9 ^6 a
- class Life{4 l2 t+ u3 v/ n; R! W$ O
- function __construct(){
. Z% M& Y) `0 p- {( f - echo 'cat life!';" E( a9 a2 N! r3 t: q) K/ A2 | H
- }7 p% C$ \/ D- m( s2 t# M- c
- }
% V! z- E3 ?! \6 A/ J; b. p1 x
( S& ]5 G& ]# c3 I+ Y! J; g- use animal\dog\Life as dog;
/ y5 A. G8 f1 d; U) [. Q0 Y - new dog();
复制代码 - V' |/ \) ~* Y* t# b
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
9 i- O1 ?! Y" U D因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
1 V( _1 D/ ?: Y; ^9 K# Z2 D
8 F3 {. @% b/ f, h3 T- namespace animal\dog;
7 e1 Z/ O/ f* c; T( I3 ]8 S
$ y! c2 d z4 g9 t0 J- class Life{
9 G& L" a- ]# o! I* j - function __construct(){# z6 e$ W2 ~8 n% x$ L0 F
- echo 'dog life!';
w! y- J6 v( Z0 N - }. e* [, M2 l8 V$ s o
- }
* R. n# g! |/ n9 X/ \ - class Dog{; U2 H5 J! O& ]9 u
- function __construct(){$ Z1 M0 t' P2 g
- echo 'dog in dog!';: a. }# \, p1 C2 [. P+ c8 w
- }3 k6 W8 g* I% e) z$ a; G
- }& Z& l" f9 j8 _/ b" l8 k7 `& ^
' e0 K% f, e) `" U- namespace animal\cat;6 L, u. H/ X2 X0 K k0 Y6 j t
- $ I2 w3 z# ?& i9 B& \: \& |) C$ E
- // class Dog{' g3 _, E# R- w6 o' v
- // function __construct(){/ |3 D" r$ |$ T
- // echo 'dog in cat!';
0 U% o6 K1 F9 n( q; p - // }1 b6 N2 m3 x" c w
- // }0 [# C2 c% M. R' ?2 A1 M( ~! d7 x8 I+ a
- class Life{6 L. _- O! i& g# J* k* c" H0 E
- function __construct(){$ ~& H: k3 N7 B1 v, d! k$ N
- echo 'cat life!';
; l" J6 ?, S$ j: P0 r) _ - }: \/ b$ e; k1 v* g G
- }
0 g+ C. V: S' k- S8 Y
1 W2 X, b8 Y3 d0 a, O0 I: s- use animal\dog;
2 `' p) N5 T; Z - new dog\Dog();
复制代码 , \- W! J- r2 i( o3 T
如上,使用了 : C. E+ w7 L/ E9 Y" Z
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
. v' n6 p% }# t* X简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 - Q# t7 F* |& w% W8 S
1 m1 v! R& q5 H: C/ i4 |
N. |7 H& }' A. k+ I0 Y; |
3 o: e2 V. i( {* f0 W. v* n. L
. ~1 T: ^+ S; g: s# K |