|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 9 z" D7 }2 L% o# b4 _" ^
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 " X0 Q/ E2 K0 O# E& D/ k) s
1 a9 t' }" n# q2 T: R
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
: Z7 @+ a0 x7 W- A- }4 W& K据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
$ [. r2 k+ m2 f) |# Y7 t结合使用方法来进一步理解它的使用目的吧。
) r) N0 {* ~. Z, ^: J6 ?, x0 L2 y" `$ ?: N( `
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
' P, k' o8 i4 B - namespace One;
! j1 \3 l( d/ C% X7 A1 z2 \ - namespace ONE;
复制代码
3 q/ U, M, ^3 `; C5 R9 n如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
, r/ k; K( O( y2 F* a t4 Z# {2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 4 H! B3 G: {3 B2 [- p! e2 s1 f: k
- class Person{8 }% E. W0 a$ k+ V
- function __construct(){+ X! M) R9 [! w( Y Y/ V/ V% b; j1 I8 q. c
- echo 'I am one!';
3 X+ @0 P: ~# r; } - }; A; I% j* R1 C2 m2 X9 x
- }
复制代码- //name.php7 j7 c/ m. m6 A7 ^2 g; I: U% x( o
- require_once './1.php';
! r$ k/ [9 n/ M* r
9 y1 y- _$ x! x" K- new Person(); //输出 I am one!;
2 p# n: L* _( u* L# W6 P, ] - new \Person(); //输出 I am one!;
复制代码
; _9 _. p3 S6 j& x3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
/ K( v) Q6 Z6 }, {9 e. S - require_once './1.php';
* A @4 Y# P+ |9 s+ n - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
, r$ H' u c- N% E4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
" n5 M) j: g" d" ^* _$ z$ _2 f- y - namespace one;
& w3 @; B! W, Z - class Person{$ z1 A7 D. Y+ ?+ x
- function __construct(){, `1 U' a0 X) ~; z
- echo 'I am one!';6 _) t/ Y0 N" C
- }2 l$ L' T, p% V: T) D. k
- }
复制代码- //name.php
# L& R* y$ F$ [, s - require_once './1.php';9 s+ d7 s( G8 ~5 @& Z: U9 d
- new \one\Person(); //输出 I am one!;6 Z: R; I( b2 Z( L
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
, Z; ?: c% T, W$ B( O可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 # Z) k$ U) z2 c2 v$ M
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。* B0 V4 J( ` T
- //1.php
& P& G' C& d/ q+ D; } - namespace one;* o2 t6 i" M& z
- class Person{
" d$ n/ f. l G% j. D5 L# X6 y% x - function __construct(){
$ C/ X' Q0 V. ^" P - echo 'I am one!';2 T0 ] m0 E6 m; M x4 _; B
- }* A7 K) q' A" a" G3 s2 C
- }
复制代码- //name.php3 B+ O$ {# _: d" k0 w
- namespace test;5 I/ [5 n, Y1 n/ u# y) w: q% Q
- require './1.php'; ^3 d4 e( R. j" D$ H
- new \one\Person(); //输出 I am one!;* r, R& p9 v2 g( [" N
- new Person(); //这里结果会是什么呢,猜猜看
9 r6 Z6 ]$ F6 _4 m4 B! r - 最后一行结果报错:
8 w+ R, |% B% P0 P - Fatal error: Class 'test\Person' not found
复制代码 0 [/ }6 W" h4 n4 e, J
, g( ^ l3 `3 _% m; G' Z) h1 ?
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
; h: J+ |1 e; d" a" J4 Y结果报错: - Fatal error: Class 'Person' not found
复制代码
# z0 O* n, D8 T# |7 N3 a- ]! `# t! y! X接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
6 N4 i) e# q" u9 {4 F; A2 ? - namespace test;
4 @2 {% L' R# l - require './1.php';
8 h3 Y) G! r( q& X/ G - : {" N# O" T8 L
- class Person{
" D% k1 P) v H( L! R - function __construct(){" ?+ J& I r7 N5 Z) n
- echo 'I am test!';
( X$ J! U4 R6 Q+ D* C5 L# Y - }1 }: \4 ^8 @5 _! }- ]+ L" \ Y- ?
- }
( N5 A# }9 X7 {* K - : \7 G: t9 D9 G3 M
- new \one\Person(); //输出 I am one!;
$ x5 k4 Y( b. b/ [ - new Person(); //这里结果会是什么,自己猜猜看
复制代码 $ s& j) |9 ]+ B- i/ r/ `
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php9 w' s* }% S5 P6 I8 q6 E) x
- namespace test;5 _8 x! ^- c( w$ B) F5 g5 s$ W
- namespace one;* S' B7 W" l6 D: V* G9 k
- class Person{3 Y( c6 T; L7 d2 V. @
- function __construct(){
$ N4 H' K* j, A3 ^% }* |; v. Y - echo 'I am one!';
; N ?8 G/ _5 l9 l5 T6 y% Q - }
- B0 M0 v: N$ s+ o" l - }
3 a7 h) J0 Q1 k0 h
. X" u. J. N8 `# Y4 Z- class Person{
; E3 N, g: q4 v - function __construct(){
. J b' V i# i6 |2 x. Y( l# \ - echo 'I am test!';8 J/ \8 X/ ^7 Q8 p
- }
* I3 c' i5 n" U! T - }
复制代码 0 K5 m" s4 E- j+ I p
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 4 \$ a( G* F3 n! c
看来简单的把require理解为替换,在这里行不通。
7 X4 ^2 s k/ r& H' ]" `6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
( W/ w- Y* F, [9 Q0 k1 ^- i+ O8 [% u( o- //name.php
0 k+ a, y' q- q8 ]
# O% f* R% p8 v- namespace test\person; b7 C( m; j; j" M0 G
3 C; d7 B# ^5 F* g( m, |" [- class Person{
! q) T i# c/ G5 ~ O2 b; C - function __construct(){+ b0 c/ l7 n9 K8 g* r K& C- D6 Y
- echo 'I am test!';
* S, ]4 a) i* a' w' S' n& \, p) q - }& \; G$ p1 O1 s+ j. M. L0 A9 N
- }
, F9 U9 Y+ h7 J8 o0 b8 { - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 ! x) s7 `+ r+ |) ]9 i& a2 |
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 - ~5 o s$ Z) _+ u4 w& o* H! w
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php) B6 Y) C2 _% p5 M* x4 w
- 2 u4 B( Q% T. A9 m2 K
- namespace test;
; m3 Y6 W+ u: w; b - echo 'zhai14';9 E" K& I6 b& o- Q$ ~& m" m
- namespace zhai;
' ?, n6 D* T# x( u - require './1.php';
复制代码
5 O1 A0 P4 |8 Z% Y/ Aphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ~7 L/ q- G: H) }; L
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
E2 i( w) |* P8 q' j- //name.php7 K: O3 f4 M% U
& e( B" o, g% r+ _- namespace animal\dog;
9 F! B, y% S8 u, d/ ?) ^
% [, E2 ~ d( o8 _" }- p- ]! k- class Life{
( y5 C/ {1 x9 r6 B! u3 E - function __construct(){7 @, V, [$ y8 |" u u3 E1 }/ ?6 E
- echo 'dog life!';) v: ]- Q+ K& c
- }
2 A" {- `& |5 }2 o - }7 j! z/ B0 y+ ]: P# {/ Q
- ! o/ }. e; b! A: g8 v
- namespace animal\cat;8 _) v5 b8 K6 q0 G3 A) c4 \0 b
- - N. ^1 C' M t, |
- class Life{0 ^% S9 J7 U9 S6 D1 K
- function __construct(){4 y$ N; a4 P r, ~& s" F( T- O. Y9 ~% U
- echo 'cat life!';. v) x A1 E5 p' i
- }2 d S& k: F9 d" Q
- }3 E& o1 [2 U, ?" ^/ i a: C, Z
- 7 L: }, m/ _' t" k# }) l8 p% p
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间% L7 g v1 n5 h2 |. |4 O7 _6 Q, Y5 c
- new \animal\dog\Life(); //A$ H0 y9 t# x0 ]6 U
: K* \4 [# x. U. F) Q- use animal\dog; //a
; j4 F8 n- z; h) Q: u - new dog\Life(); //B2 ]2 m- `9 z: X0 u
- ) A4 k5 J- W% L- q1 c0 A
- use animal\dog as d; //b
/ c, l+ O* Y. `% R% A; I/ y - new d\Life();
复制代码 9 h' g. M& a2 v5 s+ j
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
% T# ? s6 |$ D通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
& S- }( c) Q$ ?5 b* U相当于 o& h0 [9 {: g! ~( n7 |2 y. X- M
2.namespace后面不建议加类名,但use后可以。% y% c# S% b/ `2 Y
- //name.php
. ~' C' A9 o9 l4 B
7 C/ D5 n5 A" _9 I8 i) f9 t- namespace animal\dog;
% u3 S: E: M; q8 R) h) Z - 1 D( ^! g `, \: f
- class Life{0 z% k( V) @+ l" H! x8 w8 `
- function __construct(){% l: n: k# V4 G' j* [+ b
- echo 'dog life!';
* x- G) E/ T0 y* T - }
! k3 ]$ K# F6 s8 | - }
! b# n* W+ e1 l4 A+ K2 H9 R$ W6 ` m; H
/ w; P4 ^- G# {$ q- namespace animal\cat;
+ `# m- O {3 B8 t0 f! r
; T9 Y" M" B; R- v1 c) h- class Life{
- z# w4 G9 x5 e1 m9 M B9 `/ c z( W - function __construct(){" l9 H( O6 M, ]/ s9 E0 W
- echo 'cat life!';
+ y3 y6 w) R% B6 X2 }: X - }+ {5 [5 K2 E; T$ q0 F5 m- \
- }, w$ ?3 \9 i, G: ]% ^& D% r Y) s8 d. l' g
- 1 X$ N$ y$ K# V2 k7 W0 X! y
- use animal\dog\Life as dog; - L5 o q2 X8 j: w& o
- new dog();
复制代码
1 q7 }) \8 a8 j1 r$ H* C如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
# }* x4 a7 d) S' Y( q* m% E因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php1 ]6 P! A8 s y
, s% d5 x: c# a5 e' m) ?- namespace animal\dog;" t% E) J/ u1 Z# ?
- . O1 D+ S0 R2 I$ X8 v6 B( l
- class Life{
+ c4 Q3 Y" O- G( Z. e - function __construct(){
d/ O7 }9 t. K3 } - echo 'dog life!';2 T/ } S6 T' C8 F# O% b6 |( ~
- } P3 u5 w# Y, j# w
- }2 O) `& W4 O4 F& e
- class Dog{! h9 }% n0 ~( O% P5 d1 j
- function __construct(){
K" F# a5 D* O0 J- f3 y - echo 'dog in dog!';1 W6 v, j% r9 W- ^" J
- }
. {' c( v) k+ k - }
9 q; t7 X L9 m9 | U8 w& U, q - 1 ^6 | ?. h% b7 d& ^1 r2 `. V: l" R
- namespace animal\cat;# K, H6 ?3 a7 p( X% l" X
- 1 f" z9 m% l6 |) E
- // class Dog{
0 j0 c+ B, X$ c" I - // function __construct(){
' ^% E1 w, ~) R( Y" y+ m' l6 B - // echo 'dog in cat!';
8 [ S! r7 |! z! T9 Y - // }
, m+ i- |$ l, ?, B1 Y2 c- v - // }
7 k5 @4 r1 v% `4 A( k - class Life{
* G* {) I3 ?/ }+ |4 O0 l g5 u: T3 i - function __construct(){- W6 W1 T, V' M5 Z& N3 m5 _
- echo 'cat life!';$ q; P4 S, T" X: Z6 M, e
- }
+ g5 x; h" ^5 _* ?' u - }
% i0 i% f6 _' j1 v u
2 d9 |7 @& \8 C% m8 ?% K* S- use animal\dog;
% u$ w) g$ a6 ~ - new dog\Dog();
复制代码
* X' P( Y* U2 m0 b; A) U: R$ W如上,使用了
; \; z Y. p- ^0 Y- N7 |4 ~cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 / e- ^% g8 R: Q( K% O9 F- H( t
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 ( P0 j' z |8 h" C* S' Z
! y& d4 l1 D5 Y& V: D
5 ]( ], O! q6 e# [" [
$ [0 E% ?0 R* V$ l, Q" _
! N6 ?4 x5 `2 q1 Q k8 e( `1 \1 q
|