|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 / K% p1 j! L) s: E) [
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 ) I! \' T+ v" c# O' z: Q3 g1 L
. Q* t) Y9 F& t$ f' Q- U5 @9 s& H
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 8 q: ]* S! Q' x* r& C& v. m0 M
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
: z0 R( Z+ E G/ S% D- F6 O结合使用方法来进一步理解它的使用目的吧。 5 q1 B. _ t: s. U
' U5 `0 Y+ x1 y, a1 W }namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;) c o7 {* a# M! q9 c8 d
- namespace One;1 E7 s' i' @; e! M% T7 ~" m7 w+ M8 L
- namespace ONE;
复制代码
. U! Y) @7 b7 F: n- @如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
% E# |: v+ V* E) ~% O# i9 ^) Z2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
* z) U7 I3 B& E0 _* \. y0 N - class Person{4 N/ Z2 F s# p* K; {' Y
- function __construct(){4 }. L' S! m5 J+ t; l" J
- echo 'I am one!';
8 G5 G8 h% m, T- }4 ]) Z4 w - }
' w0 V4 ] z T- W - }
复制代码- //name.php( m# D2 v3 i& K7 _2 y
- require_once './1.php';9 B* @) Y# a9 z/ U, ^
8 K% P5 j( d+ @# {- new Person(); //输出 I am one!;: d2 G* D4 Z- r0 w8 J# Q
- new \Person(); //输出 I am one!;
复制代码 $ n9 \0 ^( |. D4 p! B& y' G' m
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php, x1 \% j- j- r( L
- require_once './1.php';
8 V) f$ Y* j/ T; b# f* j& Y+ r - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
' A6 e% l# U% ^* ^- `4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
" r+ c- t3 _0 d - namespace one;
9 [( q' x" O ~- _! M - class Person{
" K: |( t& q3 T% k) S0 K3 C( t - function __construct(){/ g4 m( H/ p9 d1 z' Q
- echo 'I am one!';
1 U- Z- `3 |- O7 p& ? - }
7 v! |0 e* _% Q$ K7 h1 O - }
复制代码- //name.php
, r' k; K* l/ ` - require_once './1.php';
/ x6 J0 h, T& y9 I% d - new \one\Person(); //输出 I am one!;! G- R8 U; R9 @5 a0 y& ^: L
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 6 a: O, E2 W+ R; z
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 - J& N5 Z- t: _2 [5 v$ G$ w; k
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。1 o5 j( v( H- X9 `" y
- //1.php 5 U P3 M2 l& f) ~( N7 k: \
- namespace one;
- l0 B" q- @& W/ o' H( f+ { - class Person{
" h8 a% S s2 U6 {2 a d8 { - function __construct(){
! ^/ ]: J$ V F& p4 E - echo 'I am one!';% b; E0 J8 k4 P' N- G, x
- }1 _" i9 K, L+ m4 D; p! E4 t
- }
复制代码- //name.php3 i& d$ R/ n4 E; U
- namespace test;7 d7 G" _& {7 h3 k1 x, I8 I1 ?
- require './1.php';
2 x) r1 I& Z( f - new \one\Person(); //输出 I am one!;$ k6 }" I$ b& N |
- new Person(); //这里结果会是什么呢,猜猜看4 O* p2 i! G' E/ {' h% i# k
- 最后一行结果报错:
! Q$ `, A$ m$ d; | p0 f - Fatal error: Class 'test\Person' not found
复制代码
- g4 M5 @( j7 F1 x8 |) A |8 Y5 q% D' m( @- P) K+ h
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 8 c2 J' }! i4 L& q3 Y7 [: U
结果报错: - Fatal error: Class 'Person' not found
复制代码 2 y' p3 ~4 l6 U; B
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
& b7 n; \( j2 B9 k - namespace test;0 j: p2 W; O2 m3 X: z! }6 o
- require './1.php'; ( t# F- r& c* t) V/ \2 x" P
- , C3 _ c: y8 n+ V: \: E
- class Person{
9 X/ {' e1 b( p$ p5 [ - function __construct(){
" B* Z9 a9 O, k8 o2 I9 ^ - echo 'I am test!';; k# y3 O# t5 s+ ~- x9 o' a
- }9 C; \% I) q6 _4 X+ h- B; v6 L4 b' M
- }- | H9 ~* ~* g0 _' W
! l, L3 n4 }2 T7 A$ i- new \one\Person(); //输出 I am one!;- g# r& U# S6 N5 \: B/ U- i
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
0 z& O8 h% \; {: r7 j' g7 Q最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
- Q0 {/ C* @" u2 X4 R8 ~1 ~ - namespace test;5 \/ e, r9 \* t
- namespace one;3 |- X0 G' f% B# F" R
- class Person{7 p" O& T; W1 y x+ |/ C
- function __construct(){
% Y# s+ I6 [0 N8 H0 ? - echo 'I am one!';
: Q q4 L( |8 n L p - }
1 W8 L1 b' `1 J* R1 M+ w2 \ - }
. c( g: ^( ]' V3 W9 c - 9 H! b. l; }9 X* C9 A
- class Person{
) A8 t- C: I. i0 C - function __construct(){
% t( ]" }! L+ V: b' t% K3 X% K4 n - echo 'I am test!';
6 G$ U f6 M7 [$ D* _0 c - }! }. v- U( _! f: d
- }
复制代码
: |5 ^7 Z) y3 Y: i无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 8 m! R: f/ J. z8 p$ l: ?
看来简单的把require理解为替换,在这里行不通。
* `% a( d, F8 ^- Y* F" A K; T6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
0 n2 L* z5 n3 ?$ @( Y0 z( u/ _- b7 t! ?- //name.php
6 B9 f4 a( y" O3 A7 U" J2 H! [
9 P8 R+ f1 a# g7 P+ p- namespace test\person;, Z4 f+ L3 V$ @) t0 c$ r; [
- & s) V: X: B1 J& u' e! \3 [
- class Person{
9 Z8 V' n' `- h% Y- g0 `" m( C% A A - function __construct(){
% R) b0 {. i+ J; n9 U7 s3 l9 { - echo 'I am test!';
( i% ~8 Q! w. g# X7 ` - }
: P3 o; k4 l9 Y - }
% S* ^6 p% z0 k% C6 n* E+ r) }( @ - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
?+ l, @3 u$ m4 l, \不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
9 Y4 ^: f e3 X4 F7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
3 B5 C5 `! n) _7 W: Y" e - 0 V; s1 v% Q, \! B: E' w
- namespace test;3 A3 A6 _* n: |' v
- echo 'zhai14';3 l. H: E7 a: }1 t! }7 J: T5 g/ |
- namespace zhai;/ ?! z+ x7 n# J6 R- q
- require './1.php';
复制代码
6 N' X1 k/ f A* s: R* m" g* Rphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
, I' }( f; l3 t/ P& j% Y0 [use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。 X5 ^* C- v1 _7 \$ G
- //name.php
* Q" Q$ W# I5 O7 m0 x( g8 ` - 8 J( s3 s' O" R
- namespace animal\dog;2 m, @' {4 k" a; j: [+ Z
6 w# `9 `7 d) v/ r& V% c% G: ^; h- class Life{7 `6 [ v: L3 `! |- G9 P" ^) l
- function __construct(){$ c# j: L/ y# f
- echo 'dog life!';" O( R/ |- a# T6 T
- }$ R% e$ S$ i8 Q. U& m
- }
: e# a+ Q+ ~" v, C6 }
! J. g2 h8 Z. A) J" t- namespace animal\cat;
% Z' F/ D& u5 ~* Y% W Q - & o4 ~7 c& o+ h/ _- ~' E
- class Life{4 I6 z6 H5 U9 O, i3 Q5 f3 h! E
- function __construct(){# F5 w+ x. @9 d# r4 z8 b) g
- echo 'cat life!';
3 s! t0 d6 e$ F0 p" v - }
2 g# t7 t! T$ N, ^ - }# W/ {5 ^- f. f0 k" v: m; s% j
- 4 X1 z. n# N: t* K1 r( h2 U
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
/ Q: Q1 ?( }9 y( ? K8 I. ~ - new \animal\dog\Life(); //A
7 N& f" l* b9 X/ q# C - 9 O; r. k" X* \
- use animal\dog; //a" Y. h n* |+ w! x b5 l
- new dog\Life(); //B
$ S S8 q7 w8 K. E* U4 w: G - ( V8 W. O0 B, j# s+ O5 G
- use animal\dog as d; //b8 e' W& O6 \; H5 b9 E- Y
- new d\Life();
复制代码 8 b* l' [1 M6 J0 ^" @$ G, R
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 7 D6 L, x" m: A1 O% v+ _
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
2 d. [* e N* W. [: i4 G) N* Q相当于
# c* ^' D+ p% k6 b8 C2.namespace后面不建议加类名,但use后可以。6 b) _+ H5 ~- j3 J; U
- //name.php
( L/ y8 U q* M& ]0 y
* q2 y) d. o( ^0 w; P- namespace animal\dog;
9 C+ `0 w) z* \- p1 i+ Z: X+ ]
+ l5 Y% s( p7 f0 P0 n- class Life{4 F) d* v1 q8 T5 B
- function __construct(){) u, u, y$ \" i8 N
- echo 'dog life!';
2 ^3 M0 b! _. z& x8 }$ F! I7 ]6 N - }1 a4 f: f$ E2 s3 C- q
- }6 c; l( o( k9 r
- 8 I; e3 E) c5 n" M) O" ~; o% r$ D
- namespace animal\cat;
% |% t0 B7 ^9 C - ' A8 X) H" p2 d1 E/ a
- class Life{/ R: ]7 }, E+ P
- function __construct(){
7 v4 H' [0 C+ X' p1 m* U. P+ r - echo 'cat life!';5 A$ \: }8 \: B
- }
8 y* a, b) e3 O* T - }
- D7 R6 j! S/ U! k - * V/ e5 K2 s: _6 ~; R/ r
- use animal\dog\Life as dog; . o0 I2 q t m( @' D
- new dog();
复制代码
0 a3 W% M5 B5 |& n0 F8 S @( z如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
% K+ N5 @1 x, T6 P& A因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
9 g. U$ p$ V* b) [4 V
4 {0 a2 ~7 s) k! h/ v& G/ b+ n- namespace animal\dog;; N- u9 ~" P" i3 Z3 W
2 d1 k+ V" I3 M v8 S- class Life{
7 R# n3 Z; m; x8 E W) D6 E5 r9 @ - function __construct(){' I; J9 n) s3 ~$ E* t4 |
- echo 'dog life!';0 l' _% ~1 H# o f& ?4 H1 @
- }0 m$ q' i; k5 w q: R+ S7 ~8 z
- }% D! h1 T9 m8 v8 V: j5 g' r/ _/ |/ Y# `; @
- class Dog{9 R. Q; X9 B! R+ s7 N
- function __construct(){# ^( W& ^) ?2 y+ `5 b; b
- echo 'dog in dog!';; {$ c# {# |0 p' b
- }
! t: s4 n# h; @3 f - }
4 e% |, o; s; V - 7 {+ M/ b& h0 o0 v# M
- namespace animal\cat;
, q S9 ~9 t) U. `
4 I; f' A* B! r- // class Dog{
- c6 a1 o' q# _4 Q" |" I6 ^ - // function __construct(){
# @0 G5 |! |9 n( i- z - // echo 'dog in cat!';
2 S, R- @1 Z8 x. B4 D. v- E - // }+ C+ P: r1 J, A5 [% e. o3 }
- // }
" i! a( r7 h' ]# x5 O - class Life{
" q" N! }# J! `7 f' U - function __construct(){' e( Y) z- L, y3 M3 f o
- echo 'cat life!';
4 A0 k0 [3 Z: i9 X: l# H6 a- w - }
\- W% U2 r/ h/ a) @ - }
" v9 `6 ?; A- v - ( ~ ]8 x7 f' `% u; n
- use animal\dog;
* x0 B4 b9 g/ u* ]* J6 U% _ - new dog\Dog();
复制代码 3 {! a) m: u0 x6 w
如上,使用了
) U* k# z7 U# Acat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
) O; d# \" L: o4 W: t1 [, i1 ?' f简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
3 O& k/ [* Q8 ~1 i8 c- A( q1 K
' h" e4 |! @( Q( ^/ Y% g
4 w; `7 S g. w0 d$ Y0 [
* f# a" [5 x4 q" W2 N& c
$ n. e4 h* N- v1 ~2 ? |