以下皆为本人自我理解内容,如有失误之处,请多多包涵。 - W- ?. Q! s. H6 x) L; S/ W
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 0 w) ] m4 d, L+ e6 g7 G# P* I' z
2 c' }) }5 n4 k6 Y- p3 B, t8 ~
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
) ]" {' M& z' F) `! K据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
) l: S- @2 z0 h' l1 \结合使用方法来进一步理解它的使用目的吧。
* B! X% o. s+ `- N6 K) `3 l: @: m+ Q6 p) u7 i
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;( B- \7 K ^: ?# y
- namespace One;
2 {( X/ u9 W8 x: ], L% T - namespace ONE;
复制代码
% L& ]/ m+ a1 Q# V如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) $ s4 I2 _& t! @1 F, O
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php : n7 T- A% V. w; J @
- class Person{' D: H& b& N1 S
- function __construct(){+ T6 g/ z/ B6 R3 e; r4 _+ A5 n
- echo 'I am one!';
5 Y9 C( R* ]* B7 R) N - }
3 X" ^* M8 w; ]4 _" ? - }
复制代码- //name.php8 |3 ?& O j+ @. h, J+ h
- require_once './1.php';
3 G% T! }, \2 u0 r+ h - $ k1 X) P E' U2 z0 [
- new Person(); //输出 I am one!;; Q. D3 }' ?$ j& B: C% x& @
- new \Person(); //输出 I am one!;
复制代码
* ^, U: X6 C% X# V9 q6 _( }3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
/ `( r$ r3 N( S3 S - require_once './1.php';) V9 k7 t- u+ ~8 ~
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 8 ^: D+ M% a0 v2 t E
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
5 T! a$ m5 o% l6 a% C6 T - namespace one;" w' |9 }6 Q/ \6 w* T' d
- class Person{, t% z& Z o* ~( S, v
- function __construct(){
' `' Q, [8 t8 n% u y' i7 K P* ^ - echo 'I am one!';- B4 U1 T& \9 C% P. \
- }
/ Y% h7 m. B: `5 {/ A" Z - }
复制代码- //name.php+ F2 w. A9 v2 r, y! W" _
- require_once './1.php';
k, f0 Q; J) K2 R5 @) V - new \one\Person(); //输出 I am one!;5 [- }' v3 y$ i: t5 m
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ! u) O+ d5 G z8 Y# _. l5 G
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
' ^8 X* S- a. ~& _% Q$ O" v+ W5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
8 D D K b3 T( g% ~) U+ j- //1.php
! g6 j; p* B1 D0 f, T0 J! @ - namespace one;
. H3 U; j: X. A$ X: W. a/ | - class Person{
9 U: P& S* C0 j9 ^6 \ - function __construct(){5 a% }& O0 E+ M$ e8 {
- echo 'I am one!';
- P" Z* ~& A3 v1 N ?6 y- s6 a8 r - }) V% X. }+ @) b. }) N+ i/ I3 y
- }
复制代码- //name.php
5 |& g3 p8 W" B& ^% `: ~* @ - namespace test;
4 ~6 ~2 L2 G# [3 i( X0 R( v - require './1.php';
3 P+ l! }1 ]: ^! ]& W - new \one\Person(); //输出 I am one!;; M) _& x/ r: c* j% a
- new Person(); //这里结果会是什么呢,猜猜看
5 }- F+ k! b7 ]; V" U$ [4 { - 最后一行结果报错:
+ Y+ X& v7 h/ [/ j. B& Q' q2 b - Fatal error: Class 'test\Person' not found
复制代码
3 x( P# v) z: |( H b' G
6 {3 A$ B7 I. M首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 ) v p9 M0 R/ }
结果报错: - Fatal error: Class 'Person' not found
复制代码
7 ]3 N. X7 c' F6 |/ R接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
1 ?7 w4 ^ J& B# s& _ - namespace test;9 X$ C% B" ]( K2 V, D
- require './1.php';
7 d/ u7 F, f* E8 x' D
' z6 F' }- i$ A9 [/ E% m) P- class Person{# Y i% r. ~; e
- function __construct(){. y2 Z. I5 M+ I b$ B1 [9 y
- echo 'I am test!';
$ \% }- c/ C8 E; G - }- Y$ \7 E1 H# k$ }6 s
- }& U1 g/ D3 _; J6 F
7 f; T/ Q, h" D3 I7 a$ u- new \one\Person(); //输出 I am one!;* f, l1 L# ?( E0 C& }3 E' M" ^
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
. C. h+ i( ?/ a/ E1 \2 Y最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php% ~5 s- S$ i1 d3 z7 k" R- U
- namespace test;
+ O# P# B* o0 d. |4 I! d8 K3 x - namespace one;
# o" \8 k6 {8 v0 _2 v - class Person{
# M- L) \ z' z- s+ G8 V+ w - function __construct(){
5 d+ ~+ M( Y2 o+ u4 C0 c - echo 'I am one!';
0 {9 ?4 ?$ D/ U) R. J; ^6 E7 l3 z1 I/ X - }8 x# Z2 J# ?2 |& f
- }* J- M8 z- ]4 @9 ~1 Q
- 6 S+ O& `# Y; a' z+ n
- class Person{8 S0 W# v7 d u' K" ]
- function __construct(){
1 n& U* k3 I. @7 ~/ j - echo 'I am test!';
9 c/ D0 u- `, y& v$ `% ~ - }
; S6 z- u9 Z: T( {& g b/ z9 D - }
复制代码
" s: r" |8 m6 `/ w" {无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
. T! ~% M0 i4 q3 [# ^看来简单的把require理解为替换,在这里行不通。
1 j" D' c: d1 s9 Z* ~) P% F6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
) s9 k0 s! s3 j9 q$ J6 i- //name.php
9 U. G X% t- t1 o+ @( I. L - $ H8 A0 Z' j. t# o5 ?( Y
- namespace test\person;
( \: Z) m S( U/ p
+ y/ u9 J0 @ d' K; E* a- class Person{; g4 l2 ?2 W, m; P4 z/ S
- function __construct(){* [: L2 t z0 _" M3 c* h; {
- echo 'I am test!';
, F9 C6 A6 q6 l' I& k - }5 V$ n1 S* Z/ C9 S% W
- }1 M X4 q7 j( A5 G& Z0 R2 ^. p
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 - L9 p( F% z* K
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
( ^8 T' r3 B3 a8 A$ B7 r$ r7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php' j$ n1 z7 u9 P+ ^- ~9 n
F3 j- k( a9 S! `1 @& x- namespace test;
: m c' d* S8 J3 g) D - echo 'zhai14';
( W y+ S0 b; U8 y. J - namespace zhai;
[ [4 s. p. y$ ?3 X( l1 y5 m - require './1.php';
复制代码 * ~0 ?' `$ O+ A5 B
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
; F) K1 q9 Z2 `/ F: M; [use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。& w0 X& z5 j0 o0 M' k& N
- //name.php0 W% H0 Z! C. p/ R- W& r6 [
- ; Y! L3 a6 _5 g& h, R; f% ^: D
- namespace animal\dog;! \& ` b" X" T! V: {
d( \3 H. _1 f- class Life{) C6 i0 l2 O5 |) M
- function __construct(){
8 y+ F8 J. @( _2 @4 q6 w - echo 'dog life!';
+ f" h8 V8 h: a. O& u - }' Y" N$ x) i* C
- }- w* J+ a1 g8 A
- ) a7 L: H9 J0 ^4 z- R
- namespace animal\cat;
0 V. w- t, u- U/ E: S: _% {1 i" e+ ^7 G
I- g. J1 O8 y! f# j- class Life{7 l' U: ~: u7 x% t
- function __construct(){
9 V( _# \ T; Z8 Q- g - echo 'cat life!';/ e! E" {; N' _9 p
- }
9 I3 ]4 X: O0 y0 n8 F0 n Z - }
+ g5 O6 G0 Z% D w( s5 r - 0 [' }; h k, f: R2 c
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间3 \4 i6 y* o- h( N9 O+ \0 o( B
- new \animal\dog\Life(); //A
( m5 ?0 ?1 p, U# L6 Z/ C/ O
( P, \2 S# s! j5 q4 y5 @- use animal\dog; //a3 k; q" {2 |9 L3 ]# K. I: J( G
- new dog\Life(); //B
5 t) N! P! C6 ~; b( _
8 M' b3 P; {' n" s; w8 W! r/ K- use animal\dog as d; //b
. q6 F& \! j( U+ H9 A5 Y% j- ` - new d\Life();
复制代码 9 \5 H# X! ?, v
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 : n* V# v' }/ `) p3 D, B
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
5 @) N M' x/ ]4 A+ V相当于
# y# v" Y9 v U2.namespace后面不建议加类名,但use后可以。! ^# [$ F4 A8 L/ B4 a; J
- //name.php( B. U7 R) L9 v- }* t
- ' W' p7 s6 l, _# G
- namespace animal\dog;4 x7 h' N0 f' L1 _( Z- K8 G
) t: r" n. V! \( c- class Life{( v( r w6 a: x8 v/ O- C
- function __construct(){
# n* `; C& D2 E6 w/ R - echo 'dog life!';
. [8 `7 T( }6 f$ H5 P) o - }# A; r* _: V& e- x: D
- }5 B! \) M6 L- S7 I: Y9 h
1 Q D/ B* l- J* b) g" }. ~- namespace animal\cat;5 X* t, y. W6 s! B8 T" \
8 ]* Y* @% r0 Z2 U5 M- class Life{6 G$ k2 h P3 x" v. d
- function __construct(){
$ J+ X) l) d3 N. A4 R - echo 'cat life!';4 ~* K7 C$ h9 X7 s4 w
- }
: R7 S q) z- t d7 V( ~0 E* p0 P - }
! H3 h9 \' x- p4 Q0 k' A$ N+ i# ]) j8 a" j - & D$ G2 a1 D8 {( \: s
- use animal\dog\Life as dog; $ C& A$ G9 j3 ~3 q& D
- new dog();
复制代码 9 Z1 S$ S8 d, Q" Z
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
' z* A6 P7 ]. h/ p4 u. o) P因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
; ?: @8 p8 x( L) ? - & ^7 ]: I3 S" i+ A, i
- namespace animal\dog;: o$ p- y- N' @8 I+ m& |
- # U! W0 T$ E0 O4 B
- class Life{* J. V+ H' ~. T4 x7 ~; `, E, e, Q
- function __construct(){" m1 G, _8 Q# y `
- echo 'dog life!';
6 ]/ v3 [+ ^% N - }
% d! ^7 k% ?: \# T; y( F, x - }
3 L2 K T$ B3 e1 }: V. X - class Dog{
; q# h2 q L( q" E - function __construct(){' L v0 m3 N* u& e% ?5 O9 i
- echo 'dog in dog!'; Z% e1 C$ |: V
- }8 M7 H; e3 j1 P
- }4 E# ~ A; i% Y& C
* g0 O1 P7 O& M# X; n7 v- namespace animal\cat;8 F6 ]* n, h' k
$ J; u1 v9 s0 p, i& \, g9 B" j- // class Dog{/ B: h! |: X( m' r. h
- // function __construct(){% E% R3 {: h! J: A5 G4 M
- // echo 'dog in cat!';
6 e7 O |, l5 t1 T" m1 O+ @ - // }) k. S6 `! B" v
- // }$ N) `' ^2 L3 y
- class Life{
( c- E+ P. N- a. v: [, ? - function __construct(){
1 F7 P9 w8 i5 A2 W8 M: k/ q; s3 W9 F - echo 'cat life!';
) u' T' f$ y; |' g) b7 m - }
$ w8 [; h$ U* Z4 y b2 O# U1 s# w - }) y7 [3 E+ r a1 S
' c$ A# {+ `; r" ~* ]- use animal\dog;
. s" |: ~5 D- |, ^) g3 o - new dog\Dog();
复制代码
5 ]+ G2 U" _0 M. W2 c# k如上,使用了 , b9 W* R6 J# x
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 2 a3 h1 p! d& S- W
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
) [: i* `- c4 C7 F9 ^' [; `" C1 M$ K( |6 d
* f/ y4 E; f E& z) e% q
4 C. ~5 I1 s7 l! b/ ?1 A
: v# m: c4 C, N& X3 }( q% p
|