以下皆为本人自我理解内容,如有失误之处,请多多包涵。
0 H, T: O2 o. m/ A* \文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 ) D& P8 m! B" U5 }6 Y' |
( o9 e& Q- T1 y
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
# `; T4 C5 A4 X2 a据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) ' d7 f1 _# S0 N9 e- o" Z
结合使用方法来进一步理解它的使用目的吧。
0 q" A; x+ R8 `( g* j, @0 [/ B$ ~. i0 Z' C: ?5 @
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;- F$ t& [/ x- f" M' m
- namespace One;
& V c/ N+ X# f) E& d* y - namespace ONE;
复制代码 6 F8 s. B/ J+ k6 y; s: U2 o
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 6 U% d, O( Y1 @, g2 ~8 M
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
6 [8 w/ `- z" _4 \ - class Person{
& j8 L9 [4 E- Z+ W; o) i - function __construct(){9 _* |6 G; O1 ~
- echo 'I am one!';: D; ^- g( S+ w- B" {
- }( O* _, }" I! h1 S
- }
复制代码- //name.php
% O' c9 ^4 D7 |1 q' w! J - require_once './1.php';9 i0 _1 n- H! ]: M( F: `3 Z9 {
- 2 x p) g' P$ F j& ?" n2 t
- new Person(); //输出 I am one!;
- @( _; w1 v6 Z - new \Person(); //输出 I am one!;
复制代码
. ]" X# T4 X4 l+ d5 J# C3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php7 q7 y8 ?# |$ `$ M5 b& K
- require_once './1.php';5 `; Z7 n) Y' O3 A& o* ~7 n+ n2 J6 n
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
6 J p6 [9 `2 U( b4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 7 v; i* r0 B+ i1 { X
- namespace one;
% n9 |2 _1 R& o0 K1 T - class Person{0 h: w$ U- K U/ ~2 z' [" ^9 n, v8 q
- function __construct(){
, z M4 L) a6 D9 s1 @ - echo 'I am one!';
, S: j7 g4 t" ] U$ k$ b \" L' V - }
( D) N0 ~( R' L5 v. s& x9 u - }
复制代码- //name.php; F% |0 C& u9 {( F# g7 y" {4 W
- require_once './1.php';: i, Q" T& Q: W* I1 b, e7 H
- new \one\Person(); //输出 I am one!;
6 t! }( B! W" ~* L5 e - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 # r& o- `& G$ e& W& M
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
1 m+ w' E' z- P$ |, B' n% | d: x( x5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
/ B6 Q! h/ d8 ^: p- //1.php ) h9 ?; `) c7 k
- namespace one; R4 b# b8 n) z* g; ~
- class Person{. C: Q, B/ k9 \ F
- function __construct(){
J; H0 ~ f9 D - echo 'I am one!';
8 r! N0 L* I+ c+ f0 ^ - }
: Y* b1 a' o4 n: }! {8 h - }
复制代码- //name.php* \! i) F; d+ @
- namespace test;2 `$ Q2 z* L+ y6 w) \' K) ?7 r$ F
- require './1.php';
2 A+ V& }0 ?9 A5 ^+ Q - new \one\Person(); //输出 I am one!;
9 q+ r) e. c# _0 J$ m - new Person(); //这里结果会是什么呢,猜猜看- t: a; c' Q- x# V3 N0 x
- 最后一行结果报错:
* _5 {/ B- [! b/ P - Fatal error: Class 'test\Person' not found
复制代码 ! n- n3 r' n4 K8 Q
5 B# T6 v6 X+ k; o6 s7 K S' H& ?
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
6 T3 C' ?3 k8 n结果报错: - Fatal error: Class 'Person' not found
复制代码 # N% T- b2 j2 Z# n
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php# o4 d1 P: y; T X1 F
- namespace test;9 t7 K) g# q6 V$ `
- require './1.php'; ) R( J0 s2 i8 q o$ I+ Z0 y. ~7 p
- ( I9 P' r/ {: ~1 `' W3 M
- class Person{7 c& h! r! L; Y
- function __construct(){
/ ^" \6 }" B# r7 X - echo 'I am test!';$ p2 U) Z2 h% T `- T
- }
1 U! U! g' f# Y0 d9 r - }) y! }2 m) \1 k1 [( g5 v. |8 V
- + b1 j/ d3 s+ x( z8 d1 I( p( Y
- new \one\Person(); //输出 I am one!;
* K7 ?4 m4 N+ Q8 ~! w( Y- E - new Person(); //这里结果会是什么,自己猜猜看
复制代码 ! {4 K4 J% E/ U# l# b1 j
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php, T' b0 {& y* u$ i7 c
- namespace test;
' @* z) ?" Q$ K - namespace one;$ N/ Q1 G6 {. r2 p: J
- class Person{- V/ Y X& X9 X8 ^) ^
- function __construct(){( D, P' `9 v- c: n5 ]) V
- echo 'I am one!';
x- y% C, I8 P1 }5 m - }/ Q" @; ^( n/ W; U7 [6 W& l
- }& ?3 f3 p$ Y$ y* X" v9 f
0 t2 b# H/ o4 @0 B: n/ _- class Person{
! q/ X7 y' Q4 | - function __construct(){/ x7 {# e1 D4 [7 E, z% p* Y. n% X
- echo 'I am test!'; a& h2 J9 ^4 [
- }5 Y8 \- X1 y z8 V& W
- }
复制代码
' K: S' }1 a9 {/ J" E无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 : r1 A0 B' H5 x5 v4 P, I# B
看来简单的把require理解为替换,在这里行不通。 6 R% R5 i" u! R6 f
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
. y! e7 q2 R8 q+ H- //name.php _# k/ D7 H' @
' o8 D/ A; D5 N- namespace test\person;: a5 m' @) Q' }0 h9 n
0 F. v$ R# U5 ]# I2 N! g- class Person{1 S+ K8 M" ~4 P$ q
- function __construct(){
% |* K; T9 }" d3 b. R% ^) ^ - echo 'I am test!';, K( L& A* j2 E3 A6 |, R* a
- }
4 r, J4 v3 B) O* V( {( e - }
+ Q M! Q' M, n' s - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 7 k: [1 j# u8 r) C% f. S
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
! ^/ {) L* C3 L9 }1 o, o5 O6 r1 `7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php& I% q- L, O. h6 q
7 s2 ? k# g& O4 \' y0 g- namespace test;
, i* ~) N. r2 d4 T4 f9 ? - echo 'zhai14';& v9 L' T$ F8 y# f1 l
- namespace zhai;
! H: ^" h$ E8 b: W9 b6 m - require './1.php';
复制代码 % N$ U/ a9 N0 h9 v$ l, r+ S
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ! F3 e$ Y% X3 x4 d9 [' ]9 S# \9 L3 l
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。0 O' Y# c4 L5 w/ _
- //name.php
5 z% t1 r, p, v& A# e
) b' `7 Q& B0 F. e- namespace animal\dog;9 r$ Y8 x# F% |9 s6 T% B0 W' x& \+ P
- 1 w! ~ j8 F; ^( }2 ~( ]: `( I7 Y- C
- class Life{
! R6 A5 u Y& L! V* m7 v - function __construct(){
' N) |' p d3 ~4 G5 q* U6 k H - echo 'dog life!';
8 ^* }: M/ [: s - }
- l3 Q/ n4 y! @5 o2 c - }; R+ D/ i* H& q- {. F+ ]/ ^; V
- . Y- \. g! B) P/ E: O7 H4 ^' U
- namespace animal\cat;
/ q! ]5 S# B( F - ' J& k9 R# Y. E$ d3 O
- class Life{4 D0 a5 w \3 C, b
- function __construct(){1 b. K7 F: G. r' J
- echo 'cat life!';: G2 B5 l- h7 s3 p9 |
- } o9 J0 |8 a7 o' h @# L
- }
* A8 c) L$ R V. C
! T8 `, P) M/ s) d+ _9 ]/ Q- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
) i+ [) V, X' c2 O - new \animal\dog\Life(); //A: j$ q5 G& ~& N
- ]$ _ F2 Q5 V* A9 p- use animal\dog; //a- A; l! `+ M& _' x
- new dog\Life(); //B" z" G/ L! p( }$ U1 l4 V
& \7 h5 n# J, ?! h- use animal\dog as d; //b
' ^ F; G7 T( g( x6 d- a - new d\Life();
复制代码 8 H0 w% S2 d% {
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
- o H) s% T7 \ I/ p; T通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 7 t, U0 ^9 S! B7 E) U9 ]
相当于
: A c. J# ~6 o0 q2.namespace后面不建议加类名,但use后可以。1 A0 o( p$ {; {5 X% }6 x8 k7 j
- //name.php
1 J9 f. x' }: M: z% m
& i: p# q. {% b# J3 @- namespace animal\dog;
6 d1 V/ l- D; a5 Q - 7 h4 L% G: E6 |+ t2 B. i2 Z
- class Life{
9 K* E7 D3 a) } B) \+ j8 ^ - function __construct(){
' x* u& Q, x3 X4 L' p - echo 'dog life!';
# C+ W# C1 I' L7 B y* D0 b - }
" S" Q" c& P. k9 | - }; Q2 m9 N0 D4 r7 U& R$ W- r
- 0 u2 u" @5 R1 Y& p) m8 B
- namespace animal\cat;, z4 [; u5 e: c
/ [3 Q( ~1 E8 H# b- class Life{, C$ @) J) w1 I0 A* J9 f2 G
- function __construct(){. }% ?5 k5 P/ q
- echo 'cat life!';$ O1 ^ M# [4 @! W4 g- L# e
- }0 T( l7 H% z5 j# R7 M! z
- }
$ k$ o4 M" y/ _6 q# {6 a& E: `- a. H - , A1 W5 d1 V; K. i0 ?9 A/ [
- use animal\dog\Life as dog;
) G% \, }1 _$ L- K* D) S - new dog();
复制代码
* b. g; f: q8 B" H如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
I0 \! ?7 q. Q9 q0 C0 p6 Q* F- L+ J因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php& Z& B# X5 _$ l0 g+ a
/ s. _2 R& ?( j z& d1 N* M- namespace animal\dog;
% A! o* [& X9 `& D" w ? - ! a$ \0 T ]5 G( U
- class Life{
$ ]- q( w s! ^ - function __construct(){
' O4 N# Y5 |/ N* s" E: ~. g9 c - echo 'dog life!';$ X+ x# M: W: ]: ]+ Z* r
- }9 e% k/ [5 K1 f
- }9 k$ H. z m0 i! e( {
- class Dog{
J2 g7 |: c0 ~7 c. i' {9 T - function __construct(){
5 M4 ^8 J9 [& z6 C3 k" f - echo 'dog in dog!';, x4 X9 h3 y0 l9 G. w3 _" a9 @
- }
' N( Z* e, y% ` - }) J- b: e( N" ~, U% g6 ]6 A
@" i% G# t7 e; Z: I g' x, y R* U- namespace animal\cat;
, [0 C8 M: V& C6 T% B2 K - 6 X5 `4 x& b I$ x. `/ f: [, t8 @
- // class Dog{
2 L+ a7 [& @4 T4 l, T+ l5 Y5 w - // function __construct(){9 \7 N4 d) k! k# i# O
- // echo 'dog in cat!';9 ]$ @- S% S: e p3 R
- // }) P) e, _5 M+ E$ `8 c' o- Y2 M
- // }, u( m( N2 |$ Q9 a' a+ ^
- class Life{
: v7 a2 n; O: h6 V; s9 E - function __construct(){6 I( E/ G3 B& F; T) t
- echo 'cat life!';' T8 l2 E- U. u4 S3 J) q
- }
0 b+ h3 q7 f- _! ]) b9 Q* h - }* u: J8 ^- m- H+ `" X
- ) \/ T$ _3 x2 O, ?/ l
- use animal\dog; . i: @( S) M! D6 X! a9 _+ [ k& _
- new dog\Dog();
复制代码
1 Y7 \" x, W- T9 D如上,使用了 7 e! h/ x! P0 d% W; W% Z1 {, s
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
- z/ G+ Q- S7 E8 G |6 l% D% _. C简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
" Y* u9 ]( c- I% e, E
l. K5 O4 h$ h" `% a! i; V, x5 R/ @+ t; _+ Y) S% I' }
3 U- ?0 y- z e) I( W1 x# L& ?" W6 N$ e v1 A! ^& C; h; N
|