以下皆为本人自我理解内容,如有失误之处,请多多包涵。
5 {) H: A' t* ] N! ~0 d文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 % [; ^" U0 ~9 U7 C
/ A' U( ? M; [& ]) t使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; " ~5 E3 [3 l- P: J' F
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
) T% Q( l! h; W q结合使用方法来进一步理解它的使用目的吧。 2 m: p9 F2 i6 U* U
& J+ k8 W" |+ @* e% X% Znamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
% U) X. y" i, V% ]& ~/ A" O - namespace One;
; t @' ~7 P, a6 e F$ O - namespace ONE;
复制代码 * \4 l+ q6 v M6 t
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 6 y5 [$ a* k: Z; Z& S% q9 T
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php ' g9 s' B5 ^$ j- G
- class Person{9 Y" _( R' ?( K
- function __construct(){8 k8 q2 q, j% J6 w
- echo 'I am one!';1 t# x$ G2 f$ {% n& S: H) e7 t( n
- }3 l. l4 {5 E3 B2 e
- }
复制代码- //name.php
0 w! j2 `+ |% o7 Q6 a( k: e - require_once './1.php';
8 c& p! m$ b0 X. J. Q8 T - * v' \0 D2 L1 f. c
- new Person(); //输出 I am one!;
$ d. g3 o& B T8 W, U; n( ~# x$ C - new \Person(); //输出 I am one!;
复制代码 ; P4 Y+ h% B+ S$ p: }/ E
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
1 i5 x- T& @$ K% h, V6 |8 G; Z - require_once './1.php';
# f5 ?7 P2 h# @( `- ? - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
, ~/ E- d$ J" c9 [9 M+ F& _4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 4 n% D% h9 v% S; P% @+ ]4 ~( z9 p' q
- namespace one;7 E/ b7 D4 r4 i& g5 [8 D
- class Person{
. G3 Q' p/ ] J1 z/ s0 x' g - function __construct(){
6 ]' `/ u# Y# ~2 h! u - echo 'I am one!';, ^1 R2 l3 u' V9 _; k3 s
- }5 h. h. I+ O! `8 M
- }
复制代码- //name.php
9 V9 B5 a* t$ Y/ D0 r' A - require_once './1.php';
( U0 q3 F& c, ]) V' H0 s- z# } - new \one\Person(); //输出 I am one!;) f, N, h3 Y4 c
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
/ i+ [7 @: M+ D3 G0 A. k可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 % M8 A4 G+ b$ U' L" n
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。, m) x4 S J6 R1 b) |
- //1.php
0 t+ L+ ]( x# |7 C5 L - namespace one;; ^5 j1 K+ l- Y' ?5 F* J
- class Person{9 o3 j! Z6 I" y/ g( ?* H
- function __construct(){
% U& K1 k% I& [ G+ T+ x1 q! Y - echo 'I am one!';
$ k% ]* \6 [0 m: j - }
. x' M M* O6 {. w5 W1 k. A9 G# P - }
复制代码- //name.php M' P; u& |* M2 Q0 l, W" F
- namespace test;) R+ {8 \# _# J5 C) ]1 S
- require './1.php';
: m* v, K" }) b - new \one\Person(); //输出 I am one!;
% w' ~9 |" u7 [8 q1 F& t. S - new Person(); //这里结果会是什么呢,猜猜看6 Z0 x% [# }; {2 j( k9 E6 L0 m
- 最后一行结果报错:
6 K7 u0 K( H7 I - Fatal error: Class 'test\Person' not found
复制代码 8 I3 \! ~2 s3 U5 z
; _$ i) M9 I, Q$ O* M
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
: r% ^ q1 p* s# L" q: \结果报错: - Fatal error: Class 'Person' not found
复制代码
% A2 U1 E5 m: W% k* ?6 P接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
4 f* R1 K7 v7 o! l: ?* ~ - namespace test;
9 G, H( k( i. _# J; E - require './1.php'; * B7 _, w. N! ?; ~+ H6 q( C
2 F! k$ a/ u8 I) [& G! x- class Person{2 I' ]9 g* q( U- J; F* E
- function __construct(){, u; Y' d% _; ?3 v
- echo 'I am test!';
! I8 M* g) i9 `% F5 N6 A+ a8 \9 r, m - }% F, n( d& D3 X* T" L
- }
* L! Z5 N3 k' g5 ^2 d
1 w0 ~: l N! C0 U) P0 @ G' L9 e- new \one\Person(); //输出 I am one!;4 Y4 V$ S! h, `: b! v
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
- G7 x% G3 j) ?2 P1 S最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php% e* l, \; ^; U- Z1 @$ c% |
- namespace test;( u8 Z2 {+ k; ^/ G/ g; P5 t
- namespace one;: m) Q( P# M, m2 B- ]6 V& d9 o$ W
- class Person{
9 m, z+ ]1 r, } M - function __construct(){. i1 p9 d/ l4 f0 Y/ r) G4 o' f
- echo 'I am one!';
! P/ _, f6 U9 r - }
0 v2 c5 R6 Y, K& W9 X0 w - }) k4 Z, B7 ~2 E% L3 L# V: C
- ( h/ R# Y, _( w" ?. E, d
- class Person{$ i" ~+ [2 W+ z; [' M/ J3 h( [$ Q
- function __construct(){$ o, `% r- p+ I: Q
- echo 'I am test!';
6 j8 _6 b9 a0 }9 w' E - }
3 f; w' t) g9 U3 O9 f3 u" g* [% t) M' N - }
复制代码 0 \ l4 Y" b7 Z. ]% N: g
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 2 f, D; F' V4 N I, R% q; [
看来简单的把require理解为替换,在这里行不通。
6 A- ~, u g9 O* i: o6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
4 E, m& [/ d+ @! B, {7 o- //name.php
. W+ J: R& ^& u5 r) b' U - ) z" D- l3 K+ P3 U6 p
- namespace test\person;8 D/ D9 B; F) I% t
& ^+ [8 i7 W; n3 F- class Person{) f- \% y+ d: P% @) W' S3 S8 M
- function __construct(){* i$ V5 t) h7 H+ y/ A2 L" P
- echo 'I am test!';
9 T' A9 G( Z$ Q6 f( | - }, Z' q. a" _" i) o9 n' ^) F: y
- }
4 \8 [; ]( W% f# B7 O4 i1 ? - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
3 L. L6 E: [* U( a5 B0 x不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
. o, q% N2 }* f4 `. ^3 W* H L V7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
3 _! p8 g3 T, M. L
1 n- y# p+ T* |2 x! l- namespace test;# V! x+ z8 A- I" d7 q2 y
- echo 'zhai14';% B, I$ G8 }) a3 v* l
- namespace zhai;
; W6 M- J; k% Y+ b/ b0 G9 t5 h& w - require './1.php';
复制代码
2 y0 Z. u% Z4 ?php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
) U2 ~2 `9 U fuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。5 q' U; y$ s; m: g4 o
- //name.php
! e6 U: }2 ^4 }; L' n2 w
. M) E# o0 t F- namespace animal\dog;
6 }* L+ h7 d2 l! P' n) E3 ^ q: F - % H5 F9 M; N& n4 E
- class Life{) i' M+ q. F/ z
- function __construct(){
0 O9 `* E9 d, o# [8 G* ~& ?1 }- C - echo 'dog life!';! S' O, Y/ X$ n$ G* [
- }
! [5 G+ x3 D5 c$ h2 D/ U - }/ H7 o: o- r, \( F2 k0 ^
- ) a0 e, r- M- L& n
- namespace animal\cat;
" J5 S5 W6 D/ y, t! S3 c - & W2 o" k1 I- A! N1 `' i
- class Life{3 H0 Q. q' ^. ]! X
- function __construct(){* y: D' g f4 { X% ]" c* E
- echo 'cat life!';
( V M& V' }' p( C - }4 ]* E$ p# w# e5 t* P- T+ E* C
- }. @* I# `' X/ N X
- ; j. M' E N5 k4 f& b
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间% M, l; q# ~, R9 e- V- p
- new \animal\dog\Life(); //A5 x% M) o9 O" Y. O' o4 J( e
- 3 [& b+ c; y+ X4 t1 M; h
- use animal\dog; //a/ L4 j2 c6 A Q3 I
- new dog\Life(); //B
, ~' o, J0 q" o - 5 A$ c' J: E. @3 Z6 j
- use animal\dog as d; //b
' G% X/ t& B0 J k4 h8 [ - new d\Life();
复制代码 $ C9 D2 N+ |5 n' P! M2 W
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 9 c. t" V. M, R; I$ r
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 3 p( N9 p4 Q& B% L, |. \3 W
相当于
4 n2 M& z; p4 Z6 Q& p* G# M5 U" |2.namespace后面不建议加类名,但use后可以。+ S4 x# @& s [: d; F9 K" u
- //name.php8 G. x6 d6 \' T0 ~2 v. i
9 }# a" I+ T9 }, X( z( y- namespace animal\dog;5 A. v6 {! W) Z9 `, p( g9 ^1 I1 E7 R
L O' A4 M! v5 G1 D- A: ^- class Life{
: z9 l" n$ `$ h6 n6 X" R - function __construct(){7 ~; \; S% k; i
- echo 'dog life!';5 v1 {) Q1 |- ^" o4 W+ l N
- }7 J* ]: k3 C* K5 }
- }
1 W/ e) u/ A' p( w n2 n2 w - ( c. y* O. B4 @9 F2 x2 A3 C
- namespace animal\cat;/ l) P3 Z3 C( f4 S; a
# b) ^# c$ p0 q u( ?8 P" q: h1 j- class Life{
( S6 O- _- z# S7 E. `! |# M - function __construct(){& {# j3 U/ u& o* I
- echo 'cat life!';' H. q% O! U6 Y' z7 c
- }/ v% z4 r: b- N' W$ y: B' V
- }* h" ?( ~" ~7 L# N: m% T
- 4 A& V7 d! U% L: S( F* C
- use animal\dog\Life as dog; & O3 t- f" D& g' p& J& z) {" U
- new dog();
复制代码
1 H J+ i* T/ w2 k. q2 e$ ?如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 4 d/ b3 m% U4 i% S9 E0 a/ \0 w
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
' m" n9 Y D+ Y% Q; b/ o5 ` - 5 m* f" [1 |! ~/ C% d$ W$ E8 M
- namespace animal\dog;" A8 G2 y" U, R- T$ `; I( C
7 Y8 ^4 M0 W! e( ]6 G4 w- class Life{
- \( }' F9 @5 v3 f4 u' \2 a& v5 Q - function __construct(){
$ A& A+ Q. L* g; `" W - echo 'dog life!';
+ N" f: v8 Q# Q$ Q% B - }8 I" Z; J/ w0 G8 g" ?6 s
- }+ W% `. f6 g/ d' @3 E8 h& [
- class Dog{
5 M5 g! O' m- Z' R$ s - function __construct(){
, G8 [* i Y; t7 ]+ H; }& b - echo 'dog in dog!';
8 g( o7 r, ]( {' A - }
) F1 X- |. K7 h2 z6 o. H/ h/ d - }( X l: z" ?; d9 x$ w7 A$ a
' f9 j$ c0 e6 @, M% v* ^- namespace animal\cat;9 ?! o2 L* _" a
- : ^/ m8 J( t; q6 \
- // class Dog{7 r0 a6 U3 R2 c2 U8 u
- // function __construct(){( g! T. B% d+ g5 [& ], ]* D
- // echo 'dog in cat!';
\" `( O4 p7 i( U/ T6 f J) S1 u4 x - // }
2 B; b8 i& d8 }" X - // }
" U3 }7 `2 u/ S) I/ o - class Life{3 T# ], t# H ~- A) S3 A& ?
- function __construct(){! k1 O' \) C* t. D2 N$ z
- echo 'cat life!';
( f4 M! S8 u l$ W+ W0 C5 G - }4 g9 l0 g$ Z3 N; ^5 D
- }$ d! C2 ?( r1 P8 @, w1 [; `
- : l! l2 Y' M$ ?: y0 R
- use animal\dog; 5 V/ s4 Y3 _& w
- new dog\Dog();
复制代码 7 z9 L$ i; ]" @
如上,使用了 - p3 Z# w1 v' N+ i( ~
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
( Y& M6 n, n; q: W简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 3 \5 D- C/ Z; D- }( ?# s
+ t3 w( d2 t: a+ i! C
' r; P/ i0 s; x( C
$ I+ Q8 b+ I: x H% p: o2 k
3 T9 {/ x3 T+ X( Z2 n1 ?) K9 T |