|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 I1 X( u4 f3 G+ l
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
4 h& @, f3 {" ~2 V: o: @3 z. `% h/ e7 L+ {+ ?3 ?2 y' c7 x& d8 R% n
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
7 S1 H& w6 `3 U) T据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
+ _% |6 ]! u$ D* s) D3 B9 |+ Z. a结合使用方法来进一步理解它的使用目的吧。 . r* d" R. D, d) a) x
4 Q* u( }: E3 V/ D6 Cnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
& g# [+ w! L' ~ - namespace One;; {6 Z( J) n' B0 H7 z
- namespace ONE;
复制代码
$ u8 R) \$ h# }- N如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
, l, @; N* D* Q; k! d9 X2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
G$ z3 k9 l; `$ Y& h1 W/ f f - class Person{) M' E% T {2 b& z* [
- function __construct(){
% ~ Y- k- T0 Z0 E/ ^ D - echo 'I am one!';) n& J% F2 A% n( ~" L$ p$ U! K
- }' ~/ d! _1 Q/ I5 W" A) w
- }
复制代码- //name.php [- b5 Y H' v& H9 v8 M: t3 A
- require_once './1.php';. s# Y' s- w3 N" `
- 3 [7 k2 @6 U A: r2 ~
- new Person(); //输出 I am one!;" m9 z9 i8 o, F/ @0 F4 e
- new \Person(); //输出 I am one!;
复制代码
. |& e2 p' I2 g8 d3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
Z$ _. x8 `4 \3 w- I - require_once './1.php';
! G% ?( S* \+ n1 e! C& N - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 / a0 E0 S. b2 ^, X# ?
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
, e G* N6 X% }1 G - namespace one;+ V3 i9 t; Y, f* j5 I8 B S
- class Person{. s$ g8 x( ^ {3 H5 ~9 d# K: q
- function __construct(){" R I! u" E5 J& O, ?5 \( {
- echo 'I am one!';3 _& M5 [$ Y. i% H% w8 Y2 r- {
- }5 P: _. z2 I+ P5 I" e' P5 E, n
- }
复制代码- //name.php
5 R2 m% R# e ~ - require_once './1.php';
) r9 _( C- M( s- Q8 o - new \one\Person(); //输出 I am one!;
% c2 O% Q! v/ P& B x; D \ - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 # T9 X5 J- c. J8 N# F
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 1 S3 X8 [2 X& p1 k3 r: t
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。# Z. X7 E4 q$ U; a. M: \
- //1.php 8 ?9 t& b7 J n, |$ W9 D. l
- namespace one;
6 S2 N7 _$ X1 n0 G - class Person{4 D7 w9 [: J7 u0 v
- function __construct(){" m- c: h% G* c. P! [" b5 J
- echo 'I am one!';, Q7 S' D- D* B O. l: K8 I
- }
/ m% Q6 j6 v) d4 K - }
复制代码- //name.php
: [) m1 v) z* q& F ` - namespace test;
0 Y" ~+ z$ v6 J& o6 T - require './1.php';
C% n- b9 O7 N) \& w& Z! P# u - new \one\Person(); //输出 I am one!;
1 U: e: \& {( w/ p, m# W- I1 k - new Person(); //这里结果会是什么呢,猜猜看$ n# u9 r: }8 w
- 最后一行结果报错:
& N) i( M" q$ O. i, N$ Q+ F9 Q - Fatal error: Class 'test\Person' not found
复制代码
# ?& `; B7 C3 x5 c1 Z% }% y. L$ O- u6 A4 O* Z
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 9 u3 k+ X5 @/ Z0 e) u# |1 U
结果报错: - Fatal error: Class 'Person' not found
复制代码 9 J6 i! h+ N0 Q" o8 \
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php) v3 x, ~. ^9 @" ?* y) I/ q
- namespace test;
& z- ~4 H: r2 r; U4 u - require './1.php';
" u3 I5 x9 b5 `: s0 X
- l; S2 `+ c8 z: V2 h- class Person{
4 W" m, V3 ^ x5 H( B - function __construct(){/ x$ B3 O6 V p) r
- echo 'I am test!';
2 J: _, h- i: Y - }
7 x$ O f+ P5 J8 w" t# y - }! T3 R& a! ^* [5 }2 D# X
- 3 h, N9 M6 e& H8 G- _- A! X* q
- new \one\Person(); //输出 I am one!;
2 Q# r) B4 U" C' x3 }8 \ - new Person(); //这里结果会是什么,自己猜猜看
复制代码
& O" y. ?6 K+ N+ S# I% A最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php, ]! j' ^; D' {5 j8 C |
- namespace test;
`* T! N% v' y, E y - namespace one;2 b3 t: t9 b9 |, d
- class Person{
- d8 X' @$ |4 m3 C- S2 h - function __construct(){
8 D; Y3 }3 u% u7 n" K - echo 'I am one!';5 @1 s# {/ u- L. Y3 Q
- }
, T* ?7 o1 M- \ - }6 K8 }" x2 i/ b3 t
- 0 s. L- ]) F4 O+ b
- class Person{
+ @" C; { a$ w: P) v - function __construct(){
/ E7 b: v( g) P* @ - echo 'I am test!';
3 o1 E: g0 i$ k+ [# ~ - }" S6 F$ }. z; n d) Y8 q1 @ O9 I
- }
复制代码 & Z( |0 c( v' N) w
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 ( p- a. u) T$ e4 k: l
看来简单的把require理解为替换,在这里行不通。 4 b z3 h7 Z h, z( A
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
% [3 z3 W# ~% G" V- _! _/ u- //name.php
|* G7 K$ Q) N g/ h$ e
. @: z7 o# \, `/ z1 A# }. @, t' _- namespace test\person;7 |, \ }& U( |& L' g
- / Q7 v9 |0 O* k8 R
- class Person{
# m- a) K# ]3 n. B. {, [; x# @# Y8 i - function __construct(){9 c5 K/ D' ^4 w9 b) v: @$ q4 }9 K
- echo 'I am test!';( m' ]1 `& i( z* b
- }5 _) F) o: y& b3 L
- }+ H& h( j. `, {6 [( s" r
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 . y# r* A' h8 K- F
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
1 E# f+ i3 Y7 g5 a! e' U5 k" M. D4 G7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php2 m3 F- }# O: n' X
- 4 \+ n& j" _; ]* p3 @
- namespace test; W: O" g# h& o/ v( J' P6 N
- echo 'zhai14';0 y0 B( J9 C: J
- namespace zhai;, C/ ~4 X/ Q6 ^" ?
- require './1.php';
复制代码 1 R/ m# ]9 N# X( O
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 / J: b t: d1 L0 ^/ c. L$ S4 X& Q
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
# a9 @7 X) E) d- //name.php
! ?) s. ~# Y. R' v1 }) w5 R& u8 k
) M& F, K( L+ s4 J" l0 h7 H* Z% R- namespace animal\dog;) ^7 W: `% L q2 V: I1 v
- 9 S( O% v- m- E$ w% e
- class Life{
0 ]# d2 i' k& @+ C - function __construct(){- w% w/ _; l9 Z
- echo 'dog life!';* k+ E# J& q, D6 C. l! E
- }
0 I" }, t) f* c- y9 ?4 \ - }% Q8 S; U5 p7 s5 U
- 5 f! u- C' f3 n7 S6 V' h$ _
- namespace animal\cat;) }# x: z( g* S
3 |. ^+ @# o& w* e# U3 J' f/ G0 j- class Life{
" S* ]0 P0 e6 F0 D% H' x: p - function __construct(){" \( @% a l0 x8 I
- echo 'cat life!';
7 |* |. R- U. R8 ?; s - }2 I0 Y: V! ]7 B. u6 J
- }
1 y2 T4 E+ B6 R7 p2 q; c* }
7 L; v. V; C$ R% w- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间& c* O4 g8 Y2 B( g+ O. q6 K8 l
- new \animal\dog\Life(); //A
# x/ E2 K5 h# i! |5 A! `$ G9 J% h
7 p; M* m' l$ [9 b- a- use animal\dog; //a
$ y' y, Q; S) L& j6 u$ u - new dog\Life(); //B# M+ F6 u: y# [
- 1 e1 c# R& E' L6 R9 p
- use animal\dog as d; //b1 k& X& q, `0 a5 H* V& L# h
- new d\Life();
复制代码
7 e v* A$ G! n* W; B/ A6 n通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
0 u* U# h7 t |% f/ [5 O$ n通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: # l, u) c, ^7 Y" m, z
相当于 |8 ]# ^0 w! w: L a" I5 [
2.namespace后面不建议加类名,但use后可以。3 y2 O; H$ G: K/ Y
- //name.php# X" M$ K a' i( E! @! F" S
* o( p) }5 U: W5 n5 b; m* ^- namespace animal\dog;
* w3 {0 _# P- U# H, i6 R& o3 a - 6 Q) ]; l. k2 Z5 a' {' @" G5 U, H' F
- class Life{+ `# L! U. s# C0 S. \% s3 G
- function __construct(){5 I$ ^1 P8 ^+ x! m& r9 U" e- c
- echo 'dog life!';
( {9 O' P' b% r- z/ n - }9 s$ a# J4 o* S6 J3 s. y* `
- } T1 C7 k4 v8 i' r7 k* s9 M
- $ p/ d* F: @0 s' c
- namespace animal\cat;: s1 h) A0 ]8 e0 L
" }- D c9 k* V2 K- k- class Life{$ W* d6 }' m9 z( @
- function __construct(){
' i" S7 z" `8 D( P, }; g - echo 'cat life!';
/ p/ ^! p; J, L4 u7 x' g0 x# m: g - }- f7 p+ K& W9 m3 m- C6 v; O% O
- }
7 Y) e8 l; d6 Y" w' x - 8 k% T, b/ h9 f. M- D; [
- use animal\dog\Life as dog; ' P4 g8 n S6 O# i3 F! y/ c
- new dog();
复制代码 / {$ h( l2 D" T! v2 @ `; P8 z: Q ?
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 . N! {* @ |% ^1 r% X
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php( u8 ~6 e1 N, N$ T& ~
- * @. P9 {. q; ]$ V
- namespace animal\dog;. W# g q `6 T& U/ f( H2 t# E
- & z4 [, I- R0 Y
- class Life{
4 V# G5 Y/ I X - function __construct(){' Y V7 y: ?; d B
- echo 'dog life!';# a# Z* o. z# O4 c2 e" K5 }
- }# a3 ~1 J! o8 Q& ^/ U* X/ `; Z' `
- }: p p8 u' F _4 _/ F
- class Dog{1 i% s4 U$ `- C1 ^4 S9 Z" h
- function __construct(){
7 o3 B2 m8 u* S8 ? - echo 'dog in dog!';
3 I/ \0 m; U1 e) k/ d5 A! D9 g - }, U5 A# L8 m. d- [
- }
0 t) V* S# f$ e8 P6 l# P
) c9 \+ O$ J+ b+ D; ^' ~- namespace animal\cat;
* O$ ^, s+ ^7 e. t
) l1 Y# |5 C6 N6 a- // class Dog{
! ~9 d" n- Q0 ?5 O+ g" @ r" _ - // function __construct(){! S0 j5 a5 S2 l5 m3 O
- // echo 'dog in cat!';7 ~2 W: m, G' L& U; j
- // }0 X. X5 L* A) i: a
- // }- t- H) j l* ~
- class Life{6 w2 t& f6 W! |9 N6 G
- function __construct(){
1 h7 x; n* S& h- y: w0 e! K - echo 'cat life!';
2 d6 f' V. ]& h! { - } ]7 @9 l- I$ U1 h' q! ~1 g7 r
- }
8 y" B% Z. T" P% f. K4 \! l+ P1 u - % N [$ g: t6 I! j7 Y( s% ^
- use animal\dog;
" {3 o- e' N! r% @: Y) b - new dog\Dog();
复制代码 ; ~1 k5 G2 H0 k
如上,使用了 ) p; k* X6 O) A8 k8 N5 a2 x( Q& O
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 / q. H0 j; X0 b
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
/ B6 n; p7 c. j& p5 v8 `1 `. |7 i% Z1 N x& g1 [: r
) D3 l: r7 H+ Y9 \* [
. C& H& O+ c) i' G z" [2 A# k, Z5 q1 t5 ~+ p9 f0 `
|