|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 ( f. p8 Q' Y. c
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 * J$ t8 J8 w+ `) M f; V
! u4 O2 x3 \3 l# B/ O" G9 {
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 2 H# j* S- g4 l) ]8 O
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
+ {, N( j0 E& K8 Y. i9 l. G1 P结合使用方法来进一步理解它的使用目的吧。
8 P8 E6 T3 d& y( |
n7 x" |; f9 v; j0 T/ Qnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
, F) d# O5 ]& v/ a& \" n% ^+ _ - namespace One;
5 f# d; z/ K! g1 B - namespace ONE;
复制代码
$ s0 n+ H- v4 ~+ X$ T A$ E! \5 W! S+ c如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
8 w- ?4 F- n; Z$ Z& L; T+ m2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 7 a5 P! \3 V, V+ E, M7 l
- class Person{
9 F8 B$ p1 J: {3 ~4 U, [% z - function __construct(){+ |2 F. E* i) A1 [; ]( n% `7 `
- echo 'I am one!';! [8 d/ ^- i0 G) J9 `' v
- }" u0 j) Q5 l: A% l; S4 J/ a
- }
复制代码- //name.php
& z* b+ \% A+ r - require_once './1.php';6 {1 |% X5 F, J$ T, A
- . `3 _3 {2 f) O- }& @* M- a) k
- new Person(); //输出 I am one!;6 ]( |! B4 ^+ i8 _ L1 `! T
- new \Person(); //输出 I am one!;
复制代码
7 d! L, ~( ?8 {4 Z: b$ @4 d/ Z$ w3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php+ {; L# _ o' A4 S1 w+ d: E: i
- require_once './1.php';- h3 s0 V" h" X& j4 {
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
( J' I- D7 x {7 n4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
. b) z! Q4 }, x- s: q3 k9 ]0 W6 p+ G& j8 r - namespace one;4 o+ |$ S' k& }
- class Person{+ ~3 M# Y" `& b3 K
- function __construct(){6 R! s9 K: G4 A9 c( I0 {% j
- echo 'I am one!';
; a6 d0 P2 D. I! `: i3 Z - }
) y' }1 [9 g0 t2 [ - }
复制代码- //name.php( ~& v5 t# Z K9 C C
- require_once './1.php';
, o8 s' r! L8 C, ~: L& `9 L - new \one\Person(); //输出 I am one!;
, V9 V+ m6 g" {* w+ ]0 Q7 N/ H4 C7 a - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 3 R3 g2 T# Z+ m1 {
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
( D, a' j2 B7 h5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
9 D* b: R5 R- t% f6 E& f- D+ v- //1.php 2 j M5 f' Q* Y6 A; f+ [2 q! X) V
- namespace one;
$ s. _/ [% N$ a9 N9 a - class Person{
6 s, n/ p% D) `8 v1 ~ - function __construct(){2 `9 _2 k5 K# G+ N1 E X: G3 F& P
- echo 'I am one!';
+ p+ N" t) a) a: g - }
1 J4 T! I8 {3 R% w- I - }
复制代码- //name.php6 a! q R g" A/ t0 e8 p' t
- namespace test;
8 Y8 L2 \1 ~# o+ \ - require './1.php';
: \; s- t0 `6 O. d" [' l# I0 | - new \one\Person(); //输出 I am one!;
- f9 ^7 V$ j5 \3 [0 e+ ]" ^& s - new Person(); //这里结果会是什么呢,猜猜看% e8 M- g ?: p! A* S% G2 Q: a
- 最后一行结果报错:2 t: g; _2 Y* |# R5 s. q
- Fatal error: Class 'test\Person' not found
复制代码 1 j% T5 \$ A" z. b% Z
# R& X. {" R" Y! X
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 . {% B7 v# G" p1 ?; C0 j
结果报错: - Fatal error: Class 'Person' not found
复制代码
! b! w; h9 _8 @( B9 e+ [; |接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
& ?7 r) Y* X3 P0 W/ W - namespace test;$ o5 w$ x v3 ~ a$ ~. b
- require './1.php';
: ?: F/ v3 u2 m. J4 p* t - 0 K: {1 N, i1 H. ^
- class Person{
& h" o8 i7 _4 F- Q, a) b - function __construct(){
6 J; ^2 R. A% r8 s - echo 'I am test!';' o% c' ] ]3 X, v8 l4 ]5 Q
- }; ~* H5 `/ o1 i) O% e
- }
/ F6 y; t2 f# f0 o( c3 \; f/ y
: s- E% H* s8 Z3 i Z- new \one\Person(); //输出 I am one!;
; b" _2 d/ w) f3 b" T - new Person(); //这里结果会是什么,自己猜猜看
复制代码
7 x' s/ Y9 g! ~0 M) b: m* ]8 B最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php9 l& [" l# n/ \! {! [
- namespace test;
' {1 T4 Z. f! G* w9 J - namespace one;
+ u0 {5 M# {& `( d5 H& z; X7 M - class Person{ h) u' ]3 o) y: \# B5 J
- function __construct(){
6 M V- z; ~$ X j% H - echo 'I am one!';6 e' { \$ O, L+ P# W+ V- p, {
- }9 v* f. Y8 i" C4 y9 ~; f; @
- }
" q* x0 p8 p# S% Q0 W
- S9 q3 A& ^; H( Y+ z: J- class Person{
3 Z& E0 E3 G* u0 d - function __construct(){' K) Q5 z, n: n- h$ j
- echo 'I am test!';
7 C/ a8 P7 u/ u9 e/ r( n H8 _, d+ C - }
0 R0 b( E7 p( }8 b" c- M( Z - }
复制代码
- h* t+ f( U+ `% f1 Q, n无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
4 N' n- u X( C5 `" E) w2 X看来简单的把require理解为替换,在这里行不通。
1 D: P' v. G6 ~8 k: h6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
* i5 ~) q) @: V, h4 u0 e: ]- //name.php7 g% ?, w! u+ r& b V' v, Z) u
- 2 ?- _2 Q* u2 k
- namespace test\person;6 @. i9 G; j' o. C, ?) z( c3 r
; |; Z7 f% }+ H9 k- class Person{
0 \$ m3 ?9 I) X* H0 z - function __construct(){
, U7 d2 `9 J/ F) K8 R h - echo 'I am test!';% b; a4 m) w+ N, E, P, c8 u
- }6 m6 j$ f# k. ?
- }
# g0 R4 A) D4 W( \ - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
$ V5 ~' Z2 x) t1 A4 u不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
* U5 _7 I N v( S7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
. g# I. A, ^- i8 ~7 }) s - f! R M. f. U& \
- namespace test;
, w+ N$ ?+ T# k5 F1 Y. [ - echo 'zhai14';, M& x1 ?1 b* J5 O- v! o
- namespace zhai;" m; P- j; }8 f! _2 X3 l/ q8 i& a
- require './1.php';
复制代码
) B# b5 J* Q/ |' D8 k* {php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ( i3 M, p6 |% s# m+ V
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。2 m1 x+ s; |) w* U
- //name.php1 S5 x( N+ ?; s+ t
- 9 ~: O' h7 L" O m: S7 \
- namespace animal\dog;
% t0 `% u+ E+ _! G
7 f, X. y, J/ O' m' k8 d- class Life{
1 ^- s8 j/ A2 ` y - function __construct(){8 z1 B9 D, C- m
- echo 'dog life!';
/ s6 `0 @3 l2 t( S4 F - }
/ F! C) n) j4 o9 x - }
* T2 H, _: m) m9 C! ]' E
& h; C! _" f0 G; ~, {$ Q+ E- namespace animal\cat;3 m" m: r4 J" e1 g
- 9 X8 p- Z- o, p
- class Life{* G; k/ D) v: y$ P- x
- function __construct(){
; v; I6 ?! I8 W4 z - echo 'cat life!';% H8 E8 ?! O9 O
- }: E* {" P3 |/ }+ H+ W3 d4 s
- }9 c* I: q6 A2 ~% U5 ~& Y/ S
' _& S ^1 x( o8 h* O! n- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
: e1 v- e* A& ]. ^/ ]* q* |1 w9 k - new \animal\dog\Life(); //A B3 X" f; o% e- e: D
3 W% t% R) N+ D; z+ P- use animal\dog; //a g; ?! r9 j, v$ f, U4 ]; j- \
- new dog\Life(); //B
& `" @" {2 K4 n- t8 V# h - $ `/ {3 U6 F; n% y5 [! }
- use animal\dog as d; //b1 n! b9 M9 S6 d, K% \
- new d\Life();
复制代码
% l" r- x8 U/ {# Q$ A通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
+ z) j( L5 c9 t: ^* _8 u& a通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
5 ?& X! ]2 ]6 r$ L# C3 O4 B0 ~相当于
" o3 q) G0 f( Q T- p2.namespace后面不建议加类名,但use后可以。! n7 Q0 }, C, ]: E" }# G& v
- //name.php; f, {+ V7 | D3 {% K1 [1 n* H
- # S3 _0 }- u5 f! \7 S4 _
- namespace animal\dog;0 X- P g* D, g t8 c
, A s) E9 p6 Y4 W- class Life{
0 i" Q% ^( i# W4 }' O& w A - function __construct(){
8 j: t, o3 Q' C: S; X' s5 e& ? - echo 'dog life!';
; M0 ^& K( r l3 X. \9 ] - }9 Z" b. O& V. U1 c! I7 G. x
- }
' k. r, y! R1 F
2 F: Y( i; J9 {& ?- namespace animal\cat;
4 D8 K+ j: q0 x/ ?" y - 6 g0 r7 l/ f: U; T- m! J: b
- class Life{
. f R3 } ^- t/ M! d. | _ - function __construct(){7 z+ Y5 _6 e9 q7 V1 U0 V
- echo 'cat life!';
0 V7 M$ e; f4 n/ z! M# T" G9 f6 | - }
; _( D! Y( O6 O( c- Y - }
9 k& a( m# \" w% \
# [- k0 t8 l/ ^- use animal\dog\Life as dog;
9 N/ w- P+ z" T - new dog();
复制代码 1 g+ g5 X6 }2 i: A7 V& a
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
" O5 b0 ^2 L4 ]- v0 i因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
, w" O4 U' u. _/ A3 }
2 S" N0 _! H0 `+ {! G+ U- namespace animal\dog;! H9 F6 v) e+ M( L& `
- % d6 r' r) h# t
- class Life{' H, i2 C/ M) ?4 I1 \
- function __construct(){6 v* D1 ^9 U. G9 F) ]# E
- echo 'dog life!';, O: S# _; H* E
- }: S/ U: ^/ {% U# w; j" d4 m% Q+ x
- }: P( n& P7 h+ @( i5 K
- class Dog{
: V Z/ |2 p. Y* {2 w - function __construct(){$ {0 J# I- N' L s6 C( `
- echo 'dog in dog!';9 `/ p& o6 R+ M5 r- m* c" @1 T
- }
1 J% S/ R8 i) M6 c- N8 J3 B. u - }
, ]' u5 V2 Y3 N! X. C+ P - 2 C4 L$ {( H0 Y- C
- namespace animal\cat;
! i. N* f. Q3 p+ I: R
- h/ x# v: |9 h4 I- V/ o" Q y- // class Dog{
' I Z/ t/ Q. F: N/ l" m - // function __construct(){
; e! v6 e. [; g( S - // echo 'dog in cat!';- `/ T5 t: k# { H9 @$ m
- // }$ d4 w* g$ W% Q Y3 F7 x* P* X
- // } G l7 ^6 [1 o9 u5 u9 A0 k& T
- class Life{
' L9 ]3 [% k6 q, ]3 M3 G - function __construct(){/ h% f: K$ M$ ~1 A! \& k
- echo 'cat life!';1 S' m! m" K# l# T
- }" v# W% x) B1 w
- }
& M) f" N4 a8 {- ~9 _
* f) ~/ E7 l" X1 r7 ^, F- use animal\dog;
/ z) n, i$ ?* k2 E7 r - new dog\Dog();
复制代码 , Y( N }- l, l# L, D0 W
如上,使用了 , D) ~ q" {! t& R" O1 Y3 B4 [
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ! g7 e+ s4 `0 ^2 D/ b0 Y
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 % _) g; G0 Z' n6 p- _
' ?8 ]) I5 p5 o4 F7 o g
' @8 X3 l* Y2 t9 @* k2 p* z& ~
( l) U0 U; `6 ]; o' n g$ i
/ b7 o' G, }! h: t4 h& q |