|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 ( G1 `2 B5 W: g
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
# D# N# A, j4 F0 b4 o' o5 [. r$ P2 \4 r8 l3 C/ O4 o
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
& M( N# G- }, {9 T& |- q& Y9 j据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
5 G- e! \) p8 s2 n( c6 m结合使用方法来进一步理解它的使用目的吧。
% b9 z: b, i' E; [$ w
3 C' ?; P& L8 t' g% rnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
) G- E/ a4 Z1 L, D: c; R - namespace One;
- o1 V2 r" u: C/ F/ U& I& R - namespace ONE;
复制代码 $ i# D8 G0 O. j% n; K4 S
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) " O, m& x4 O! r5 X- |
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
# c' y/ y. j! f5 e) r( R - class Person{
1 n1 D& Z! H" F8 F! t - function __construct(){! U+ E- L3 `$ T9 B7 R. \8 x& I3 h
- echo 'I am one!';
2 ~7 g# t- p/ j2 v$ W - }& g; ], M. m$ p2 B s! ]4 s' {$ _
- }
复制代码- //name.php8 Q, S. \: ]; @
- require_once './1.php';
5 k, O& [# y* R/ Z9 i" N3 N - ; H# x. ^2 F9 w: \
- new Person(); //输出 I am one!;
& M$ N* O. ^) d' @& y - new \Person(); //输出 I am one!;
复制代码
! T. v6 y7 [% l' K5 ]; \5 d' ]3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
. w, k, X! c6 L - require_once './1.php';+ W- j4 ^7 s: @
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
( T: ~2 @, Z$ O& ^6 q; P( W8 ^% K4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
7 o& k. k# a% m, v/ e - namespace one;7 \3 j! z% c& U! ]2 [, m
- class Person{2 W2 W# u' ~2 t, Z1 Y' w
- function __construct(){
' a4 e, E$ ?+ B( D - echo 'I am one!';% {' @ Q. Q" G- [; J+ k: |
- }
1 _1 M: ~0 w$ r- {$ q7 v - }
复制代码- //name.php0 {, Y& I; E- O" h% C* z
- require_once './1.php';
# f7 F6 h! |0 H9 W' a: T - new \one\Person(); //输出 I am one!;! l! A. w& j: f* N& a) n
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
4 e' m( E8 Q: p* _! p) ~可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
9 z3 p. v! i+ _* z6 l! E0 R5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。1 c/ C& h0 ]5 f
- //1.php
# T) @% H1 ~8 y- O8 K - namespace one;
* v3 _2 @5 [& ^: }( }5 f - class Person{% U. }- F. s, s: W* c* ^* X4 [( ?
- function __construct(){
/ B+ \0 W# z& Z - echo 'I am one!';
# R0 o- c% w; a- V2 Y9 \ - }& ~0 M: m( P/ w" Y* ^4 h8 r" ^# |
- }
复制代码- //name.php) u% h n4 q) g2 ^' h
- namespace test;' L0 _' Y; b3 s, f [$ q
- require './1.php';
5 |0 l8 o9 B% A - new \one\Person(); //输出 I am one!;6 @0 C4 R; B: m: H2 p
- new Person(); //这里结果会是什么呢,猜猜看
/ b9 m8 ^1 P/ A' O/ J \ - 最后一行结果报错:* `$ k( {9 ^0 m' D
- Fatal error: Class 'test\Person' not found
复制代码 3 A3 l- [) p9 K) k! W4 U i
( l. _6 _1 S, c% f
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
. Y5 ?2 }2 T* A" a4 G( n结果报错: - Fatal error: Class 'Person' not found
复制代码
' I9 h4 S) V2 r/ Z! l接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
" S- ~! }$ a; U! X - namespace test;
6 a5 M! j8 @- F - require './1.php'; 7 Z' ^' g4 e, z) F1 _; p1 m
# I) L0 Z# i6 a0 E& u8 ] q- class Person{" |: k9 g, c: O; H
- function __construct(){( w% w* _% S- D+ f; m" O
- echo 'I am test!';5 a8 }0 s# b3 |4 M
- }
' W" n: b2 U8 R+ ~, x - }. ^0 S: M3 h7 C( V, i* v( g3 |% H) J& k
5 F+ o: ]5 V9 c$ l& j0 p- new \one\Person(); //输出 I am one!;
$ c% ~1 j1 s6 P - new Person(); //这里结果会是什么,自己猜猜看
复制代码 2 K) q! h! a# V- ^3 J% \* S5 Q
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php. c% y# G" a/ b4 e% k
- namespace test;) o" k7 g) p: ]
- namespace one;
" Y s4 Q. W) J }0 ~ - class Person{
* X7 e% J( }1 u( T- E3 m ^ - function __construct(){
& J- C: I( F1 [2 w- }3 w. U - echo 'I am one!';
# @! G- \6 {' _* j - }
8 G% {, _/ E d; T - }
k C0 H6 A/ c8 g4 e) H9 H3 L/ G
# i8 I# P& o5 j/ }) E, M4 k4 s( P- class Person{+ [$ k1 s/ \% Z3 q
- function __construct(){
2 b7 @+ i U6 W' Z. i# J - echo 'I am test!';
; ^4 g! G, t" ~- ^6 M4 r - }
4 D2 Y6 ?. |9 R e' z4 W0 K - }
复制代码
, I/ d3 n E7 E! k无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
0 m$ j/ W% B( Z2 P% r看来简单的把require理解为替换,在这里行不通。 ' i6 K! a% g2 p9 @
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。% H* { N6 `& X |
- //name.php
1 k/ p# z" v% E: O0 X8 w - 8 g0 K9 d0 {( C1 V
- namespace test\person;
% S. z9 F: a9 I9 \7 c& c - % M" v1 U' P' _- p1 J% U
- class Person{ m& X& J6 f/ J+ L x
- function __construct(){3 o d% ]1 O% i8 ^( c0 e
- echo 'I am test!';6 {: B! ~+ j! D" {9 _" K8 r t; K. h
- }% V# ]9 y0 w2 G- V7 l
- }* y9 T f1 M, ]5 X, v1 t0 D- ^3 K
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
4 S m& z; Q6 F& c不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 ; P2 p$ T$ o* O- n
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php. d2 f2 L$ r1 V [; x& H" C" I
8 V9 B9 W9 m3 q. {& y. v- namespace test;/ G4 N) P6 x5 y6 t, }4 h6 G
- echo 'zhai14';
: ]7 K9 d; Q/ z4 ?) L# X. g - namespace zhai;( U; B e: P' }- G6 W; o
- require './1.php';
复制代码 ) M; W1 g: V2 J8 @9 `
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 3 t2 m( o- H& E: S
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。: Z! m U1 r7 Y
- //name.php, C- T: o [ [
- 2 C; S- B& I/ q; ?
- namespace animal\dog;
: O& K/ R' z3 T3 B* C
6 L# c6 t, \% k9 \+ O- class Life{
$ l8 S; l S. ]/ O - function __construct(){
& a7 Y9 A. T( n7 W' {$ n - echo 'dog life!';0 }7 n# P0 G" j$ S
- }
0 z5 ~% ]: O* | - }
. k; }* O# A8 g8 G# W) @+ ^& x
" B- T4 {" N" Q, ] U- namespace animal\cat;( O& H' k1 U% n ~6 @0 z
- & Q6 D3 a1 H$ H) ]) ]
- class Life{3 q9 a' L7 n- q, S L q w
- function __construct(){6 _( Q9 `6 Z- c" U8 J$ j
- echo 'cat life!';
. l# p+ `2 o2 ^/ d4 l/ A - }
4 x% N) g6 F& F+ a) ` - }
) z5 D Z G( `, X4 A% Z% F
5 g* f8 k$ A3 ^( i; ?- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
* I3 ] A8 o. @' C - new \animal\dog\Life(); //A+ I' s; d0 v+ b9 W7 a s; j5 R+ Q
- + v( v. ^( K$ M! P
- use animal\dog; //a+ W" {; @/ ^: r% X
- new dog\Life(); //B
6 H( t+ S( F0 R& C - i, j6 m* h9 u5 G* G* U
- use animal\dog as d; //b
) T2 \4 H5 i+ ? - new d\Life();
复制代码 / v. ^5 Q) |. o
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
0 I+ g& ?: |# ~; M2 k通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
% x& O8 ]; B' j4 f, r: V相当于 + l M+ D! V& {. T* M1 S
2.namespace后面不建议加类名,但use后可以。
: C2 O1 Z" @1 i" ~( d! H1 V( _- //name.php6 B1 h0 T: \( u/ \7 l- ?( i5 X: e
- # a. k a' Q4 l; U
- namespace animal\dog;( E" i! E& |: m" O
4 S! T; a% y7 [& r# Y- class Life{* ~$ @, S8 |" p, v% q
- function __construct(){2 D5 e: D5 f+ ^0 I
- echo 'dog life!';
" p) r; A2 H6 v8 v" d' G H# T - }# ?# r' c+ M( r) H) i( a+ [
- }
% x+ e# J6 q1 z
( a. {) U6 w- J( G& x- namespace animal\cat;. w8 @, b: d# R
. q- |3 ^' p$ d- class Life{
) w. F( i+ F! W: r5 b; e. Y, R - function __construct(){
# N# B7 N0 D8 g5 ]2 T7 F - echo 'cat life!';
/ B( j3 V& O8 T - }9 J% a3 M1 e& b9 W. O
- }, j9 E- F3 m' |! _
6 C6 L# o# J1 H, t+ v5 Q- use animal\dog\Life as dog;
! W7 P# ^( m1 ~& W. v - new dog();
复制代码 ! l" m7 c( b2 O# r; B- o) m! B
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
. q4 }; N9 m& \+ O+ e因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php' y$ K* ^( x( C4 L! W3 C, @
- 4 T( [+ s. A3 s$ {. q* M+ ]
- namespace animal\dog;
7 y; m) W9 i4 ~- Q
7 d/ w" z; {7 \) S8 s$ w& ~7 O! `$ B- class Life{
$ v) ~: y5 V$ I - function __construct(){6 P( a1 q3 w) L2 R
- echo 'dog life!';
# U& ~" ~2 q; l! r - }% s% a: v8 Z/ f J( q* A- N. G
- }: c" z; Z e* D& Y1 a
- class Dog{
& @0 H2 p' u! h" V3 w - function __construct(){
9 E" Q! e" g0 B$ d1 Y% g3 A - echo 'dog in dog!';
% N4 [1 t1 m" |8 `) ?$ F; g! q - }
" B/ `; p! S' U- H - }* x! Y1 u- F2 W2 I
# R9 ^5 x) @2 D/ v0 W/ l- o- namespace animal\cat;
: d/ z& x: M7 y4 C0 G' ~, w% g- B! @ - ) T, x$ A2 C% x0 d l" f
- // class Dog{* j3 Y' P# j, A5 O8 O
- // function __construct(){. N0 h5 r5 l" Q R9 A$ L
- // echo 'dog in cat!';. x8 \# L+ Y7 M& W5 b$ Q
- // }( ] [ N1 I- Q5 n' ^1 B
- // }" V+ z) P, L8 @9 F) Q! F% \$ u
- class Life{; h5 e' Y' c0 E& ?( a
- function __construct(){
$ }$ k& Q0 f- u# U, u - echo 'cat life!';( d7 @4 d1 K( n1 h4 H5 \
- }7 _0 Z6 e" n" ~" ~4 I, C8 T
- }+ H* m, M( u6 T" N
; [; U! j. l4 o2 o5 Y- use animal\dog;
7 w. D/ u1 Q T: \5 ` - new dog\Dog();
复制代码 M& k W# [0 D. a! q
如上,使用了 + y! ^1 u* e9 E. M/ _/ e8 L
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
0 d3 T o: V3 h简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
* \2 K; t6 K$ y9 l4 i
& J0 V+ X m! v
! G& ~, b C, W2 Y& Q7 Y. D/ R/ V+ y
8 m" t) t0 _. X S
1 l0 x# }$ ~$ L- I% V1 y |