|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 : v4 g8 [' X9 R5 K/ r/ n2 {' z
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 # d: m( Y; g: I; B, V: z
) I# m+ \; \3 E I5 `
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
7 d: l: i' d/ c- }据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
2 E" P) u# ?; _" ?8 a结合使用方法来进一步理解它的使用目的吧。 $ N3 m0 {, S1 ]. `
# n3 V2 M9 m8 N6 knamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;, N! N. w# x0 d4 p+ W2 J
- namespace One;
0 H' f# S' F y t# p" F. c - namespace ONE;
复制代码
" c. r# y, R2 g- O4 y5 Z4 G如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) ; b2 F9 g, p3 E3 {" X1 a" A7 r
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
7 X: D$ g4 i5 D: d) C- l - class Person{
7 e e2 {2 _: [* x) l - function __construct(){
; w4 l3 ]" w' |' H6 _ - echo 'I am one!';* B$ o: H8 n) ]
- }! z0 G1 t9 y3 m; a, K4 h% P7 _
- }
复制代码- //name.php
# @' C0 N- e1 I. |1 O - require_once './1.php'; R! Z& k2 D8 a
- ) r# a2 E% t4 z% Q4 s
- new Person(); //输出 I am one!;
( q1 Y7 y$ e2 l7 J; N6 } - new \Person(); //输出 I am one!;
复制代码
% D6 D4 e8 k! |( K6 u! G6 s3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php U* Q4 f- u" W9 Y0 [0 L0 B7 S6 T s
- require_once './1.php';
" b) [/ d6 F% M7 K$ | - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 5 o3 J1 C. q3 c \" M' T
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php 7 n) ~" s( _; w1 f' L7 Y$ Z& s: X
- namespace one;
) W( E: V* l/ d# Y: s% E - class Person{+ W) b9 |" i) v* g- ^2 n% p7 ]
- function __construct(){6 k0 F/ d- h% r8 K- ?% E. b" w( u5 R
- echo 'I am one!';' e0 g# T0 D& h- `9 z
- }) h0 |+ P7 J8 O1 Y) y8 }, C
- }
复制代码- //name.php+ k, ]; Y6 ?( h, Q
- require_once './1.php';- j1 p! N2 {) f/ ]
- new \one\Person(); //输出 I am one!;
" Z5 B* D! D* u( } - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 5 X ], q" C% A8 L; e& D* m
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
$ s* m/ O, G. ?$ W% v# f5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
: s: r+ L6 W6 U! `' }' Y0 ?- //1.php 4 p3 b' j6 M2 o* y/ K( n( l7 H
- namespace one;
: U2 J8 ?$ g) }' s - class Person{
- H4 ~2 K5 q$ [ - function __construct(){
3 Y! Y) I3 B0 C u$ S - echo 'I am one!';
" }2 O2 |/ ^, H4 z2 |7 `4 T - }+ b: v K. H9 P; E t! S8 K) ~. g
- }
复制代码- //name.php
( C3 E r0 X6 Z7 J# g2 e; R) ] - namespace test;2 @, o, N. [ f; Q( e3 n
- require './1.php'; - K' ]* |4 K8 B# \: h* C8 f
- new \one\Person(); //输出 I am one!;
+ r1 ]+ s7 `0 I6 m: e/ s- K0 H" ? - new Person(); //这里结果会是什么呢,猜猜看2 z: [1 o5 A/ v; w ?
- 最后一行结果报错:! ~) c J& {% m6 H& E1 H" y
- Fatal error: Class 'test\Person' not found
复制代码
- i0 K" V Q @$ X# y2 N) h1 S% F8 f
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 2 }7 `- E1 W) M6 v
结果报错: - Fatal error: Class 'Person' not found
复制代码 # b. h: }. h$ y
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php' O1 }& }% J+ u! H% d3 S3 H
- namespace test;& r! U- W! y% @. _6 m
- require './1.php';
( W6 p( ^0 a$ A7 J# x% p
* i* E1 }' s: Z3 M6 q/ p2 D- class Person{/ o2 _) x8 h3 o G
- function __construct(){; J/ e; l) v+ u+ C+ o5 D6 x
- echo 'I am test!';
& V+ t4 O% E7 @* C& X G4 Z' ~0 W. k - }
, K( Y- l" J* X/ S! x K/ d - }
% J5 N7 H6 f9 v( Y8 ^
- P+ f: @6 z$ a- new \one\Person(); //输出 I am one!;
) p# g* Q# Y+ G2 T, V* _ - new Person(); //这里结果会是什么,自己猜猜看
复制代码 - y" y! S3 G/ M. K1 f! G$ P
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
0 o( ?) o. @& A' e( V - namespace test;
6 e3 v9 R# r% x* ^0 |! }: }2 Y - namespace one;
, i! w' U, E6 m3 R& [# ~2 D - class Person{ F+ i8 ?! m0 E |
- function __construct(){) |! T( ]5 d" Y5 C% Y2 f: j
- echo 'I am one!';
: v' ^" s$ E& S8 r - }
( C% W2 e1 \! e - }8 p% V$ [. R& n* L% |4 l
- # r( @0 G* C, Y: s
- class Person{
+ ]4 A2 T+ I5 B6 } Q f8 V% p - function __construct(){
4 G `9 n$ O0 E- ?) z" R" Z - echo 'I am test!';
# ^- p) c0 y6 ?' _ - }
& _( y) G3 t: ^+ d - }
复制代码
. ^- l' K: a5 I5 t" X无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码 + B( B% T, _# y/ q3 `
看来简单的把require理解为替换,在这里行不通。
, \" I5 V6 U t6 I I! q( v2 {6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
/ n8 u/ F, ~, N6 d& t# ~- //name.php
! b$ D" |" m5 k7 F) L& i$ r - . n1 z8 o N0 {! i2 I5 O. G8 |6 b
- namespace test\person;
; O' s5 B, b) c; J. x5 _; {3 E - 0 @$ X2 z7 H5 t N( i
- class Person{% { K8 F, P E
- function __construct(){9 e. w6 ?2 h8 n& O; D
- echo 'I am test!';
$ X$ p# R q: o, \, z5 b - }
; |5 H# T8 E+ L, x m4 E - }3 p8 z" X2 Z) |5 U, T# b
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 0 J9 {/ v4 R8 [" Q& C$ u' {
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
- C( A- A; f& ]/ G: A: |7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php: f. N; [9 h8 d1 `1 J
- ' l% U' E# Y3 c5 [
- namespace test;
, p, m( i! Y0 I0 L+ M. R - echo 'zhai14';; O3 C" ^; A, F
- namespace zhai; z% F/ j9 t6 Y! B( e; I$ |
- require './1.php';
复制代码
& y$ w+ C3 _8 B& Ephp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 3 U4 m: T& b9 e1 c* T! o' \( n
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。/ a4 g7 ]( x& a
- //name.php2 X/ Z" w! f) U" X) B
- + U* d0 c! O& x: q% t" J- N2 q
- namespace animal\dog;
" t- J# T1 y3 _ - ! h& M- E% i! P4 I% ?
- class Life{* r5 T1 ]/ c. V) r
- function __construct(){
; m# _7 W( `) a k% \9 R; ` - echo 'dog life!';
) }) x- d4 ]" `7 U$ f - }
* i: V- N9 T5 O% ~, W: s, x - }+ ?& C. K/ k6 i+ p( j# j0 p* A) h
" N% ]6 _% W+ U. ]- \; P. x2 L3 ] i) W- namespace animal\cat;
9 {, N1 X7 u( k/ ?
& N& J% ^; V a$ e6 W" T) V# f- class Life{
* T. p4 `1 I8 s) R. {) ~5 G- v - function __construct(){9 g) \1 q5 _ p/ H+ P' }" @1 t
- echo 'cat life!';" ]; z! o+ E7 f) _. p, l& l$ o
- }4 Z [( q% s M0 ~$ g
- }# {) V P* S( l
- 8 W# \" ]8 C8 y& f/ G4 ^
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间+ T/ S; r$ X9 H- w1 `1 ^$ l9 B
- new \animal\dog\Life(); //A
$ F0 M; P7 t" _' c S# h - ! V% G* n1 F8 c) h- F$ M( p5 |2 |
- use animal\dog; //a0 ?' ]( N( C1 c% }' f
- new dog\Life(); //B' C3 b H/ T( U" V
- S- w9 V0 \, R- T- use animal\dog as d; //b' A7 [4 X6 O$ E9 n ]: K
- new d\Life();
复制代码 - C5 W, Q& n3 U7 a
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
( I/ Q+ b: F4 G通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: + w d b# N" y/ m/ [2 F$ m
相当于
- l6 B; H, ?& }2.namespace后面不建议加类名,但use后可以。) |$ D9 t- M% y2 L7 P% u# F
- //name.php# c, ?1 t0 h5 d" n, j$ \0 x0 \$ Z o3 G
9 X9 P* J; n5 a4 K4 k- namespace animal\dog;
: Z \2 D* F; Z% W; r' F
* B" |+ x! ]8 Z8 n- class Life{, z& ?6 c& N0 k k; ~9 j
- function __construct(){9 j& J1 ?+ T4 e: Y8 O
- echo 'dog life!';3 B+ s; B( N8 e5 K3 m2 Q
- }& C' Z: B: j, I
- }
: K! Z0 a1 R- G5 M6 P - 3 v' X3 C& j0 v
- namespace animal\cat;$ K: O7 Z: a9 m) ?
- 1 d: r, G: P- _4 g8 U
- class Life{) d) j# p; R/ |+ n
- function __construct(){
( a3 c& G* s- s9 |, p/ W - echo 'cat life!';
% [& R8 g8 F- h" v* q {/ l - }- H. i( h1 j: {9 ~
- }0 _' {& n: B1 B( `& b- _8 O
) T5 d1 }0 u @9 ?. d- C2 U- use animal\dog\Life as dog; 7 `+ O: ?8 n% _. X
- new dog();
复制代码
2 E+ x# O; F* p) a2 [如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 8 h' ?8 i6 L% M& j
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php3 m- P; l4 ]7 s0 W# @. Y/ W9 d. I
' y2 X! y ]: s7 V% o4 U- namespace animal\dog;
7 p" A0 x% w: t% Q" i - % L4 h1 B7 q! g" {
- class Life{
3 Y7 p( }# [; d* t' c - function __construct(){5 a R3 m- A* E. e! C" s
- echo 'dog life!';
, e8 A' G$ H8 s% i0 L - }' L+ S5 _) u; h! f0 M3 G: [
- }
& T4 u: Y3 ?" ^8 H% x$ V - class Dog{
6 }) W3 ~- w2 }& H7 u - function __construct(){
7 [! Y K8 e6 `$ q9 u% N( W - echo 'dog in dog!';2 j/ K& \. T6 L: R# a( q0 c9 p- w
- }; X; b4 W- g% E9 d; E% B. R
- }, q% _3 H7 H4 v+ [; s& e
- # C5 h) N Z; O0 y5 ^
- namespace animal\cat;+ ~' u. B3 ]3 j+ {) l4 c
. q) v7 W# z$ N. p# H6 B( a* h; S- // class Dog{
$ T, L7 c& R, J) D6 q' h6 { - // function __construct(){
^, H$ c! n7 [. {3 J) ~1 V& n - // echo 'dog in cat!';
9 ]! |5 G" }, j5 U - // }; S# p; ~& ~' q/ J' x
- // }- @1 U6 U1 V. y6 Y! R" j
- class Life{* e6 u1 a' D$ C, A3 G
- function __construct(){8 G6 K4 v/ `/ g$ `- |
- echo 'cat life!';3 C& O: ~; _$ a% K% `
- }9 k+ A- \' q' T
- }5 N+ q9 a$ n2 i% P0 _ V
4 C& |) }" B$ W/ _5 @- use animal\dog;
8 @# @- ~- U( d [; @ - new dog\Dog();
复制代码 ! E b6 A0 @# Y' Q0 y+ ~7 h1 l- r
如上,使用了 $ _# S9 ~, r, q) s
cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
( \- F7 o( u2 C( d H5 t简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 3 P" i; R' R, V, N8 M [
' `' u: W- c# L p) V
! e$ M7 k+ C( [
$ d5 n7 A. j! p5 S9 \$ H6 [& Q
9 E2 q0 J6 y- B1 M |