|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 0 t/ h, x7 I: S
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
# [. b' ]0 p/ `+ H
3 a+ X& d+ I L$ s使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
2 f8 j7 G% R# U# R( }: e$ w! n) J据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) 1 u7 e. a1 t& D6 P" i, e& J- i& v& b" K
结合使用方法来进一步理解它的使用目的吧。
& P- d2 o0 @+ d( }& ~7 ~
, y& g6 b# U0 [, ?+ d0 T1 G& Unamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;; |& ]* w9 h$ j* @
- namespace One;* V3 v) R/ o8 i# @( u, }$ e
- namespace ONE;
复制代码 # _% Y9 ?9 O* d$ Y! j
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
8 H y& \4 J h0 M3 s- |2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
0 q$ [# r8 R) x9 A# I/ \) M$ U - class Person{, i4 W2 b6 T( d$ `+ a( v0 k
- function __construct(){/ `. Y# q) q6 N; Y8 ?/ C
- echo 'I am one!';3 l, E$ x+ O* d* e) E1 W$ @# x
- }$ J) s* d6 f6 X$ K9 |
- }
复制代码- //name.php+ r7 I$ o9 T. T' V9 c
- require_once './1.php';: L) q0 C; s, t9 I0 n
; i5 l, J6 F! @3 b4 U- new Person(); //输出 I am one!;+ Y# _6 L0 D; {9 @ D6 F
- new \Person(); //输出 I am one!;
复制代码 ' N7 ^$ j# W0 f4 {$ g/ Y0 a
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php: D- [, y y0 A" l* Z
- require_once './1.php';
9 j" E% g% W* X - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 & O! v; q1 a* N3 u5 N0 {
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
2 B7 y+ r$ b ^8 X6 C: X7 y5 T - namespace one;
+ r' T: E4 y5 c7 [" w# q) K6 g - class Person{
0 M" }; x) _% s7 `( B" Y+ h - function __construct(){
- X0 m+ R/ m5 b6 @9 Q) A - echo 'I am one!';
& |! e3 m* V+ e4 Y* a7 q; j - }
* q' U; z K- I9 s* B/ `& ^ - }
复制代码- //name.php+ E+ @. J( f. x8 ~1 V% u7 M: d1 _) D
- require_once './1.php';
8 L! U" o, N% |* @ - new \one\Person(); //输出 I am one!;
4 c# j4 y1 ?2 Z. M - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
" w( ]/ u0 I2 B* Q3 ]6 g% n# ]( _可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
1 P7 h* e: S& ~% R f, z# q9 K- u j5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
- V6 f1 ~7 Z' R/ Z! G: H- //1.php
' t. T7 |' F: E( g, U# q( p - namespace one;
% h9 ]( G! z5 d - class Person{' }: j7 j0 r! P
- function __construct(){
$ k. f: t( X2 ]! S8 M ]8 ` - echo 'I am one!';5 ]" Q& i- X, J
- }
6 E" n8 s# I' b8 U - }
复制代码- //name.php* ]* M( J; @- q; J
- namespace test;( T* r. m. l( J l) g/ f
- require './1.php'; # H) P9 ?, e- I2 R% t7 X& l
- new \one\Person(); //输出 I am one!;4 I: z8 I) R' B% F ^& X- ~
- new Person(); //这里结果会是什么呢,猜猜看
: p" R5 K/ q& T/ b. } - 最后一行结果报错:
3 |! Q5 i4 E7 [3 I - Fatal error: Class 'test\Person' not found
复制代码 $ T- Q/ s0 V" D% B8 z" `
/ N3 Z4 J( S7 K8 S. `- x; _" y$ l首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 $ ~0 Y. W: p' g. e
结果报错: - Fatal error: Class 'Person' not found
复制代码
: i0 Y% u% s1 v* N0 R0 ~接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php a# S* R4 k* h$ B3 G" h& U
- namespace test; ~. y2 t0 Z3 A
- require './1.php'; 1 l. U9 z% x1 H- s# f
- / L! r5 l3 q- X2 ~
- class Person{/ w% U q9 ~9 x& t
- function __construct(){4 ?7 J+ o0 G# N
- echo 'I am test!';+ z( z: |7 C8 P" v- ^
- }7 H6 r, b. z6 f3 n7 C+ U- A- ]( P
- }
; J# G' c+ ?7 Y, y. P/ k
$ J* f' S3 g8 s4 `2 f8 c- new \one\Person(); //输出 I am one!;( f5 d; d, B$ g5 @% ]
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
8 g, W# f3 s* z) r$ p- ?8 f2 ?9 p3 h6 R最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php0 B$ T0 Y2 p+ b7 m# D
- namespace test;& ~4 H T5 ^- n8 H6 R
- namespace one;
3 _- A) {# X$ l. h - class Person{
5 ~. O; D5 @' H - function __construct(){. T6 f$ H7 i0 l+ m. E* c- l/ [
- echo 'I am one!';+ N1 w. ?" J3 w) }+ J
- }
9 \; l4 {4 P0 x9 Z: y0 j$ r. H - }) o4 }! D9 U+ A0 N% g8 P
- $ D! P9 L0 v9 A p
- class Person{
- l; e" l% V$ a- P6 [ - function __construct(){
( T% A# c# U+ A3 F$ r: X; o - echo 'I am test!';: L5 f; Y7 D0 p' _) R
- }! V4 Y* R+ K1 m
- }
复制代码 / o) l1 O" p9 O1 I4 A
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
9 v; L+ \: x2 }# t* F ?. B7 {% q4 {看来简单的把require理解为替换,在这里行不通。
- A, {8 t: I8 o7 u/ o8 b" m6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。) ]9 V: R) D) o5 s2 {0 b/ F! @
- //name.php8 a' H2 a% D) D/ b4 F
5 V# ?4 d/ Q7 i% r8 O! o1 u- namespace test\person;
2 K0 p; N5 B; H& ^4 J$ H - * F, R4 \5 Y8 I1 x& w
- class Person{4 X: O' U' ~) q$ O" {" h6 T
- function __construct(){
" O6 |9 U) x- R% @' f - echo 'I am test!';2 M3 t! f1 x$ [& r
- }- f/ H H( b3 ]7 X
- }
' ] s" O4 ]4 { - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
8 |6 d) W; ~# X0 U7 X: V不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 + J' S, I; o, Y1 k
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php
6 C& m* Z+ P p- V - 1 \8 e# n: B& b! a* C% _; L; I7 N3 W
- namespace test;" x4 S- S: T# x5 b7 Q
- echo 'zhai14';; s0 [1 t" A6 S
- namespace zhai;" }5 d, M% ?/ [2 |9 G! V; \1 H
- require './1.php';
复制代码 1 C6 w5 D# o- Q
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 $ U2 l. W3 p( [, K7 a
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
8 v& [6 p3 W" k7 j+ [- j) U- //name.php! k1 Z: u# G- a- T- V+ J, o: x
- . T( H; i' {- U+ I! D% N
- namespace animal\dog;
8 W9 g; l2 R2 }! y - 6 V; q. h9 F5 O) \5 l& E
- class Life{7 d4 \% I- {; t
- function __construct(){
, U( G& ^! w% [; w - echo 'dog life!';* M$ _: O, Q4 u/ j {# V1 F" E
- }9 a! h4 A. V' ~ d% \( w
- }4 G% M- x9 u) c5 C$ _/ e$ t* D
- & ~' T3 H; k: P$ x
- namespace animal\cat;
: o2 O6 L0 u& N& t
: i) U/ A/ H) S/ U4 @8 @- class Life{1 M5 h. P$ @" u
- function __construct(){
* ?& f2 q. n2 q7 a, f6 {# O0 q4 r - echo 'cat life!';
' _) o+ h7 B/ L" c7 R - } @7 v0 Y) w! O. T- L0 w
- }5 }9 k: i- g$ l6 a1 ~' a1 O- |' c
$ G- ~1 h6 q/ ?+ `7 V- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间; x, u! \5 c- F
- new \animal\dog\Life(); //A7 Q4 E0 R; d& Q/ D* R: q+ |, b
- 8 c; j' L3 ]- J$ D. p
- use animal\dog; //a
) u& y9 {, C/ N' G0 u7 G. ]' b - new dog\Life(); //B
' {& g- O! {7 h! A9 J - " L C. v5 t: K# w$ u; Q8 i r6 ?
- use animal\dog as d; //b/ x3 B- O& M( K
- new d\Life();
复制代码 . A" P6 u7 q% a+ k4 }# L
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
9 m& V: F! y$ ]+ Z1 K通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
; f; t$ m9 N2 R( u y+ T相当于
' i& Q: m; \! H1 W3 m H4 o2.namespace后面不建议加类名,但use后可以。- N2 F8 `8 J9 N! {
- //name.php, A" |; |! ]. m
7 @/ T4 X# `4 g- namespace animal\dog;7 H' |. C/ j7 h) b* t
8 i' v7 [3 t" T" }! ]- class Life{! j- }! T/ _- t7 h( K! { Q
- function __construct(){2 q# ]( z. K* n8 J1 j0 v
- echo 'dog life!';
+ H0 A* @7 r( K& @, \/ `4 ~( } - }
7 `6 X" Z/ a2 _ - }
+ C$ x* }0 a* g# ?5 B1 g6 O# C4 A - " p6 M; b4 S1 P. l. G
- namespace animal\cat;' B; A" X5 ]9 Q, D# G: c& I& v
- 3 l* R; |* }. ]4 k/ D
- class Life{
) z/ {. y" g7 ]0 L- C - function __construct(){
& R- f; o- x6 ?/ `0 E" C - echo 'cat life!';
! ?: M) m) R- x) K - }
% B. Z7 M W5 X6 B& Y, `9 k - }
0 s" F( }" U* U9 c* [2 W9 W6 M3 g6 r: G
- S) D4 X( G. b3 c! C& t7 G6 R- use animal\dog\Life as dog; 1 L+ Y3 e5 }$ _+ S; J U Y
- new dog();
复制代码 8 M6 r! }$ M$ Y7 q
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 0 H( [) U" d+ D# f( g' I4 r& H" M5 b4 h
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
1 T; Q6 ^- Q2 y, e- k; a9 g4 X+ t
# ^6 p- k- d& o% F/ a2 N2 w- namespace animal\dog;* n% G' J4 }8 o4 l3 d$ N# B9 l1 f
- 1 D }$ h* n# O% o: E% O: M
- class Life{: p: b* J6 ~' T1 m
- function __construct(){6 M+ b3 t0 ?6 ~% G2 H( I! Y2 J
- echo 'dog life!';$ U, u9 _9 c* p! B0 I9 ?
- }
. Q W* j, v0 M' l - }
( P3 s) Z! a4 j! d - class Dog{
6 V- b5 g! A# K - function __construct(){
: b% f5 Z" L' A. L2 ]3 b' q5 p; f - echo 'dog in dog!';
7 y- s5 e$ K) h' o6 T3 a5 z - }0 @) V) a; }, F. \- A
- }
; [! C- ~: H9 d- |6 Z7 N4 e- _ - 5 `# Z+ s: x$ i1 ?, u, s y( [
- namespace animal\cat;. _ l X& P0 f9 X3 `5 [
- 8 X4 ^0 M, p( x; P+ X7 }, V0 q
- // class Dog{
0 C2 a4 {3 C- Z: J. G3 I. D - // function __construct(){
# h6 s* N/ O4 Y% N1 O) O - // echo 'dog in cat!';
" @: G6 ?8 x" n. Q& K - // }( B8 r1 @6 U1 `: x- Z
- // }
5 ~& X6 x& m# ~" y& e1 y' N - class Life{
- j6 K# U4 ~: f9 Y1 a2 t/ Q - function __construct(){2 _% v( P4 D9 S- n# k5 b* p2 F" y
- echo 'cat life!';8 ]% Z' q7 {% A8 A: r- p2 ?8 U/ P
- }
5 M+ B) R+ ]% P. B8 o - }3 O" Z3 P% A! Z8 a( B
3 H, X+ I3 w7 }0 i- use animal\dog; 1 G% M( J/ ^% x/ u+ {; G$ `
- new dog\Dog();
复制代码 ' p5 ~+ N9 w4 k" F- c
如上,使用了 - V) b' F G, B) E; k2 Z4 j: j
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
0 ]8 R2 v( W/ ^. U# T简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 0 g9 w' C( o' J4 ?5 p" Y) N
5 W9 A0 ?3 f( A1 Y
" [' x7 w' a9 I# u
0 |% g% o8 H% I, x i% k
5 t7 I8 |" p) H6 P) l* \/ z |