|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 & G" ?2 t6 o) s: _/ L: i- H# c9 d3 u
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
" M* L- l5 P# f) o) Z. s. z, o8 V. v. M) ^' Y* A2 {3 \
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; d+ m1 R8 g( F2 h' x
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
4 }* X2 ?! y% k% d+ n8 A结合使用方法来进一步理解它的使用目的吧。
2 { d4 D& _0 D) v1 l9 k
; L- D! d3 U! {5 N+ }namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;$ J) X, D; C+ W a8 o
- namespace One;7 d4 H% m( M2 A b
- namespace ONE;
复制代码
% v, b& r& m% v! I如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 1 G( z) F# n( N3 P# _# W8 B
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php ; _* |& F0 ?7 q
- class Person{4 a( D; o1 e0 e* V. q
- function __construct(){
: U9 p# I9 Z4 J. l& x! l M - echo 'I am one!';
( ?3 X" t# C4 \/ N7 L! l0 l8 k; X - }$ O: j6 A" g+ A
- }
复制代码- //name.php1 { c! D: y, ?: Q2 g
- require_once './1.php';3 a- F5 r" k3 r& g
& W; V4 ?" K6 v! t6 P* A2 b7 Z- new Person(); //输出 I am one!;4 L2 j8 _; P0 y' l- F
- new \Person(); //输出 I am one!;
复制代码 , b" @- B0 f) H& Q) x0 Y
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php5 {; _" T8 T: {
- require_once './1.php';+ X# ~7 N# A0 G a) H
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
j. G H' ^3 ^4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
7 y4 e6 b% Q# t% K" p3 T4 }8 x - namespace one;' }# T G# P2 @. G
- class Person{
0 C! @' _3 ^; d5 J( b5 l6 r - function __construct(){
0 T! s4 j$ I% q - echo 'I am one!';4 R; @% a! q3 h( b7 r
- }
4 E' o/ J0 L6 t1 I - }
复制代码- //name.php
& \! _0 A2 H8 h- M8 B1 K7 n - require_once './1.php';
- k' ]4 d. F7 [9 C6 `' U. l2 G, T - new \one\Person(); //输出 I am one!;
! ]- H! o8 f" e x; c - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ; G' F8 `2 u) }6 ~' |
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 - v2 m6 m1 N: y9 U8 i, I
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。! A' K. X" [4 b4 e4 U4 \
- //1.php 7 B* ], `& U1 g$ x7 o3 K( J
- namespace one;
, o3 O( F# w$ g( J" D" [& o - class Person{. N8 Q$ O4 Z7 n) J
- function __construct(){, H2 A% Q0 `- Q
- echo 'I am one!';
d2 S c0 X* @, [+ l) `: [6 p - }
/ F9 ]$ q6 c4 \' A - }
复制代码- //name.php
- |7 J7 M7 z h: @ - namespace test;
$ U- `/ {$ q5 s - require './1.php';
& v- g5 c3 v. I - new \one\Person(); //输出 I am one!;/ K9 X* K- b' [4 a/ O* `
- new Person(); //这里结果会是什么呢,猜猜看7 [$ k5 k+ [& u9 K7 r2 L! E2 e
- 最后一行结果报错:; R! M7 o" \# t/ d7 f5 ^' K
- Fatal error: Class 'test\Person' not found
复制代码 0 j6 W. G( I' M$ s& w/ v% L+ Q
2 y$ B1 w/ i! w( ~+ K
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
+ _9 x( @9 o: S0 a3 R8 v结果报错: - Fatal error: Class 'Person' not found
复制代码 4 V' T5 @. k( z5 C- q; d7 `- {
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
( d4 R6 Z2 X4 S/ V/ J' |3 U, C7 e - namespace test;% i' g3 G/ j9 I- k- _) |4 H
- require './1.php';
* q+ p- h; U% }0 U0 { - 4 @- T! J, k) J" h6 g2 ^
- class Person{
+ u& J! ~1 u5 |; K0 D - function __construct(){
, Q M1 c5 d* ~* H - echo 'I am test!';
: J* i/ k; L* F - } y* g( p5 l( h B7 U, }( X4 t0 H% O5 Q
- } J, K* M3 O- _# e. ?
- ! E, \, j. d, }7 f( c
- new \one\Person(); //输出 I am one!;4 O% q8 Z# G( G: O
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 4 F) W6 z- J/ p
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
. ]1 A: e* ~: E# z# j" C) w3 Q - namespace test;
, }+ Q; S) c9 u1 u - namespace one;$ P* j% ~6 b1 E+ ]6 r
- class Person{
+ @- e/ F- t1 c6 | - function __construct(){
* z: H0 W1 m. |+ f \ - echo 'I am one!';
+ |, X. k! m& z - }0 q; ^* ^7 b$ ?. M3 N7 Z: P
- }
% A4 \' B0 |) \; Q/ [1 C - ' h$ M' n0 C& r% Q. U
- class Person{' G, r* U5 P% c$ H: F8 ~7 F/ n
- function __construct(){
% G% k& P, m5 J) W B/ G0 d; W - echo 'I am test!';
( h* @: c- @+ D" r: T4 Z - }1 v) u' v+ q5 n7 Z. j
- }
复制代码 : ?1 E- c# W, W( v! b K- k+ N
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
, Q9 V* _$ n1 g看来简单的把require理解为替换,在这里行不通。
& p8 T& W7 c4 a. N; {6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。3 j* K5 M2 ^4 i! d1 G
- //name.php1 T9 V3 ?7 v1 u7 {$ \4 d
9 w0 `8 F+ \5 g# V( P2 \8 D! x- namespace test\person;/ ]0 l4 I% j' K; [" U0 ^
- 8 I2 m4 `7 j' v- V$ ^& L1 K% t
- class Person{; h( K8 J- R% U1 O% W) M! F. l
- function __construct(){% f) c: U) `3 Y& [: U0 g! n
- echo 'I am test!';
6 j4 p J7 Z, T! B8 ? - }- k! M0 G: t' g# R5 I, D# V
- }
! E2 y' C- ?8 `+ h! V - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 1 m; ^" p$ v" D) B3 ~
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 ! R# p5 J4 z6 O7 j0 }9 j% u5 v
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php7 \. a- p* j" h, `( E0 q+ B
- . r+ S" U, Q* d4 c" E4 p& ?
- namespace test;
( \7 P! t- a& t) o - echo 'zhai14';
, a, @+ {& t) W# d. ~/ L - namespace zhai;" E6 M* Q. H, n' g
- require './1.php';
复制代码
5 J6 Z4 T; x( ?. ophp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 3 ~( E. ~2 G; \5 y7 O, D
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。4 |5 n o+ e d# l* [2 c+ D3 V/ t
- //name.php
; r' f% ~1 ^7 h( k# N$ l
( K- F+ j8 N7 ^8 r' _- namespace animal\dog;
" [- W1 s) U( c3 r1 N - 0 |9 [9 s3 {* {' K: u6 U2 `/ j
- class Life{3 C' F/ d2 Y7 B
- function __construct(){! i; M" q1 H2 h9 C0 p" X' l
- echo 'dog life!';5 `$ J* s3 h! ]* T# D
- }
+ b4 @7 H) X2 w - }- y2 y$ ~" d9 j* }; s
- - t. @5 P" q0 L8 P5 J
- namespace animal\cat;4 ^3 S I$ r& O, m8 W
9 I( t1 r/ J9 Q7 n$ u* B; h- class Life{0 T0 y0 h5 a( t4 L) y* q
- function __construct(){
) ]) V( u" n7 x/ J, a9 }0 v3 o - echo 'cat life!';
0 d2 \. j' F5 T5 u) Y - }: \2 u. C& {$ j! J+ S! d. N" I
- }
4 |$ H2 S5 [: Z1 q2 b+ A/ W
, U/ \. K+ G: u" \8 M- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间! L/ L" J( j, y
- new \animal\dog\Life(); //A
/ K+ `: |$ H/ e5 y' {: b - 5 Y3 a! d/ Z2 Z5 U9 v; k( {
- use animal\dog; //a6 K# X/ G; n2 c7 B7 z9 V
- new dog\Life(); //B, a3 Z8 R% z# g6 M% y' g
2 U9 ^. x+ E4 H3 q. c/ p' g- use animal\dog as d; //b
- D9 C. F6 X6 G" I i0 E3 W& s1 _ - new d\Life();
复制代码 - ]/ f. R/ i; D! d1 B
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 z0 A/ _8 d* ?0 w) J& ^* \
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 2 u/ m! j4 n+ ?. I0 e1 ^$ e" X v
相当于
3 \ u( Z" i/ }' q+ k3 ?. z2.namespace后面不建议加类名,但use后可以。, I9 A% j0 `5 k: X7 x
- //name.php
2 U3 E* J1 L' j: J5 u
# r5 i. h+ j R$ ?8 Y- namespace animal\dog;
+ x* i P$ m, N# s$ J5 H* J
4 J4 V* J! J. z5 I w. ?- class Life{
5 u5 p' ] J3 b+ p - function __construct(){+ B; }2 U. a9 h6 f9 _" P
- echo 'dog life!';3 y9 J8 ]" E5 d0 D
- }( G" O7 n/ x3 U
- }0 ?. ~. {( u3 h
9 z& r3 b* E, X, B, m- namespace animal\cat;
; } f, D4 g3 a1 Q/ s7 n$ b) n7 } - + j- W" s( ~& T% [' n& ~& n
- class Life{
8 q9 F7 f) u: o, s3 e - function __construct(){
0 z+ u; V$ h; V4 \5 \- N - echo 'cat life!';
( q3 i2 ~1 p+ C& c; ~5 q/ Y2 m - }5 J/ r% E9 F9 Q0 h/ b% T
- }
) [6 k( a/ s! ?. W" r
: m8 ~; r* C6 B: ~3 v$ i( J' o- F- use animal\dog\Life as dog;
$ ], l `4 H& k1 u" b! b1 E: D( ? - new dog();
复制代码
8 W2 t6 Q8 n, H如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
% O3 P) u; ^, W X$ U$ Y因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php+ H( i# p Y2 E# @8 g& U( {
# X& }; O4 @. x0 {- namespace animal\dog;5 h B* i( D. L- l6 E
, R6 D2 X2 a6 x& V' @- class Life{+ o4 a/ R1 y+ _7 ^; K
- function __construct(){
1 w/ V6 b6 I9 E2 x; I, H9 W - echo 'dog life!';
% ~, m* ?! n* G# }* B; l - }
6 |& r- e2 v) a# b - }( |( R+ J6 o: k: H& ?$ C" V
- class Dog{
. b3 p6 ]' H- i P - function __construct(){
( J7 k) c5 u/ ] q9 `, X - echo 'dog in dog!';
7 b! @5 u3 l: `/ V0 h - }
9 d2 E' B1 Z( o% g5 E7 M - }
( I; j1 x8 P1 [, x6 s: M! }
, _) F/ [3 e# m) D+ o7 s- namespace animal\cat;! @0 r* T) y: v( m. Z. v
- 8 M/ y/ b, Q. Z
- // class Dog{. g; A* }$ y/ H7 @9 T" F, [) v
- // function __construct(){- G5 v, P4 E, i+ }, P
- // echo 'dog in cat!'; z, k; W! E% I! j Z. c6 @$ A
- // }
0 n! K) x4 x" q4 u0 F% U - // }
* M, A3 M/ C( [) y% d6 [! U - class Life{- {$ v {5 D' Z* h
- function __construct(){
5 ?3 z# Z* Y6 X2 Y7 ?8 a t - echo 'cat life!';( J" K- X$ t! n. O: s, P# M
- }5 G" ^6 {8 o5 Y
- }: d: s% d/ t/ D5 g4 N
- 6 w' @3 I' o, a: S* m. v" c! ~
- use animal\dog; * j! Z- j, L4 S) d7 Z7 X' g' _
- new dog\Dog();
复制代码 % B* |" m8 Z% I* v7 f: m" n" [
如上,使用了
8 C/ Z; q0 w/ ^" ~0 }7 ~# i; h, wcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ) u3 s4 v& V# L% e E, M; _8 T- f. r
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 . o2 A) [. A2 w H
+ n: r4 e2 g/ ]
! C; K9 U9 \- E
1 d( @8 h& ^) n- X# n4 u3 U$ h, }# k8 [. y' H/ l
|