|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
' M8 [# p( E- z' |0 a: f文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 / m3 h( B. N4 h/ l9 T# ? o. I* h
: m8 a% ~: q0 ]. b" T( l5 z& H
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 9 ^. u9 C9 F4 r9 ?' ?
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 3 b1 Y1 G+ [; ^ l# r
结合使用方法来进一步理解它的使用目的吧。
/ A, Q$ _6 }# @8 Y
, p: G, E& p5 J9 }7 v$ Qnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
, H6 c5 q: G0 u6 S5 f- Q+ X - namespace One;$ s9 ]8 u1 E4 e
- namespace ONE;
复制代码 * U& v+ |9 ]; z+ I2 N
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) & f5 G/ ^5 E" w+ b
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
. I1 s# P- n0 Q" g& E0 e - class Person{, n4 \, |# t b I- p9 h- p
- function __construct(){
4 t4 U3 C9 M8 f - echo 'I am one!'; N( r9 c$ \& b5 \
- }
7 \ m# G- h7 n; k! `8 r - }
复制代码- //name.php! R" \( B+ D l+ q0 ?
- require_once './1.php';
& l& X+ V ]9 J3 F# p9 E
6 E6 h, S# Y0 X" E+ }4 B- new Person(); //输出 I am one!;0 j* ^4 n3 N! L, {9 K
- new \Person(); //输出 I am one!;
复制代码
- K+ e' M: o: W# u7 R3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
5 [$ Q& `% U+ k" w/ R P/ Y3 ]+ X - require_once './1.php';2 U+ C4 ]! v& H; x" w
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
% {/ j2 | H8 f" n4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
* C+ i5 V0 { S8 A2 z - namespace one;- f) E. A+ h+ [9 n/ [# i s% U
- class Person{
9 M" n' j1 H. P9 O9 | - function __construct(){
# t' e/ S! Y" [& t8 q - echo 'I am one!';
' s' n9 d- \/ t6 n5 ]" o+ h2 T - }+ ?) _, L5 E9 D' @
- }
复制代码- //name.php) ^! n' D+ K2 L( R
- require_once './1.php';
2 b# @; \' J$ x$ M5 v3 p, \5 f - new \one\Person(); //输出 I am one!;& Q% A# H4 l# n3 R2 F3 u! ~0 E. M! x
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 7 n7 Q* t- ]' g, g
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 $ \/ E. L, T$ n( i3 P, p( o
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。) z2 p% A. X, i+ i
- //1.php
* m& F4 G @3 ?# a$ g - namespace one;6 m$ J1 `. [: d7 e" r2 ^
- class Person{
/ P$ v# `6 h- J - function __construct(){: ]$ w0 R" t; d& a. A' W8 K
- echo 'I am one!';1 a4 e0 W: J" A) H7 r
- }. V( D: g% W# c
- }
复制代码- //name.php
+ j3 E' u3 E: g - namespace test;
9 B9 A* d4 A# T - require './1.php'; 9 ~( y" M |5 z' M- s5 E9 k
- new \one\Person(); //输出 I am one!;
* {) C2 k. P0 X/ W* ]2 v8 I C0 _ - new Person(); //这里结果会是什么呢,猜猜看
3 u- @3 j4 r7 E4 G1 ^ - 最后一行结果报错:7 |8 i& p4 v" I& i6 G
- Fatal error: Class 'test\Person' not found
复制代码
9 `; S& P% s0 h( _* }2 x+ b0 p& D
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
* Q$ n' o" r3 [结果报错: - Fatal error: Class 'Person' not found
复制代码
3 o! y& n1 x* g' M" ^4 F接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
, ^8 T* p' L6 e - namespace test;
2 N4 u, h( B$ Y6 B0 [ - require './1.php';
4 L' q. M2 V; y1 Q* F/ T - 6 j' W0 [9 g+ s
- class Person{5 G1 N8 G+ x% L0 `" [1 P
- function __construct(){- P% S. F8 N0 M# r" W/ d
- echo 'I am test!';! M6 T, s( l/ E8 c+ e0 C* @
- }+ Y. K: M4 Y v
- }
/ T$ E7 \; C& T3 e5 l. {
8 J% v/ l( Y& K' x- new \one\Person(); //输出 I am one!;! c k/ f. B/ F( m9 `
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 , |9 a! V6 ~( X7 \* `7 ~
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
2 [1 N3 q8 |/ a - namespace test;/ t& X- D. q) A. }$ U
- namespace one;
, _; _0 a K4 I& ?- m - class Person{2 Y2 ^; g! v3 o; m% ?: k
- function __construct(){) O; Q: `; c. t- ~0 p. u7 X
- echo 'I am one!';
/ s8 y5 c0 _6 g% U5 |5 G, G- I - }
, \# Q/ [( O% K8 h - }
- ~$ c3 j1 e4 g7 S3 E - 1 @+ ^, q5 T8 X2 G
- class Person{
6 B6 c- }7 w. I, e( l! j7 S6 T6 G. f. A - function __construct(){
6 ^+ L0 y/ l' N% u9 c( b - echo 'I am test!';- U& V# v( H5 W* K% K
- }! W- a) G- F) C, z/ A. Y
- }
复制代码 9 F6 D& P7 z$ M8 e0 E/ ]( x
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
Z" i/ h3 T6 Y8 b3 T看来简单的把require理解为替换,在这里行不通。
+ x! y5 a Q- y K6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
# S0 w8 X9 A& B+ `- //name.php' O4 u. @1 h9 n$ f, r9 D
: Y2 ^3 V4 K; J" _% f- namespace test\person;( b; K7 u' ^6 O
- ; f; g- l K. [1 v1 R; g
- class Person{
: d% v" V& v8 |. n - function __construct(){
* ^- t) `8 g0 E" S - echo 'I am test!';# y; l; k! D. c& l' L
- }3 s2 p/ L; R. F% q; R, V, O
- }
: z" W( s( L/ J! S( C" ? - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
) k( P. v' K: Q' ^6 a不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
/ p: @+ a; i# P, \7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php/ Z6 Q' s# m: m W! I* P3 K
F# ]+ c! X% \4 t) |3 S- namespace test;
3 A, P- c& k- M# z* p - echo 'zhai14';
8 C: \: `% W3 @5 ?" ~0 _ - namespace zhai;
1 w* v$ K, \1 ]4 e5 l - require './1.php';
复制代码
5 S: A6 ~, r; {% D$ xphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
9 [# C1 S q$ a2 G1 K! ~use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
# s( [6 V ?2 z+ [- //name.php$ Y3 X: U, h% F3 _7 v; h6 t
- 2 K1 s# x" Q: T6 G
- namespace animal\dog;
0 s2 B6 S3 H$ }" Y
9 a7 o) v! R v( G- class Life{3 }) k( I$ C, s, i/ I6 l
- function __construct(){: f" O2 ^3 u$ Y, r, L( U9 J
- echo 'dog life!';
0 d: C& a* x4 n1 i" S9 ^# W - }$ Y, s9 n, c. B9 L. G
- }
' L$ m+ `5 l) K
4 ]! X; K& V" D! p2 ]$ v4 F- namespace animal\cat;) q- C. M G) r* u
( q5 l2 u7 P; j! ^) w- class Life{! [( g# K; A; N! H/ \! n
- function __construct(){
& }+ K% `" N: n! \% ^ - echo 'cat life!';) V; Q' r9 D/ z# j
- }
R8 @$ P0 O3 [( ?5 ^ - }2 K, `6 m$ h# d% j! ]$ ]
. z: x A$ L2 h: j9 v- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
p' A+ t, w/ s - new \animal\dog\Life(); //A% w: t( _. V, h; ^5 a
+ [6 x% G0 V" p- use animal\dog; //a
" V3 q0 ~4 ^# z3 e) U$ | - new dog\Life(); //B0 m- l( e" Q% M! @% V2 c2 q) l) N
- . I4 h& g7 c* v
- use animal\dog as d; //b; S5 y6 X, o1 f" B. A" @
- new d\Life();
复制代码
) y0 v0 {- F, I3 c( T7 l: w通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 / w; R7 _" r* Q; h
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
7 x1 y4 a2 o8 l4 z9 n G相当于 # H0 z2 l( Y3 m u k2 T
2.namespace后面不建议加类名,但use后可以。
$ ^2 _' W5 @$ F- //name.php
q! ^9 Q) y7 T; p( W ^
2 @$ Y! P8 \5 b4 F7 ]1 {# U- namespace animal\dog;( j+ q9 {8 [8 ~; |9 R
* m% H- ^8 @. T' n9 A- class Life{; L6 i. n" k+ C, N
- function __construct(){8 U% |, Q3 i# g* U) L; [
- echo 'dog life!';2 W) E7 w9 o/ W5 E% {/ t) C
- }$ k1 j1 f2 F! ]& C
- }4 l7 X L, B- @
7 @# H9 i2 J3 g q: ?/ w- namespace animal\cat;! T8 e* j3 f6 M8 r. z7 C- |) D
- ( s6 k1 D, ?7 \7 E* e3 l" k% W: O' s
- class Life{7 _& w, w# e1 A8 ^) p: E1 V
- function __construct(){
' K" C' @. k s - echo 'cat life!';, c, G' I) t) e1 S- ~( G
- }
/ V5 n* r& u0 X6 u, t - }
% b6 c2 x: c+ ^4 \7 Z
) Q- F) m( J( z3 U/ e- use animal\dog\Life as dog;
, O! R, I1 R# Z5 D5 O$ z8 S; D& D% A - new dog();
复制代码 * ^/ A; T5 s/ k6 K7 h0 B
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
/ F" ~) h0 \3 D. u因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
1 P6 ~$ c1 v* S* j- C) h3 G1 B
% E; l' f3 Q, S- namespace animal\dog;
7 [; ~) ?/ O0 x. T# U7 x - 8 ~" N" F$ N2 J, O, r6 }4 Z
- class Life{
( H" @. n' u# A5 w% M9 E; t - function __construct(){% V, f; i5 @! O, q* _8 K* Q. P- r. i
- echo 'dog life!';
" i/ P* g0 \; Q. X - }
% e. {! }# u. o- D* W* u- J - }
) [; o3 f2 x" Z: u# c. _' X - class Dog{
4 p/ _! a' }" s L4 ?4 U - function __construct(){
3 x a2 q; \4 W, M* x' z - echo 'dog in dog!';! _, E( S( W4 }6 i1 p
- }7 [9 K# S7 S+ \5 ?% \' [6 B
- }
d3 K% K7 B( P5 {2 V. e1 m - - e( }) g2 k! E
- namespace animal\cat;" F& r Z x% Q( U
* A( y/ X% b, C4 A' n5 U- // class Dog{# m) ]- }6 J0 u7 ]- a9 n
- // function __construct(){
9 t* d$ J: i8 p8 L5 P - // echo 'dog in cat!';
; Y t; @& `: z a - // }4 K6 [5 t) W; q/ L
- // }2 T" A5 l( h; _& i) O" H1 s
- class Life{
/ N' F% f% }. s) p8 D - function __construct(){
" T" b3 e4 }6 Z: a - echo 'cat life!';* g# Y0 X) S4 {$ r+ H* A
- }
7 b! F! W# R) I k$ e$ R0 g) J - }
. U/ \$ O* F$ `6 ^+ f
3 n$ o5 `2 M5 L& W( Y; P- use animal\dog;
4 V8 y' I9 k. P. a q3 B - new dog\Dog();
复制代码
' ?" w. Q' M7 y如上,使用了 G" ]: @; R! S/ ?$ v& P6 ?. |( ^
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
* }8 l/ Y- T% }6 l5 p简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
5 k+ k3 M* L) R( \2 _0 d1 [ w9 `2 \9 I/ Z
# Z! z& G. n$ U- m, Z
, n% `$ k8 V1 T
- x: o: U+ Y! Z+ t7 ]) l |