cncml手绘网
标题: PHP命令空间namespace及use的用法实践总结 [打印本页]
作者: admin 时间: 2020-7-1 23:37
标题: PHP命令空间namespace及use的用法实践总结
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
$ g, T1 K* P7 P' F; |
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
, G. Z' A4 B( f
8 `9 @' P* o/ w; s
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
. _/ ?! |5 P- v& h9 @
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
/ H3 f3 p2 n4 S |3 {, P结合使用方法来进一步理解它的使用目的吧。
' R7 t0 h, q% z8 B3 C( D3 v) z5 Z5 s) o$ Q5 `
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写- namespace one;5 Y1 t' z: {( \( T0 u3 u
- namespace One;) F- c: O& ^( r9 ?# L% O! L$ R
- namespace ONE;
复制代码 ( R2 x7 Y7 T% P& q$ h' j
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
. T% c4 k! q1 Y+ }* ]
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
% a; K, [1 V! I- j. w% E2 W# \ - class Person{
/ h, k) `+ t H4 Y - function __construct(){' ^( R- p' B9 M# {
- echo 'I am one!';$ O& Q7 o; _7 i; `: B, ~" w
- }
! c# h! |. e7 Z9 H) w/ A R - }
复制代码- //name.php
5 y' S/ p5 E, c, Z; e - require_once './1.php';( N% Z8 b- p/ y. W
- 3 S) @: Q: k+ R# m, k( k) h6 V
- new Person(); //输出 I am one!;
$ V3 r s) ]3 E& y3 X1 ~$ b$ ^ - new \Person(); //输出 I am one!;
复制代码
7 {8 W+ v. d1 @$ v3 a3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php; _9 @, b) I+ K3 y
- require_once './1.php';
( e! g* n/ Z% I0 c( z0 E - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 ) I& H, t d& H
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
- //1.php 5 w6 ~1 w& ]2 H! L
- namespace one;
& t! t) B& d, q; P2 {" A b0 R - class Person{$ m# Q( Y7 ^! u6 X. \* ?
- function __construct(){
" h9 L# R% k, \ n6 V2 Z - echo 'I am one!';
5 x5 u; K: J, l5 w9 a+ P. J - }' {: b1 L9 j8 n; A" K6 e: X
- }
复制代码- //name.php& C1 Q6 G0 r( Y
- require_once './1.php';/ b9 L9 o' V8 _: M9 ?! H6 }
- new \one\Person(); //输出 I am one!;
: u4 U+ c$ X" M) O9 ^3 ^2 c( u/ T - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
' d4 P! P& r- D% K; t' J7 f/ ? u可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
/ z% i& b( M5 c* n# d5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。1 } [* Y( `. q! h0 N! B
- //1.php
8 ]* z: E0 O. \7 c3 ` - namespace one;
4 w& L9 z, U7 q - class Person{3 S1 r8 w' ] @/ T% a# j3 D
- function __construct(){4 o2 L/ _6 f, C. R# {" `
- echo 'I am one!';% w- q* w! ? u; i- g9 x5 t
- }
. k. l" T" `, U+ Z% X- }/ O - }
复制代码- //name.php
$ g& }0 q+ Y7 ^% \( q& s. O2 H' c$ ~ - namespace test;
- G" Z$ Z% J& U' z - require './1.php'; 1 `' I$ O$ G( K9 B$ @
- new \one\Person(); //输出 I am one!;6 b- m7 n+ z- X4 z& j+ o' t3 \# D& W
- new Person(); //这里结果会是什么呢,猜猜看. R8 l p/ I7 R' m7 `% A$ V2 o- Y% P4 I
- 最后一行结果报错:
( h# ~- G4 y# d! G' P2 @ - Fatal error: Class 'test\Person' not found
复制代码
* b* l9 K/ ]# [, X9 j3 D8 Y' o1 K' k% G8 A: P" ^
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
1 ?: X8 f, @6 ?$ l) |
结果报错:
- Fatal error: Class 'Person' not found
复制代码 5 i4 ]* Y. y+ h! A3 w" p
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
- //name.php
* e! m. S/ U; X5 W9 v7 O - namespace test;8 B% n+ m/ K6 T
- require './1.php'; , `7 B& N4 F0 y E% E
1 `: @8 z4 @) X$ {8 R6 i- class Person{1 x" m/ O3 r" f7 {! A8 {+ d
- function __construct(){
1 @9 T7 U: F8 W8 U9 }8 v - echo 'I am test!';
- X+ I H/ I- Q$ X% n! l1 ] - }
* ^4 V/ D/ g& f: Z. F) C - }
: _9 i U1 n4 `7 t - : q$ e$ e& o( f% w8 m+ M3 O' I5 [
- new \one\Person(); //输出 I am one!;
7 x2 M' w8 u- |5 q1 y- R - new Person(); //这里结果会是什么,自己猜猜看
复制代码
! r) }+ v8 \9 X, C! v7 `5 l! [# P最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
- //name.php
+ b1 d& s3 a4 _ }7 |) R/ A- K) O - namespace test;" j; h/ k% q0 f3 L" X
- namespace one;
* G/ `$ d$ E' R, V6 x - class Person{; u- j4 x3 z% I1 g
- function __construct(){
& u0 P1 X, ]# _ T% T; ? - echo 'I am one!';
+ G+ j, D6 x3 }8 }1 c0 _ h$ m - }
, V: Q/ v" I/ ?, m: |3 | L3 R - }
0 u6 D, H. a0 n5 e5 l% N; d - , r% k' w7 {0 V4 b0 F
- class Person{
5 w, c9 L7 r! |: D+ l, {3 H - function __construct(){
& O( @7 w& _. |/ X/ q$ L - echo 'I am test!';
+ f0 ^. s6 Z/ Q9 v - }( I$ d) H |2 o
- }
复制代码 7 j* z% H1 b) T
无需new类,该文件就会报错:
- Fatal error: Cannot redeclare class one\Person
复制代码
& t- O! I: ^! S- r m看来简单的把require理解为替换,在这里行不通。
8 f9 B( H+ _1 t N" L0 C4 ~; m6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。 w# N& l( w* S0 B* o
- //name.php
% v* H# Z, P. h* X1 T
* H ~4 S! K( W( Y" x; s- namespace test\person;
0 J, A6 Q+ ]. b& f
! b( o+ w$ A8 j, S9 s! y w' e3 X- class Person{, ]. n+ Z) _ k5 T" C, o
- function __construct(){
! T! @* u X4 d. S* z/ w" b0 p3 e - echo 'I am test!';# L2 x$ [9 b7 ], Y
- }+ S- {. `# ?7 j% q* U' P% ]4 i5 D! o
- }
& L, U$ m# z8 Z; f4 E. t" b9 h - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 " H# q7 n4 j/ f5 T' C) C0 A
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
! c4 v1 L* z( k% e8 h' c0 V7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
- //name.php
+ q- _+ ^9 z4 p x& ^# [: M! g# d3 p
- @; Z, ^$ Y0 `1 J) @2 |0 ]- namespace test;
% Q+ c9 L1 [6 N2 l+ a - echo 'zhai14';+ G9 h. p, p: X. U- e; P
- namespace zhai;5 ~) M3 ^) Y3 K8 H* x/ h
- require './1.php';
复制代码 " Z/ Y2 E( u6 _7 W# R s
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
4 I1 {8 A7 ^/ ?use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
0 I/ u7 D" [# d0 m1 I6 T; Y+ f- //name.php P9 o8 m4 S5 h! N. H( O
- 9 ?6 z$ D" D6 J' d: v; x
- namespace animal\dog;: d4 E. g8 C0 r2 e A7 ]! L$ ~4 M
- ! k8 Y2 P' t, u+ }0 d
- class Life{
. g/ h# q0 _- |0 Z" Y( k8 O" p - function __construct(){2 {; U% M, t5 |7 B
- echo 'dog life!';
- K3 p; J; m, e4 g" O5 S3 n - }& |+ o s9 V2 i& ]0 \) p/ y
- }
" N2 s A0 n1 L8 o9 W - 2 j$ g. M J9 b! z3 o
- namespace animal\cat;
+ {3 q: S" t- i- z/ L: j, O! O+ E7 a - d0 b' V+ @7 Z0 I9 S; H0 A
- class Life{
; M8 r: H8 r2 J2 d0 o6 ~; U - function __construct(){' r/ w0 [4 n5 D2 T* b
- echo 'cat life!';
) g- v% U; e; d2 S. d, ^" w6 K - }
- [/ n3 ]9 |/ d( X! L - }
! R9 ]; ?$ L% @
2 U- c4 `4 ?+ F; R, O* [: y- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
# r* e M# ?6 ]( t2 t1 N - new \animal\dog\Life(); //A' B3 G% H" T- v2 C0 a& N( o% L
, C( X6 d' n3 Y- use animal\dog; //a& z1 H' }, E( R" r
- new dog\Life(); //B
, |( E" q' H2 z4 ?* `& u; p
/ R/ x4 f: M8 c. |7 I, _+ {4 b- use animal\dog as d; //b
& t0 g5 U- F3 O - new d\Life();
复制代码
6 N' H* X1 I( E/ O通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
% Z' W. q% h" P5 G6 H( Q) l
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
9 ?" Y: y h- {( O相当于
- p% o# [. p2 ?, A: A2.namespace后面不建议加类名,但use后可以。7 q2 {% l; ?3 Z v# j, F8 t
- //name.php
4 a& o: S) I2 u - 9 \2 L9 O( h# P5 ?
- namespace animal\dog;
2 U. j' O2 G. G3 [8 [6 @1 n9 r - ) \ _7 X( {) l3 }" \
- class Life{/ a+ ]5 F4 {" D% S
- function __construct(){
& W4 U4 K% u: |7 A, P - echo 'dog life!';4 {1 S5 R4 i% I
- }
3 \1 I8 o: @# J4 x# V N9 Y - }8 E- E5 b( M/ U) x- |
# L$ i+ i$ Y- s( g4 N- namespace animal\cat;: X$ \+ l: v1 Y4 g0 ?) R
- ( [$ k: i% W5 Y! t( M5 t) F
- class Life{* B4 d" q' Z, B& o0 O8 @
- function __construct(){6 `- x Z4 j) h5 s# t1 C+ z3 ^0 \
- echo 'cat life!';* [5 q. ^' U, U( s! V8 ~- x5 Y/ c
- }5 l" X4 G3 {+ n/ d5 Y8 U
- }" T4 p* P4 e" k, g+ z. F
- - u5 c" a: T. y1 ?6 b( E
- use animal\dog\Life as dog;
9 J. @# V$ I+ h# _' ?0 @ - new dog();
复制代码 ; A7 @ o0 X; v& I+ B
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
- Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 7 j4 H) Y; w- ~; ]$ _( |; n' _8 h
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
- //name.php" d' o2 L) V1 ]! A
- 1 w ], |% `) \- N3 s/ c
- namespace animal\dog;9 W* w6 |' g* X/ V# @) w9 R
B$ v5 H8 }- {! ]8 l" q- class Life{
- h! i; L9 \) G1 ^* c) G - function __construct(){
9 @, R# i1 S" n8 h% x - echo 'dog life!';
1 t1 J. V- O/ |; b" r - }
% k. q' @1 ]! B# ]+ N - }# T3 }0 Z" T: J
- class Dog{3 D4 H6 X4 e" i. E; O+ ^6 ^: q. j' w: T
- function __construct(){
; q+ E) m3 p/ f6 \( I x; K3 H - echo 'dog in dog!';5 y t, b. _. F) h
- }- ^2 t0 H9 U4 J: k
- }( n/ Q4 z, K+ K$ L& q# Q$ y
- 9 c0 M# j, \) @" a: B
- namespace animal\cat;" M- Y1 [+ X" k- @. a
3 z( @3 n5 F7 y- // class Dog{
. G( ]; P4 d6 |. \7 K0 V - // function __construct(){0 ^3 R \/ \+ k/ E o9 M8 [3 A2 r
- // echo 'dog in cat!';3 g& j+ C, t$ b! [4 _/ K* m
- // }2 n" z' \ {% `# h
- // }% R& Q4 e1 w% ?
- class Life{/ x* B+ c* L5 E7 e( s
- function __construct(){% h& @) k. O+ x; _) h w* w" Q. G
- echo 'cat life!';
& A5 P! v9 m2 p8 X - }
9 G' b7 B5 U3 M - }
) A5 k0 n! A6 A8 H0 M \ - ( x6 o' L( j- g' d7 ]
- use animal\dog;
0 W8 T' s7 D, A/ L9 w - new dog\Dog();
复制代码
" X4 I* t5 j% P8 \* W0 {如上,使用了
; B3 b0 y6 U+ m! a+ L9 h
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
0 [6 ^0 W1 }! l. d
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
( ~9 B# ]$ U% y( [* f! \$ P9 ~
& _/ Y7 o7 R% b( Z X8 d* {4 q$ r- G& `& c4 z. r
: r# X3 n- t. u* @- r
8 Q9 q9 K% n- j) p. d& V
欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |