cncml手绘网
标题: PHP命令空间namespace及use的用法实践总结 [打印本页]
作者: admin 时间: 2020-7-1 23:37
标题: PHP命令空间namespace及use的用法实践总结
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
" Y8 C3 P$ H8 _7 M8 r
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
, P- u9 ~. n, l& n% I
3 t! m) I1 ~ G8 Y" N* ?1 A+ x
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
; B, R8 K+ o; d4 {: y" ~" n* m
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
. J2 s9 _# ]0 u结合使用方法来进一步理解它的使用目的吧。
7 t, g, V: Q- Y+ ^; C
& G) b! R1 E I% G* ynamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写- namespace one;
& h6 h* P: ?7 R, ], H - namespace One;- D8 R" I5 X, }8 P5 m$ Z) q& \2 V* S
- namespace ONE;
复制代码 # K7 N0 N4 |( N1 p3 K" G
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
: J) |; e, c8 h& e2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 3 }0 k; p- r( Z" J, o
- class Person{
/ C& K" S! g! k' W/ ?& e - function __construct(){
* x$ s; t" N: G' R' ~ - echo 'I am one!';5 P% A6 R1 J6 L
- }
: N. J/ ~# e- l+ {4 ? - }
复制代码- //name.php4 \/ s/ v) ?5 O2 t1 t) I
- require_once './1.php';4 i3 a0 B: ~* S( Y3 E
0 z$ ~3 s; @3 |$ T9 r& u9 O; u- new Person(); //输出 I am one!;% C0 G+ w2 V B4 o
- new \Person(); //输出 I am one!;
复制代码
+ ]+ V* h2 @* g7 x4 @4 z9 O4 J% ^3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
5 v: k/ f j* K9 M# X - require_once './1.php';6 j+ T( L: d. D! [, i
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
$ S) l4 c9 t, C7 Y7 G' `/ L; `. S4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
- //1.php
# k" f$ K2 m0 b! f7 f7 Z - namespace one;
' H: t( `1 i2 _ K - class Person{
) S( A/ {& u6 D% d - function __construct(){7 U5 g- y, U2 M8 [2 F9 J. u/ j
- echo 'I am one!';, a! e+ a6 d) i2 @4 _/ E" R
- }6 }# c# X* W- u7 y
- }
复制代码- //name.php8 O* \9 Q+ Z% c9 B) r
- require_once './1.php';; F; u0 ^6 }$ @1 ?- u! E; s, q6 ?
- new \one\Person(); //输出 I am one!;3 z) J0 S, a- T; X
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
4 P: I, w9 A+ c- _5 e0 C4 K7 {+ |/ o可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
' N9 M' k; o1 A$ I1 C3 C8 _6 B" [
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。3 g2 J) |& D1 h- W2 {
- //1.php 9 X! \* `, _# o1 N8 E6 Z2 i
- namespace one;8 S! N- I+ H2 K7 A4 D
- class Person{
! R5 c- R3 F9 |( G8 `" d - function __construct(){2 e1 E8 M9 b6 P, O! f4 C
- echo 'I am one!';# i; q8 x4 B# u8 F
- }
5 ?) U* A! F; {6 |) w% W; l( ~8 N - }
复制代码- //name.php& l' V c, W( ]8 A5 Q+ u y- X
- namespace test;
5 Y$ X0 `2 z; S* W - require './1.php'; 1 L" j9 c4 c$ C6 J
- new \one\Person(); //输出 I am one!;$ j) n. S0 ]' u5 l% \* \/ n7 }1 m, m
- new Person(); //这里结果会是什么呢,猜猜看
; h# U: |- w o3 m5 |9 t3 c5 ~1 M - 最后一行结果报错:- J5 S4 j1 N8 W! T3 S
- Fatal error: Class 'test\Person' not found
复制代码
4 z: R2 E9 b% @# K6 T4 \: v; ?/ W" t R( ]0 ]' Q S6 p0 I
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
' e) T1 L( H' s0 s6 O! |结果报错:
- Fatal error: Class 'Person' not found
复制代码 0 `* `* F% T& N5 o$ m; p
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
- //name.php
: V; z, @: H, V# I! ~ - namespace test;
1 Y! m) J! O+ G# W b4 p - require './1.php';
! X7 k- d3 o" b, U - - }; G+ Z: ?1 p* M4 f; s. a+ ]6 Q1 E" E
- class Person{
: B4 Q: i- _; d - function __construct(){( `, H7 Z( i9 j* \9 ^. i
- echo 'I am test!';
2 C! h1 V3 C y3 R - }; [; p& |4 V/ {, i
- }
8 m D9 k) j" Y9 v( a% t0 Y# h$ j - 2 u2 Q# ?1 x7 |$ s, v
- new \one\Person(); //输出 I am one!;
' X( K) G5 ~ g: w: ~: `' M - new Person(); //这里结果会是什么,自己猜猜看
复制代码 1 r2 N" s# J. ~" l @) L# `
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
- //name.php5 V4 k0 G$ H) W& g
- namespace test;) ~) g8 w: I* ~! s
- namespace one;
+ x( S2 u8 N) K! y4 O% O - class Person{9 R1 G7 C) Y$ R6 t/ ?6 F
- function __construct(){
! r& `) L, I( e9 e - echo 'I am one!';
2 m2 _$ g9 ^$ }, M$ z - }
/ f, S. P! ]% O* U - }0 `3 x- J$ z: t9 ], I8 m# `4 ^
- % C! H( h1 K8 o0 T+ E/ F1 f
- class Person{
B& p5 `, s- L - function __construct(){( U2 O8 o9 z5 ~) U# U" [+ E
- echo 'I am test!';
5 y% }: E0 _! w; i: P' G* y - }4 o4 [4 g l* ^! _8 J( c8 k4 K
- }
复制代码
( L; t) k* p3 E* W0 o5 g/ I无需new类,该文件就会报错:
- Fatal error: Cannot redeclare class one\Person
复制代码 ' v7 w7 Q; `. c$ [4 H0 A- [
看来简单的把require理解为替换,在这里行不通。
3 ^; Z+ |! W8 h) _( R6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
2 P, L9 K, j6 m+ k8 z' A" I( A- //name.php
' s- y# q7 @% R* j* M
! [, z4 e3 L$ Z- namespace test\person;% L6 r$ ?0 D! q% _# D
; @( p# Q X9 r# F9 \: _- class Person{
: _3 B% M, R# }6 v7 W4 V) k - function __construct(){
6 v/ L( q9 D6 `; d - echo 'I am test!';
0 @# U1 k5 r$ B, J0 J; } - }5 m; _/ g! h7 W( [9 T# [* h) e
- }8 n" D8 j: Y0 h7 L
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 " Q8 s# e. o1 _" F! V- {' Q
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
5 c ?, r& x& W
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
- //name.php
1 a1 Z: }# r$ j) X& k4 {, m+ \
! u8 G+ | ~1 t0 c4 a2 d7 K- namespace test;7 _! |* Z: K7 P p0 ~
- echo 'zhai14';
) s' W) ]9 ^9 `0 J6 V f/ Z - namespace zhai;: i# L) V: l4 n9 b% o* ~8 ^2 O/ |3 s
- require './1.php';
复制代码
6 h% T- H9 _! |# Gphp命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
. E' y, i1 e w: _" B/ D" {# ]use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
8 t( m% _7 S+ X2 ]3 P& {* Q- //name.php: c# M& v% [& D* e) Y2 o
- ( I1 Y) d* v% y+ Z9 y8 M0 Y0 C
- namespace animal\dog;( o0 w) H4 w( z. @! \5 p
- 0 I4 @: f5 H5 L E
- class Life{! s+ h5 b- F9 J6 ]3 t
- function __construct(){
, g7 Y; l3 W: H6 U - echo 'dog life!';
) k" n- u# h' j. c6 ]6 v% s) A0 y5 g - }
, f+ _1 d& D6 y5 ], b7 {, d& _, Q - }6 i* G; x3 C3 c% K+ }8 \0 Y* I
- 0 h7 i, [+ R8 O I1 ~- [6 H
- namespace animal\cat;5 W3 V4 z* J, w& U
- z5 e2 ^/ j+ ]# x" B- class Life{
2 Q7 I7 t' a, p' X U7 S. V - function __construct(){
; N) I+ s% {' E8 B- a( H i, x5 J - echo 'cat life!';3 s5 B& ]* O( D
- }2 U5 e+ v0 l! e* O( P0 `* U8 B1 O
- }
3 d; O& J7 u8 _. a0 {' ^
7 Q9 `0 z0 ~1 a# ]) T' a- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
4 S0 y" t( Q7 c2 D- i - new \animal\dog\Life(); //A& R3 {$ O# \, F5 P! U6 _
- 4 H7 g% X" w' c/ r+ u
- use animal\dog; //a
0 V5 G2 T7 [3 e; }3 d - new dog\Life(); //B
* g* T, x; R C1 p7 m& n6 @2 {' O
7 Q6 V/ c& b6 D( `- use animal\dog as d; //b
2 w& d. J6 c9 E( b! m L# A - new d\Life();
复制代码
0 N; k" e! k- _( @! b8 A) w1 O. W, p通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
8 U/ u! O. V) V4 b
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
Y$ P0 p. I4 z; R
相当于
2 s# b/ [# y# @% ]
2.namespace后面不建议加类名,但use后可以。
* m9 P; T6 |2 \4 h5 ?. j+ n- //name.php
( k! O# o7 H( W" n; w" c( x# [- Q( Y! w
9 n0 p" x7 |, ~' x- namespace animal\dog;
/ O( P5 \9 a* V9 N$ x8 d$ { - * U5 x9 g% U9 e
- class Life{
/ I+ W' v. i8 ~: I* Y5 ~8 y - function __construct(){
+ a5 i( A8 x. ] - echo 'dog life!';
, C, F6 o( m: p - }
0 l8 d8 c* V$ f% ^6 |7 _ - }1 d: H( F3 s) h2 D0 n. s
; b2 q8 R/ D& A1 h, c- namespace animal\cat;
: Z. H* Q$ d# ^& r - A- s1 f$ M. D$ X( a+ {" a) m
- class Life{) M9 [6 F' `$ ?5 N9 J' L/ D
- function __construct(){; h F# X. {4 M- V. v# `
- echo 'cat life!';
; w; k- n% y0 r# u* S$ X& F( q - }: O( r) J4 k5 e A
- }
! A4 C" b$ V' q8 ?5 W+ P0 a
' C) Q! c- ?) _ N# f4 _( I- use animal\dog\Life as dog; 5 ~9 l M7 _7 S
- new dog();
复制代码 & A& V4 G2 s7 `, ^7 I
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
- Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
- q8 |6 F% _# l* }因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
- //name.php
( `8 |) r- M; o1 ]. ?# u
' z, C& L5 @" N! L9 |. @- namespace animal\dog;
# a+ B% n: s, u3 V7 R! S - " _! a/ Q5 ?1 {- Q* [: s) U. L: f/ J
- class Life{
9 A/ r R9 E/ t9 J! g2 `) D- y - function __construct(){. h; w' T! \, A
- echo 'dog life!';
% F) q2 q! ?6 Q# Y& @) F0 ?. H6 O - }
' p6 h/ ~1 S$ o6 u" u) M6 `6 g - }5 t8 F% l9 M' \4 y$ J# o- Z, m2 B# L
- class Dog{
6 D7 v0 h( R0 `/ g2 b% t - function __construct(){9 a# d" S8 k( s: l- i) D# v
- echo 'dog in dog!';
& v+ \% Z7 ^) z( r - }
! s! U$ g( L! L; w- U4 ~" c - }
# m* G' R1 R* }- _% N
& t5 d% g$ H" x9 m- namespace animal\cat;
0 R# G4 N; z( U2 G
: t+ Q5 b4 }" b% z% B$ h- // class Dog{( e) _; R1 D7 `) C1 p% b
- // function __construct(){8 p, W! f; ?5 j) x
- // echo 'dog in cat!';
* m' o4 U- M, _6 @& @6 p - // }- [5 C) C; r' E" f3 I$ ^* k
- // }1 ~2 E0 _2 c4 {2 u4 H1 H
- class Life{& c F0 u3 g8 H1 W2 ]' {
- function __construct(){& ?2 e' z8 _- i- U7 T, H- u! y
- echo 'cat life!';
+ T; C, o. [* y. I, V - }' j4 I7 W* Z' r+ T
- }
' w( N0 d Y, N) k1 c# P. u" y - 7 ]' Z8 F+ c j6 p W
- use animal\dog;
# b6 ~- r' h- `6 `' d - new dog\Dog();
复制代码
- w# |. Q( P2 e3 Y& g2 X5 S如上,使用了
7 Y r9 b+ v$ X& wcat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
8 Q2 n4 P' a0 |1 y8 l7 a) a4 K9 l简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
8 k% G8 F1 I% W7 V* ?$ f. ?
3 d, k* r, O0 b. h- _. E# O8 w/ x
3 ^* i0 V8 _" R1 }! T+ a! l. f( B* y, |
* R i' V# v8 i7 d/ S* |
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |