以下皆为本人自我理解内容,如有失误之处,请多多包涵。
7 Y0 M q2 } H, t2 N文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
, |; S4 [8 T! u+ d$ y: x
4 E* X3 o2 F' N1 K h使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
7 z8 ]# f0 ~8 Y2 k& y据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 2 Q- N! N& d7 `; o2 d
结合使用方法来进一步理解它的使用目的吧。
5 b8 J5 K. i* Y( @1 E4 A+ A$ ^$ @+ `
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;# u& ]2 R1 ?+ H. L
- namespace One;" s7 S2 k! V: l# v7 R
- namespace ONE;
复制代码
* \7 Y" X8 n; [8 _5 ^如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
( R. U0 l9 o* v, F2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
: O: \2 ^" E8 R! [* m) O - class Person{- `# l' M2 B6 ]8 S2 T1 e; G
- function __construct(){
! E0 W" r/ k' \# @+ F1 E - echo 'I am one!';9 A2 ^+ d0 H; x' [) `
- }6 C& Z |" p' O1 G8 \( t6 Z
- }
复制代码- //name.php; u7 H5 b4 K1 n( I0 L+ h
- require_once './1.php';6 F- o# U3 d! c; @9 m
% r$ t/ Q& n1 Y Y- new Person(); //输出 I am one!;
& ^& O0 Q' W6 i: f9 ?+ s - new \Person(); //输出 I am one!;
复制代码
% }: l! K' Y1 W3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php/ }% [, q2 i: @) _! m$ z; J6 S! O
- require_once './1.php';! m+ y3 e# V. t/ k
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
# |4 K0 J; n; a4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php ( I: m# u3 M7 x% G# x6 H! @; L6 p
- namespace one;6 m5 t+ J% T' L/ n9 H* r
- class Person{
1 z/ c% `/ r# b4 x' q - function __construct(){% r0 B# v0 v/ O; y: w; f% `" A
- echo 'I am one!';
* ]7 V% J! w* `; r V - }, F' @" C' q( f% V0 }1 X6 ^
- }
复制代码- //name.php. h* I# i$ D* k3 Z3 N Z. k
- require_once './1.php';4 m) I0 r" }0 s6 j, L
- new \one\Person(); //输出 I am one!;
! D$ D1 W- d" x/ T% m: Q - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 , J! Y9 `" u1 ]& o6 q: E% [
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
7 l& j& J6 @# o, H! R' Y- }5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
' H1 {* s7 `9 |$ Z: ~, t- //1.php ; O; E( a& q- c; H
- namespace one;& H5 [/ S: \, g. l4 t' R+ m
- class Person{( j8 I& J2 z, n$ j: Y! g0 j
- function __construct(){
" q4 L# C+ i2 p g - echo 'I am one!';; z3 @8 d& V- q+ a q7 X
- }- V1 D7 U4 a# L" m- e4 P
- }
复制代码- //name.php
0 S* |8 |+ b5 l$ S. ^ - namespace test;
- B5 }2 h9 W9 P- C+ C - require './1.php'; : g% ]" \4 [" d9 w C$ Q: ]
- new \one\Person(); //输出 I am one!;
0 Y2 J& j: L2 H: t' V/ W' D - new Person(); //这里结果会是什么呢,猜猜看1 @, m% c# L y S* x+ f
- 最后一行结果报错:& k( F: l ]. i
- Fatal error: Class 'test\Person' not found
复制代码 ' F( y4 {7 e0 B% ^* ]0 b6 _
" [; _* m8 _2 n$ S0 b6 A1 D9 W+ u首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 3 L! f3 }0 t, l9 k
结果报错: - Fatal error: Class 'Person' not found
复制代码
2 _5 W2 M" v5 \! o接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php. r( A; j7 m# |8 s# `+ {$ _/ n
- namespace test;$ M) l# N$ s% ^) S6 j' [0 T
- require './1.php';
3 R. U6 }2 {9 }: b) h. e2 H3 Q! L - , ?; I9 Q/ @$ \6 y% R2 h
- class Person{
' `; P" x4 P' H2 S" C% Q6 p& T+ x - function __construct(){
1 V2 d$ D0 A# W- O - echo 'I am test!';
$ S4 P3 ?$ C3 K' b, x" H - }4 J# ^0 j" M8 E% H
- }; B8 r: {* g) y. M/ m b
- . n! c6 `/ B& h% y
- new \one\Person(); //输出 I am one!;7 p" S4 A4 d- h: c$ @2 W
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 8 ]/ z6 d! b) @' l! G8 m
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
' X! Y6 j& @! Q$ [. I5 m6 [ g - namespace test;
& G1 h3 \, N7 b' `/ m6 U - namespace one;" ]$ E2 G0 x! G9 q' E
- class Person{
0 ~# j& {6 t# `& E2 F - function __construct(){
9 B) t$ Q7 j& k( N. ~6 q1 K - echo 'I am one!';4 f. j5 p/ E+ g) Y1 n
- }
+ Z; F4 x; b! x( @+ g, g3 Q7 t - }' R0 s4 y# Q$ S# q7 R' C* o" U0 U
. ]! K4 K# y) h3 E) D! c) r5 c- class Person{
8 T3 Z9 C2 B& ]# j - function __construct(){8 F5 O; e; X: |; ^* ~2 U
- echo 'I am test!';% K6 I; j3 L: G+ r" a7 R& E
- }
/ R! y1 K& X, C( A - }
复制代码 " ?5 t2 ]0 D/ K3 H$ M* m
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 - _4 m. H% g; Q* B B% P ^
看来简单的把require理解为替换,在这里行不通。 " |# n- L z( X- c/ V5 r" ]
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" h5 K/ A3 q' I* _2 f) k; Q- //name.php& n; X1 |/ a6 \* @2 z4 d+ M
- ) d/ T A; f& t& S3 z5 Y3 R1 H
- namespace test\person;, Z& u5 a9 k9 h5 o
- # b* b' c3 K" X9 K3 y: H
- class Person{( D6 q% c2 y; w a R5 o
- function __construct(){! d: _5 S2 y0 f" ~5 S! v4 D9 E
- echo 'I am test!';
2 X6 i% {( d$ ^2 Y0 C& ^& D - }
F2 [& q" ^: j' i - }" b( F' @6 K% u0 @ s$ m
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 . Q6 w' k; {) E" y0 I
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 " p. t- i) e ?/ z" x5 j% X, J0 h
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
0 l) J4 |+ N; I- z
+ }* F" y/ L- J4 @5 `- namespace test;
7 B' S: X3 h1 y, o - echo 'zhai14';
) Y) M$ q" r& q& l) r - namespace zhai;
0 G1 r! e2 s7 `$ ^9 ^/ `/ g! d - require './1.php';
复制代码 2 h$ ]$ G% J6 f5 L
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 . ^( z& `( j5 G0 _3 _& j
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
0 f0 a/ {2 \1 t; c% U" l- //name.php
( p1 W' a3 f) y - 0 L. |: A0 W7 s* q) q
- namespace animal\dog;
% A% B. O! r7 l+ n; k
; c: X2 H6 I! p) r- class Life{
+ {# d1 S+ P; b3 f- M& x/ y - function __construct(){
3 I1 n, x4 ?7 F0 e0 y - echo 'dog life!';: J: w' t! h1 {1 }$ Q6 X
- }
x; ^: p4 R4 E9 M - }
) E2 ]* |5 b+ S
* g V+ E& `/ _3 I% B( o/ w% Z& c- namespace animal\cat;
/ \9 Z2 o, P" V7 f3 S
# {- w- U6 G9 q) s& e! [: w- class Life{4 X. B& p, D! n. g
- function __construct(){) Q& F3 S8 }5 W6 a( A: [; c
- echo 'cat life!';2 P7 \( W; V3 Y0 T
- }4 N; D6 d' g. ]( J" |/ L9 ]/ a
- }
0 I; c( L7 l# ^/ K: m) o) d - $ S: ]1 V7 _8 y
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间8 ^) R4 {2 R( V& R2 K4 {
- new \animal\dog\Life(); //A
/ E) t8 C" r8 i3 S0 g2 l1 l4 V* L - A. x- M& i- I" s5 Y6 J
- use animal\dog; //a# S, Z! ~0 ^' j; t0 V
- new dog\Life(); //B4 J8 A1 ?4 T5 j, |& D* v
- s/ X, c# ~* \4 I: J- use animal\dog as d; //b8 T5 x# D" w' M6 ]
- new d\Life();
复制代码
8 U) Q! W0 V" \) |' l/ n通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 $ U+ F( z# G/ p( ]( {
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 8 H) |2 [( d( k b+ |
相当于 % ]4 n/ X' r. V( h9 Y! s
2.namespace后面不建议加类名,但use后可以。2 a5 M; G) Z ]. E7 J
- //name.php
) p# P# D9 h% c* x - 1 r \$ K( ]7 @: P5 d# J
- namespace animal\dog;
- N) z8 K9 C. b4 B - 7 F- b0 ?* d9 V7 r/ H+ }
- class Life{! G2 q! q6 a5 [8 k- N _
- function __construct(){% B& v5 s& l. F' Z: [8 o
- echo 'dog life!';
" P8 k/ N7 c3 U7 s - } S- K9 Y! o P: K- x& }4 y
- }
+ q4 {5 B/ h& `4 u! j
) u7 Q! N( A, {$ S3 V) q1 I4 l- namespace animal\cat;
# m6 ^$ s! m7 t. U' Z
- `9 S/ } v) B- class Life{" e% o' @2 m$ w1 @
- function __construct(){0 _: q O) E& K; Q e/ L
- echo 'cat life!';2 |# J3 a- g r) } K" L$ L
- }
4 l) f7 h8 U, o6 D5 Z; Z, f [ - }1 Y/ {( [! Y$ H4 e3 d# H
- C: R2 g' q) d( g- v4 r
- use animal\dog\Life as dog;
( B) [2 v" W, C) c) p5 k - new dog();
复制代码 . F% j) C+ ^7 U
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
, p, Z+ m3 t- M1 x4 N因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php5 ?& a+ G0 Y1 S9 X- k' [
- ) W1 ?: ]" G$ L! u: {# ]" W* d
- namespace animal\dog;0 D" y4 l2 O! u b3 ~: k
- ' p) E& ~! I/ ~$ S" y9 t o
- class Life{
0 u- e/ T: L: _% `. T; @1 m - function __construct(){
# s' f( S: I6 e6 ~' D8 T. K7 j; ? - echo 'dog life!';
: M6 }4 X' ^ G2 G) O - }
) v+ E/ v: K5 }) O1 F7 e+ @ - }
m+ m8 @3 f; k( \6 L: E' S - class Dog{+ r# ~1 z! I! R9 x% j
- function __construct(){& }5 N) @6 ]& w% E
- echo 'dog in dog!';
+ U4 _. |) `3 Q - }
" Z$ |, P8 L( E - }
5 I b- s1 [7 |* u W9 {
0 i" v8 C# ~ {- S( p- namespace animal\cat;' f0 l0 G5 R ^2 l5 a& q* L
, B5 W- x$ V4 O& _' J; E) k- // class Dog{" {+ d. f3 ]1 n4 b5 K
- // function __construct(){
4 G0 p& v+ I! G9 q! t. R. ?" S1 ` - // echo 'dog in cat!';
) ^& y! T5 ]) t' t- b% I - // }
A6 ?: b! k2 E# K4 Y - // }
1 Y- f$ N0 S4 V* w! }) h7 ~1 ~ - class Life{
8 V( s! a' r1 F; L4 X - function __construct(){
: w7 O9 C" P+ M' M7 O# l - echo 'cat life!';5 A7 h& k e/ ~- t: k
- }1 A) M) S$ k7 d% l# L K9 w
- }
5 C: p) i' C$ T - 2 h% I1 S6 W4 n B* p: r6 w4 G4 Z
- use animal\dog; 8 i$ x5 T1 e% D" e/ k2 ]
- new dog\Dog();
复制代码 0 \- y+ [: J& G d% d/ }- e% o
如上,使用了 ; [# l$ n* Y' I& e$ D+ m) K
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
" B2 g; Q; C$ u, x' J9 [简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 1 \: o! R3 w k& B2 t
+ @, I/ D: N9 m& k4 _4 F6 X \6 v0 t% H& M- K0 D
, a/ w% o% _8 d1 d9 Z
' f8 G0 \* e, H! x! [# v% D
|