|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
5 L' _' ]2 Q" y+ h文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
7 j; j1 {! C5 d* r" M! j& ], K9 I0 g$ B0 F5 U; a8 C
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 2 q" Z; ]. C$ Y* T+ W/ O6 K9 l# t
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
* [# h8 |5 N2 a" i0 x, ^结合使用方法来进一步理解它的使用目的吧。
; S, {, J% ~4 e7 o5 ?5 t1 R
* ]; O+ J4 o( Qnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;" j. v, D# N6 D7 J8 y+ J Y/ f
- namespace One;
% @ v$ q: t6 S; H1 v6 j - namespace ONE;
复制代码 - d2 a: B# i6 s, V$ ?5 ~7 i
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) - ~; y4 E; C% Z/ p2 H: }0 ^
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 0 O) V3 r# u. m( Z3 O9 [
- class Person{
- _2 f! {/ W' q6 | - function __construct(){6 n( t; }0 n( F7 f. O% d2 A
- echo 'I am one!';8 U1 ~6 T- @, x/ t/ F( o+ v
- }
0 ?! G7 @- _ { z+ q0 | - }
复制代码- //name.php
) G; w+ y8 i" i# {* x: Y; W - require_once './1.php';
$ L+ | {0 @8 Z" Z7 K
1 u6 h2 V2 t0 g( u" W, H3 r- new Person(); //输出 I am one!;
# |" V7 E' [$ m2 t) F! D4 s - new \Person(); //输出 I am one!;
复制代码 ! p1 s- q' P6 ?* s3 C, [' O5 z
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
% T9 I6 R; a q5 `. f. R, K - require_once './1.php';8 M, E2 t+ M o% X0 u) F; t5 ?) p
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 6 ]5 k5 |( K3 S- ?, M: n
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php ) Q+ u8 N; t0 i- ?( ]
- namespace one;
* `. E4 i3 } q7 g3 u3 \: o - class Person{9 W( \8 X5 e/ U* o9 B. C) h
- function __construct(){
9 v/ D! f# `/ T) n7 J. x - echo 'I am one!';
0 A7 I" ~! B# _4 i - }
/ T) [ R5 V$ H) L) c9 m8 e - }
复制代码- //name.php
& H3 s; {1 Q- h P6 r5 D3 y' A1 k - require_once './1.php';0 y3 F" ^9 d9 ~. ?+ E' U
- new \one\Person(); //输出 I am one!;
" e/ a. l, U }. ~1 S3 \ - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 # B+ ^8 P" F5 Z9 o
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 " ^; C0 P8 o% X; ^. L
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。! I8 ?7 l4 I2 T# G9 x0 o
- //1.php
3 l T; O0 }. [ - namespace one;" s, X* O$ [- Y K* m/ b
- class Person{: }2 r/ K$ o9 }
- function __construct(){
6 u1 a8 ~8 O8 C) @9 } - echo 'I am one!'; n" J5 F [- m/ B$ g3 n) v
- }9 E9 }7 Y: e9 P* q( o1 ?
- }
复制代码- //name.php
: O/ J$ P/ I$ K - namespace test;% A1 J7 H% }) s* \
- require './1.php';
1 u9 [& b8 W+ |1 G9 N - new \one\Person(); //输出 I am one!;
0 d2 _6 R& L: D8 @8 ~! ^6 ` - new Person(); //这里结果会是什么呢,猜猜看
" ?9 A9 Z% C* E+ i! s - 最后一行结果报错:$ r) F- T" N1 }: R8 r8 _
- Fatal error: Class 'test\Person' not found
复制代码
+ R4 ]2 @) m0 D" S( T- B | D! O" m. w% l1 _
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
4 X8 X3 q# H, i2 Q0 a1 S$ K结果报错: - Fatal error: Class 'Person' not found
复制代码
5 B0 d# b/ |( l& n8 r% P2 V. |2 n接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
/ d5 B) q. N, e4 v3 o - namespace test;7 _0 @# m8 x3 M+ p# E% @+ a
- require './1.php'; 6 H# m4 a( l" s+ H" ^
- ' H# v: f0 I" X
- class Person{
9 f* s& d5 u1 V O, @/ M8 ? - function __construct(){5 n( B. u- c9 Z8 B/ R. ]+ h! N
- echo 'I am test!';
@. w! \/ \1 p& q - }* @ S" u- J' |. l
- }
' Y' L+ S# W" u4 R. U6 a - 6 r7 }* ]6 c; `" n1 h% ^- o) A; m* y2 @% {
- new \one\Person(); //输出 I am one!;5 v0 X4 x ?; W1 Q9 P" w9 H; {
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 ) _9 ^/ R( }# M- q
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php' R. }( _& W& C+ C+ i* A1 Q$ T6 N7 v
- namespace test;
1 q3 [2 n8 p/ u - namespace one;+ H3 {( I4 O! n6 b
- class Person{
0 B' ?4 _% L \) z& i. d - function __construct(){# O$ P8 L0 f* H
- echo 'I am one!';5 V. a6 E% E, l, @5 B$ J2 D
- } v* ?7 E0 H( l: q n
- }
5 A& s& I/ t! B9 q - , {0 c- i8 F, r0 \2 \. g, ^- f
- class Person{
) I) _4 E# C( y: u! Y9 c+ ^) m - function __construct(){6 }% p: p x$ {
- echo 'I am test!';
8 S$ S% b# I5 L6 D5 e - }
! _! I5 O2 z- H/ h) z6 L# F - }
复制代码 2 q2 n- k& ~) J# T. S
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
0 A8 O' P; {4 G- V# E看来简单的把require理解为替换,在这里行不通。 ' _. D: h6 M7 t6 a: d. t0 p2 R
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
% l; ?2 Y$ r3 S O5 j2 g+ S4 r+ G# Z2 S$ w- r- //name.php& b* D, S! M- b) I7 j
6 I" p# S' ]! I4 j+ d7 z- namespace test\person;
$ m) e! M: d( k" B/ i - # p2 g% g5 s4 d" K
- class Person{
# R' L; h! s. [( u W2 e% B _ - function __construct(){
7 K5 [' J$ X4 w' ?% j7 W4 h7 c- p# }8 d - echo 'I am test!';
- o" b1 i/ e7 ~ - }9 l) |1 [- h5 @' |/ O! U" b- m
- }
6 X, K- }* [; ?7 G9 I5 `6 F - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 8 t, j( q! r5 T; x# j+ K$ I
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 $ f6 W1 ~/ _# ~6 t7 |1 R$ q
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
0 ]1 K( F* L# L0 H K# V9 ~ Y - - O# L$ ^; a0 {* e( Q3 m, U
- namespace test;
- V# D3 o+ D: z/ Q - echo 'zhai14';* }9 p* Y. l- h/ p) W, X' M8 T
- namespace zhai;5 y: w g0 n8 l) {0 P, h
- require './1.php';
复制代码
4 T1 a. T, z# aphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
: m! ~6 C8 T5 k) I. fuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。& `; h1 ]2 y1 S# M( X: ^% I
- //name.php* p* W O/ R4 ^# M- ^
1 Y+ p: f4 g' F) g$ E6 j- P- namespace animal\dog;
& o$ }& M+ |+ j3 F
' ]4 i' m5 D2 b3 z( t- class Life{
: l$ J2 j# j2 O- _# b3 l! B - function __construct(){& O* u h0 b8 R2 B5 t( ^/ _
- echo 'dog life!';9 `' B* x* O3 w f' z9 d
- }
3 r, Z( _: O, T% m - }
" X3 G* Z8 e$ E4 B* ], M
, F& I9 F7 y, H% W6 ^- namespace animal\cat;
% ?* R0 D% q9 ?. Q4 r, o5 R, G - $ h8 }& S: l" m6 G! j: ?2 K ]) y
- class Life{
1 E( h4 c; I1 k( i; F! f9 \7 q4 Q - function __construct(){6 ~: G9 I# {/ M" J f, P
- echo 'cat life!';
9 b* w, Z5 C+ t3 Y% S2 T - }
X. r( }# K- C& R) F: A - }
3 W4 |$ \. k. ?( m% p1 X - 4 n$ d" ?# z$ {& D$ D! b- E( J
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间 D, Y, V4 f5 q- X8 x
- new \animal\dog\Life(); //A
1 U% w9 X* {' K# n
8 J8 N% _( ?5 `% P- use animal\dog; //a- R: D, G/ h; ?* I
- new dog\Life(); //B
$ ]+ H6 L" t* x; P" ~ - 0 T+ e0 q9 p: ^2 q3 g. ]
- use animal\dog as d; //b& B0 x4 o: @$ w2 M" l
- new d\Life();
复制代码
4 e# k1 P$ \+ H/ x' @通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 7 O# ~% q/ ?9 U6 s4 B
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: : L H' B) ?/ M" Z3 O
相当于
. p' x: @8 d0 C. Z$ {2.namespace后面不建议加类名,但use后可以。& J; A- Q9 w) e
- //name.php; b1 |" {0 ?; T8 g0 \
% C n$ g3 J3 F1 Y- namespace animal\dog;/ j( ~5 Q Z: {5 {
- ; |) u7 U7 k* `! [ V" E o
- class Life{
$ P& @# }, y* U% F" o* w - function __construct(){8 o) `- q1 }% A" |9 d
- echo 'dog life!';1 b; f8 x- D8 H( v# T! E
- }& U2 t/ M: z5 N. Z2 s) i8 x
- }+ s6 J' z3 }' U7 M! D& x" Z, s
3 K: @; L! [6 D3 _& j0 h' F- namespace animal\cat;
8 B D- H! M3 N7 P - , e8 R7 @, ~6 j+ Q' @: M( @3 `
- class Life{
. g( i# i7 J# N4 I; z - function __construct(){* h7 I) c+ z9 @
- echo 'cat life!';% ^3 w! L$ O- i) z$ y
- }, {9 c$ T. f, L1 v" l8 [ f6 T
- }1 G! K `1 R* \/ [3 H
- / {1 [; ^+ ^7 c6 G7 H- @
- use animal\dog\Life as dog;
' U3 E5 S/ X/ {, c - new dog();
复制代码 + N, Y1 w$ X9 f# W9 `* z
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 ! M; @6 g F% a# k) u- h( ~
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
k; Z3 w) j7 r+ e: B - 9 Y# v% ]5 D& N6 p8 L+ A, X
- namespace animal\dog;
9 r3 }! P: B/ y - * I8 e9 o+ i: f" F
- class Life{
* b! ?4 y a: I - function __construct(){" P2 L* I5 X6 Z) ~$ o+ o J3 }
- echo 'dog life!';
) J+ P2 s. g2 w4 R/ x - }* y3 j! s6 @$ {% l% L8 E
- }
; ]. m* z0 f* u0 ~/ r" l4 O - class Dog{+ C5 b) `- c# B$ V0 G o. o$ D
- function __construct(){
* ?2 \( D8 x' e: J$ t - echo 'dog in dog!';
0 l% R: ^& S/ o3 j m" w - }
5 Y4 I& a. o6 N, Y: { - }4 h* r# \5 T% N w
( Z% p; e9 i) M) F- namespace animal\cat;
2 m9 w. |# ^, i! { S# q" | - # R. [; ^4 O; T5 b Y
- // class Dog{
* y3 Z& M! w6 c - // function __construct(){& g" D% W! L7 `5 T- o, ?
- // echo 'dog in cat!';. p% P: n: b% x/ v$ ?
- // }
$ g/ ]6 T7 `9 q/ O2 P" @) B7 C - // }
- F( K' B1 [/ V4 |" d" T8 t - class Life{
+ |/ N+ A# D5 y, i - function __construct(){- { f& m. T6 `
- echo 'cat life!';& p/ i$ k# d' X: _
- }2 _: \$ I5 n' j" h( ~; P
- }/ K% k% {5 q* e. L
}- A2 F+ i( o3 V- use animal\dog;
. E$ r" r) l q; g. o - new dog\Dog();
复制代码 6 r' j) Q; p9 T+ c' q; \
如上,使用了 6 B, R) H! V% P, h* e
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 " C% n$ g! Y2 e! \# W( f4 g
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
* S# Y2 z* o: c
: y) g& X* Z0 N# `
( v+ Z7 p: I. z2 K1 D0 Z. V# K6 P/ a2 ?0 {# M {& i
$ P) Q. B9 V2 K2 w/ B
|