cncml手绘网
标题: PHP命令空间namespace及use的用法实践总结 [打印本页]
作者: admin 时间: 2020-7-1 23:37
标题: PHP命令空间namespace及use的用法实践总结
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
% \! q7 R6 T; Q5 _
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
w$ h" L1 a" C7 W; D K" L0 @8 E- q
3 u( k( |- ?! [! `. B使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
' O) _8 u7 T: m据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
9 e/ J% y/ j- V$ W& q' A$ B/ z" V
结合使用方法来进一步理解它的使用目的吧。
( J5 G3 E p3 z* d1 t
) E- @# m/ {' Z# o0 knamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写- namespace one;- M' H% r; {9 b6 B& [) O$ V
- namespace One;
: T9 B, s1 _7 V( q( _ - namespace ONE;
复制代码
+ x+ i: b" X6 \$ m4 ^! g如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
" v1 H- u( a' }+ T
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php $ l" M( O6 Q' b$ I Z! G( _
- class Person{
v2 [2 F. P5 N/ c - function __construct(){0 D5 D2 v8 i* J* U2 J1 W/ E' y$ @
- echo 'I am one!';$ F- ]4 P8 | Q( g; h
- }7 }! J' a; ]5 s3 ^7 ~8 l- G
- }
复制代码- //name.php, G( P5 |1 O- l8 k! J+ x6 b
- require_once './1.php';7 Q7 n4 \& ^1 A8 o3 R( W6 j. M
( j+ l# b6 w2 {+ W. O E" y/ l- new Person(); //输出 I am one!;: | p2 l3 X0 o5 Q7 f2 }/ _! v
- new \Person(); //输出 I am one!;
复制代码
$ l& ?6 l: |/ X+ l0 M3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php* V, _. Q, Y! P
- require_once './1.php';
4 \6 w: Z- y% Q7 c' e( o) h5 ]8 q - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 " h: M* T6 b0 b1 L) }6 Q& H
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
- //1.php
4 _- r! g6 S( G, ^- |. l - namespace one;
# A( W( B: Z( v# v( } [9 k, | - class Person{ B J8 j- l! o7 N. D
- function __construct(){
: i0 i3 j2 t6 h- q, S0 Q6 M# s - echo 'I am one!';
0 l% p, f$ U7 I3 ~# }9 Y3 Z. i8 E - }( z/ [( q/ m% g3 }1 h# M I0 D9 v
- }
复制代码- //name.php! I. K& r9 c, Q4 r2 v2 s
- require_once './1.php';& W- B: E/ I4 C H
- new \one\Person(); //输出 I am one!;& I, z4 Q$ m0 N
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ) |3 V1 q% ]6 p/ a8 G
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
$ M6 O% k! ?8 l- R5 w0 Z$ z9 R5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
) s5 Z) K! Q3 r& T- //1.php
" D/ x( H( f+ Y' q+ r6 K - namespace one;4 r- n- e% J1 c9 ^2 m8 {
- class Person{# s( o: ]( M/ ]9 ]
- function __construct(){
8 X. t- u9 l; l+ j) X - echo 'I am one!';! n M; I: T& t7 ^! q$ j
- }/ c3 }& V" f7 Z7 }; w
- }
复制代码- //name.php: M5 n; z) i/ _) ^2 F
- namespace test; R* y) E3 q; s5 g* }; Z1 ^
- require './1.php';
, ?& f4 b p. E7 K& ~5 N - new \one\Person(); //输出 I am one!;
2 N \+ ~8 w3 B- \! R - new Person(); //这里结果会是什么呢,猜猜看- F6 R& x/ {- t+ B" Q/ k+ c
- 最后一行结果报错:
7 P' g2 C. P5 D# F+ C6 N' `5 L8 z - Fatal error: Class 'test\Person' not found
复制代码
+ C- Q) O1 ]# I4 m$ _" R5 P6 R, \/ }
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
3 \8 p8 y9 p4 O, P结果报错:
- Fatal error: Class 'Person' not found
复制代码
' u3 M, o4 \7 e接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
- //name.php+ b6 W; V! H! \+ _# ]; d% Y4 S0 j
- namespace test;
, ]! N: ?% s( S9 n1 R& ] - require './1.php'; 6 Z+ `& H& L6 t9 n6 d
2 B* d8 Q3 z8 M" w- class Person{
) Y" G' H7 Q% U - function __construct(){
0 V# }3 @. K, q6 H# f7 p8 M% F) A u - echo 'I am test!'; x+ E1 x" Z9 d/ `* I! _
- }0 Z0 b( O+ s; M. N. E) J
- }
! G* ^* T6 y. H( e$ M' ^( r
6 a! W& S3 }) o9 ~" p/ B, f; D- new \one\Person(); //输出 I am one!;$ B ?4 O' G. V8 f
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 3 ?9 z& E6 F# r
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
- //name.php
2 t! B7 n! Q* ~) R4 N @ - namespace test; _) o* k, l7 k; v
- namespace one;3 o; [0 @0 j" y. K( Q& }
- class Person{
8 ^ K' x8 k0 \9 ^( D, |7 t - function __construct(){6 X# r$ u& E \" f* S/ ]# A
- echo 'I am one!';
& P! n3 D4 C" b/ c, ~ - }
( Z/ Q5 n }7 L; d0 y* _8 v - }
; A7 t; d3 r( D) g$ Y# V2 a* R - 4 i- n4 R4 d( x6 p& F3 y
- class Person{
8 ?7 Y7 H0 A4 L i5 c& K) @. H - function __construct(){2 G* j6 S) _% j) @2 T5 \. e% K
- echo 'I am test!'; j2 J( `3 z5 ~2 Y$ R: X
- }
s& o5 Q( o1 h& Q& A& t% } - }
复制代码
& k8 i% h9 m3 I0 y4 L4 V3 U无需new类,该文件就会报错:
- Fatal error: Cannot redeclare class one\Person
复制代码
" _$ U" }# j2 I* Q( y8 x看来简单的把require理解为替换,在这里行不通。
' |+ j H, U! A( e" N% ?6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。0 A3 a: m0 k4 Q% R2 O8 J' t
- //name.php
( O+ A, l2 V6 O5 n" a3 B2 j6 ]# { - 8 L7 e" C5 B" z' f ^
- namespace test\person;$ K7 Q+ m6 U, @, t
- & y. z# Q! g: a- K ?$ t
- class Person{( u3 }/ G- a8 m* a, h5 F; y- u; m
- function __construct(){
! j% \5 i$ z8 ~4 N5 i) ` - echo 'I am test!';
* [1 M5 O+ u2 X - }* @, X* _* M4 Y% V b, r
- }
4 f4 [3 Q# P3 V1 R1 V: m - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 3 y: z K) q% v
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
# k. n) T# i% l. B" V. X7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
- //name.php
; C5 j" F4 M/ E3 L; R/ q# @
: P! v" a; M8 F; r1 Y& W- namespace test;, t& W3 P" V7 q y
- echo 'zhai14';
- O( r4 }' ~. v# E5 p - namespace zhai;
. y2 ^, M3 m$ b7 A- n! ~: s - require './1.php';
复制代码
4 u+ E8 d/ m& D. g. f2 p, Pphp命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
3 b9 }" k$ P4 S. B6 C2 A4 h
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。* ]8 Q. c! {( I* ?8 f; T% I
- //name.php8 B. M3 N+ [( p& \
- : v! f0 |3 d. I* I8 m: @
- namespace animal\dog;
G* N# l9 w$ s7 \4 \/ G
; q8 H( X9 i( m2 a8 ~8 \: v' z- class Life{9 l! h: {4 C+ d3 u1 P* O/ d
- function __construct(){8 e1 W- ~; h3 T
- echo 'dog life!';
6 T7 B- `. \' |" S* Q. t8 q - }
1 N/ t$ V6 w6 s; Z8 p1 n - }
9 m7 O9 }0 a# i2 a - 1 t4 i: L3 r7 A/ e- J
- namespace animal\cat;' U$ _) o6 |" m" W/ M
! t6 `+ p$ W4 u; J% d- class Life{' Q9 Q5 w+ Z. t: \1 |) t3 Q
- function __construct(){7 N' ?6 h; p- |% q
- echo 'cat life!';
' n+ `1 p3 |- ~, L. I k - }% O- Q5 w+ C2 ?/ n& o- }2 X$ u& |
- }
( d. L2 d u+ d" R+ Z
7 H+ \ ^. _: o6 t- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间0 c, p' e/ |# R3 Q: B
- new \animal\dog\Life(); //A
$ y- l$ B, p1 N9 A
8 ?- K& v* m- u0 N0 i- use animal\dog; //a& }& _/ q% M: _: O/ A4 ~; u
- new dog\Life(); //B: H9 {% n3 l" i$ H
- 2 H( S4 D! h2 ?1 x0 k& U
- use animal\dog as d; //b
; D' O$ { O: N7 E - new d\Life();
复制代码
E# [4 q4 S% Q v" Y通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
' V0 ]9 P/ N6 N! g" b& ]* f通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
/ A. n ^' d* N. S8 Y L7 E
相当于
, t. R: D; i( Y2.namespace后面不建议加类名,但use后可以。
' N7 j/ A+ s( h- //name.php
: {+ W- L x( l& ?5 H7 [) H - ( [% p8 O- y; _; {; P/ X
- namespace animal\dog;$ V; W4 `. \6 @- D+ a6 E
* f7 P% I6 @3 ? Y$ v- class Life{
+ j/ u7 H$ b2 x: ~! R1 \' F - function __construct(){
- ~5 \3 L" Z1 f3 w7 |- ]+ D' } - echo 'dog life!';/ G, |4 r1 G" R8 v5 y
- }
- u# M4 y/ t$ C7 R; O% i+ V1 z - }! V+ x+ _: Z8 L* E0 n6 w# X& F0 `
- ) B9 |- w' V3 B5 A7 L- v( v
- namespace animal\cat;
' m) ^' [- w5 e9 f - " U& m! F. z6 q
- class Life{/ Z* y; U. ^4 `
- function __construct(){ J$ u. `4 R8 Q1 U8 m7 ^. H; c
- echo 'cat life!';
9 \% o5 }7 }" L1 ^ - }0 w, k2 H8 x* L! y6 o3 E9 G7 D5 @3 T
- }; v& _/ @7 u9 W) H" ]/ O7 Y& p2 Y
- . Y+ d, X. ]) R8 f: K( l
- use animal\dog\Life as dog; ; z# Q6 x# P$ z$ n2 S
- new dog();
复制代码
5 I5 K8 }; L6 Q) J0 J+ N如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
- Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
+ Z+ R, ?; T3 M' Q% J$ j$ S' g: K& w) C因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
- //name.php3 Y+ y+ ]; \' l) r) o x8 v) I
2 F2 u/ X( v* a- namespace animal\dog;+ [/ v; T* S! w
7 N$ z/ K8 \3 {3 g& |; G8 z- class Life{' O* p' y$ w. ]! a M. K( T
- function __construct(){% H7 J9 f. b7 l
- echo 'dog life!';7 p( K; s" p. {
- }
( `% W% u. S h+ B3 I: H7 F* H3 o - }
v6 x+ ?# v1 o7 G2 `! v - class Dog{& ^. R& }% t3 z& a! O q
- function __construct(){
6 f' z- H- O$ d0 K2 R% v: B - echo 'dog in dog!';
7 Q$ g5 ^) o# @* t8 \ - }* {- r1 R+ z& }4 Q
- }
% g# X% H+ g$ C/ Z- e" U5 R$ a - 8 o1 l) e) u3 O( C, |( B' p
- namespace animal\cat;- P6 F* y. p& P) r1 h! K; P: a
- ) u/ d6 X9 I+ B7 A1 ]9 s$ R
- // class Dog{
& l9 V6 |6 z+ G# X6 ? - // function __construct(){
+ Z. b. H1 s" g: c$ o - // echo 'dog in cat!';
. c9 K* V& _) n5 g! P/ W* r - // }2 o3 {; o7 J( P3 M" d7 X
- // }
8 c! b5 \' Q' q- x - class Life{' S: h/ y' K$ Z# r% R4 A; b D _0 J
- function __construct(){
3 K8 |1 e/ X1 N; r1 W# y - echo 'cat life!';/ j3 j, n' q+ Q8 _
- }
/ N) P1 H, G# c, Q" d J - }
, X% q6 }% Y) M9 W
: |. E7 ?4 U9 I+ H( W5 [- Y- use animal\dog; 8 o' c! F& J& ?. @. R) T
- new dog\Dog();
复制代码 + O8 D8 A0 b) J1 z9 X# D/ U% ]' T
如上,使用了
5 d A% `# w" d5 b% @+ J
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
+ g. `; U( p+ ^, ~, G# v0 C
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
& D6 ?+ J' ^0 n. r+ D4 N% M) G" K3 M! t' V
2 ]2 F! F; q- Q( f9 p
* ?' R( G6 S& ]; J8 M! N% W
9 F! d( J6 ]2 [
欢迎光临 cncml手绘网 (http://cncml.com/) |
Powered by Discuz! X3.2 |