cncml手绘网
标题: PHP命令空间namespace及use的用法实践总结 [打印本页]
作者: admin 时间: 2020-7-1 23:37
标题: PHP命令空间namespace及use的用法实践总结
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
( q! g `8 F4 T( ]: b
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
. Y/ u5 D4 Z# P+ `# R8 |6 e" c
& L* t+ u" [& K8 ]使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
4 f/ d# a D5 ^7 w3 A& `
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
' U E0 c( X) R4 }# d/ ^: q结合使用方法来进一步理解它的使用目的吧。
, {9 X+ s, M, L0 @$ Q: k4 A& g" m$ Q. g8 D
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写- namespace one;
5 f, I3 P) Y& ]3 O - namespace One;
( |: m! F6 Y h/ j" o - namespace ONE;
复制代码
# w5 Q: D! u0 X8 ]2 }; Z如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
0 w6 W; h! {7 m" [" v2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php $ t* V/ ~& Q& F: A* E
- class Person{
! `' I8 R" y- E - function __construct(){4 v2 j8 w1 u$ Z$ R) v
- echo 'I am one!';, E6 q3 b& J" f% C" k2 E% Y
- }
; R' B. q1 {" m x1 u - }
复制代码- //name.php+ @/ N$ C9 x2 W( Y+ b
- require_once './1.php';
u. L' [6 a4 y- h# E: i# ` - 4 o' _% D. s9 z3 g( C0 k6 J+ D
- new Person(); //输出 I am one!;
& _8 F. P* d$ x% Q) b% t1 ?& k - new \Person(); //输出 I am one!;
复制代码 7 U4 @0 o H$ J2 t1 \3 y
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
% u9 l8 Q. r) l - require_once './1.php';
8 O0 o2 l: F9 M7 @) t8 Y* M - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 ; R+ _. z, n( i
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
- //1.php w! d' f/ k: s# _0 s R
- namespace one;
, i7 D) t. @1 K9 A/ i) k - class Person{
- p0 p) G: \4 g/ H - function __construct(){
: Z3 K e6 u& f2 `& O `; C) H - echo 'I am one!';
6 {$ _ z* u4 X6 ~& q# V' H) R: a, x - }
9 n2 ^6 U+ Y; H' k - }
复制代码- //name.php1 b8 f- ?% T% @$ A
- require_once './1.php';
( l$ C) Y5 e9 Z' t1 M - new \one\Person(); //输出 I am one!;
2 w' R% B/ g; @) x b% y% e - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
# p6 {* @& t5 I: Q, K可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
+ m7 V1 ?* W1 y) Y2 D" H5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
4 i" Y5 ~+ @9 Z w* t) l$ \- //1.php 1 z% s" F- W9 ?9 y( `* Z, I
- namespace one;
6 w& c$ o+ Z5 Z& S) |7 h) g- {" a - class Person{' D' F: c' B b6 p% b$ H4 A
- function __construct(){' @6 c0 A# z+ X+ O5 @) P
- echo 'I am one!';
4 y' y, }0 x( I9 s9 x - }! r5 S; `: }# j* F j3 I8 A
- }
复制代码- //name.php2 r" Z9 g9 Y! b
- namespace test;
2 z% S; M4 |* c+ s+ M# E. |; x - require './1.php'; & N+ S0 G2 Z, ]. k# G
- new \one\Person(); //输出 I am one!;
" f- y. C0 z }# V8 A - new Person(); //这里结果会是什么呢,猜猜看
( w. |5 C( y! ~+ g2 V4 H- [) Z. Q/ U - 最后一行结果报错:
0 R' @' S" k1 l! C! ` - Fatal error: Class 'test\Person' not found
复制代码
% q5 T. _; ]% @" B. ?' J2 b4 ]
, _9 ^1 W5 W& N) j6 Z首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
' V- z& f$ O: O9 o# ] h结果报错:
- Fatal error: Class 'Person' not found
复制代码
+ u/ q1 k) h* g" J接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
- //name.php0 M# r I& E2 A* C( _( S
- namespace test;
5 x/ v3 d7 p2 D9 l' N! ?4 u - require './1.php';
, s* X& Z- {/ ?- I6 {/ e- |; f
, q- C' A. R* m- class Person{
+ \# h# s6 \4 S/ G* i* L - function __construct(){4 ? g$ U4 q- s* s% U
- echo 'I am test!';
7 h9 u) t) W7 b% ? C6 ] - }
! @. n! _5 S& | - }
- w! o# r& X' d# p. l3 R - , e2 X7 ^1 [5 _9 d6 g$ d+ ~1 F
- new \one\Person(); //输出 I am one!;
# U+ W' k8 B. \" @2 H2 H - new Person(); //这里结果会是什么,自己猜猜看
复制代码
& f/ b) g% P8 J最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
- //name.php% t- w; N3 e" {$ U8 q
- namespace test;
2 S9 K; i4 M. }( D U' d$ R7 m - namespace one;
2 ~$ Z9 @" G. r; n c( d - class Person{6 e7 M- y! o9 O
- function __construct(){
" i% C+ Q4 K7 K- {- B - echo 'I am one!';, p K- P6 H# T% B' n1 i+ ~
- }: u) W( X& c5 F3 ]
- }
( D% M; {+ H+ c
& _( P4 S6 k# g: j; k* |- class Person{
; P" \( J% |% u - function __construct(){
- z/ f2 G4 z3 n0 d0 C. @8 n - echo 'I am test!';4 L' q; S. c8 k" G$ N7 W2 c; C
- }8 |1 {$ a5 h" j2 j) V2 d. |
- }
复制代码 2 v' z/ Z3 Y6 i: i6 r3 P& J s: m7 E
无需new类,该文件就会报错:
- Fatal error: Cannot redeclare class one\Person
复制代码 9 ^" x* j1 H5 V! s
看来简单的把require理解为替换,在这里行不通。
, z- F. D3 x: t
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。" S O+ m5 j) |9 q* [+ p
- //name.php- j. g$ t9 _( x' ]
- ; [/ q9 J/ ~; h7 m
- namespace test\person;+ V7 l; K0 U3 e+ `4 b L k: A
$ C/ x6 z$ J- `! y# f( v" ]' J- class Person{, x) I+ O6 q3 e) @
- function __construct(){' A- H {5 Z* {- i
- echo 'I am test!';
3 t3 a3 q+ z q. E% j8 L - }- F8 u+ G' E. U$ ~+ F% a6 | H
- }" K1 K9 o4 a" K
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 / H% s; H* w( \3 F0 ]
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
" Z. ^' g2 b3 m1 |: \) a0 D8 S8 [7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
- //name.php( D6 a1 ~9 V/ ^; ]9 n
& U9 x! o& E y7 T- namespace test;
! g& \$ ~0 H6 _: L! k% m8 D - echo 'zhai14';7 V5 H: K6 \, ?! U& e4 \. A
- namespace zhai;) O! {; f Y$ `0 q* v
- require './1.php';
复制代码 8 N0 R- ^2 t1 L9 d2 @# E
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
' F5 R! Q: Y! V# m z K
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。/ s; s* K* ]! k: B: a
- //name.php& O1 m0 }, G1 f; \
) e) L# l+ {1 x. P7 R- namespace animal\dog;
, `8 P% K8 F5 N - . T' H9 H6 V2 q; s# I
- class Life{, j; N4 v2 f/ U+ h( w( h
- function __construct(){& m! T2 }% ^* _2 c7 J
- echo 'dog life!';
% {0 O0 C5 M: {% H - }8 w _0 I6 r3 O
- }) r6 ^7 Z. v" a, E, U; \
- 7 p: q8 J2 J. Y/ D' n
- namespace animal\cat;
0 l# R* p- L L r# s' y# p$ |
- j, A$ Q% ]& t- E- class Life{' s d8 q& w8 F' x
- function __construct(){/ h' u8 r1 s7 g" o4 X9 K
- echo 'cat life!';
) G' R- l6 p0 T - }0 A$ @; u! p* k( }/ n! {
- }) h% \1 q( ^* F
/ H" N0 Q. ~) A3 {0 }4 O! d3 Z- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间/ ]; R8 i3 }# N8 K/ a
- new \animal\dog\Life(); //A& Y" P( k1 |- K
- + G, t8 X s7 F$ T
- use animal\dog; //a: ~5 @, k; M5 q1 x) C
- new dog\Life(); //B
I) X9 z% J# R/ h, L: C. f) _ - 7 [9 W5 \( g t2 |
- use animal\dog as d; //b9 K% `- D0 C# d; W
- new d\Life();
复制代码 3 q: _) F6 m% \& G( J
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
9 G4 ]( p2 T7 M( m) @
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
7 v; x& N- u1 E, \5 c3 p6 T相当于
7 R# ]. F+ S2 `/ R8 s
2.namespace后面不建议加类名,但use后可以。8 v y9 S: k( f4 `& ~; v
- //name.php- ^" L2 s, |2 e% [2 i& B0 G5 _, P( R4 z
8 U" G7 t* d, i! R, t: q+ e- namespace animal\dog;
, ?/ m4 Z" X5 @. `0 `
9 E9 o' _, l) [1 C- class Life{3 D9 b' A) t/ y3 M* _2 Z
- function __construct(){4 u* o6 @9 J& u
- echo 'dog life!';
+ S$ _+ v2 l. @2 k) L K) m - }
1 y. P. Y* y* Q$ [" a: L1 h - }" X& U, }3 h* k+ f6 C
- " ], N$ T1 Q$ b- W; G1 @2 D t- u
- namespace animal\cat;
$ f' B) G' h9 ?. \ - ; g& D7 S; P) w
- class Life{# E. h" P$ A" E! c2 f0 |, `$ J" E
- function __construct(){: J5 I1 o( g$ b1 X
- echo 'cat life!';( F* s2 L+ w* F! @4 }3 R- W5 x
- }! l* I( ~& i4 {+ K5 v3 ?
- }
?( H' b: E# D* u1 @+ N9 ?
) p# O! J$ |) c% p- use animal\dog\Life as dog;
. C; r6 a4 D, g - new dog();
复制代码 ! `8 D( j4 r' _* K' e, F8 H
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
- Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 U: \- f6 k. y* x, j0 r
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
- //name.php& V6 g* `3 i' G9 [( G
: z( l2 [. [6 X ^% N$ P8 W- namespace animal\dog;% t) x8 Q( X' _0 M2 p) l: `
, ]( P% S- `' i2 [+ V- class Life{
+ ?% @/ s0 D- C2 w3 a$ B, \ - function __construct(){9 @6 I w( Y& |7 `& t5 |1 L
- echo 'dog life!';9 D" b9 Z0 N! t8 [4 d1 q8 R$ l" s
- }. U1 `" j) {0 c! L. N
- }
5 Z9 l P- g# s6 u3 ^9 h- a - class Dog{( g$ r- E @" y- S% E
- function __construct(){( m% I( d O9 }1 r: {$ @+ R
- echo 'dog in dog!';: V w) }5 d, r
- }/ d! ]7 y6 \# Y
- }
/ T6 @: C+ G& ?$ d
% z: Y! [& i. C2 t- namespace animal\cat;2 b9 |6 o7 I3 L) ^( b3 w
- ! U8 m8 w. b4 ~3 d* D# W" k
- // class Dog{( ?$ K" u$ z4 K" _
- // function __construct(){
0 w3 p, s) P' l- M5 d - // echo 'dog in cat!';
# d% X+ F6 L9 n5 P. X7 m - // }& I2 U# g& j5 g0 ~4 f( w5 b/ j
- // }, B6 Q: g$ n3 k9 s# _
- class Life{
) C4 C" }( Z8 `, v0 u" r) {( I5 r - function __construct(){
" u& S0 G0 |+ V7 c$ W( Y - echo 'cat life!';# K$ o! w5 ], Z' O, P2 |
- }! {% m! g5 f9 [; S# n4 n
- }- P! X! y+ G) X. ~. h+ m5 M7 ~
- - D O9 |9 w0 s8 u
- use animal\dog;
8 M) ?* i# u* k6 O8 T9 @/ x6 i0 F - new dog\Dog();
复制代码
0 b/ M0 a3 W* r6 y3 U" S& p) A如上,使用了
k& L, ^! r3 ocat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
7 R0 g( B. L! A简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
' l& D7 W A* Z$ ]$ p
* ^! K. n3 H7 @* [
; L t! Z: ]6 G) Q0 T* F2 t8 q) r
. j6 \3 B9 O$ ^+ m; F0 H1 ?8 @) h$ @6 s: j( {" V0 C
| 欢迎光临 cncml手绘网 (http://www.cncml.com/) |
Powered by Discuz! X3.2 |