cncml手绘网
标题: PHP命令空间namespace及use的用法实践总结 [打印本页]
作者: admin 时间: 2020-7-1 23:37
标题: PHP命令空间namespace及use的用法实践总结
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
& |1 w* V) x. K% j% p文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
1 \ H& m$ l5 T* }9 M V
* U( E F. k |* u& n
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
$ F# l3 L* \0 |8 \/ I! ^
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
* a5 n% S; e$ `" l: b
结合使用方法来进一步理解它的使用目的吧。
& p8 D% ^0 d4 O. y5 K
$ ~9 }& v. K5 t" x9 x1 Inamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写- namespace one;
9 k5 i! V- H# [1 z; ?5 d - namespace One;5 G4 ^1 p% T0 t) s) y: _5 ?' F
- namespace ONE;
复制代码
7 b8 h8 d9 J; k如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
?* h' J) H" J2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
, ^; {! R/ j+ z) l' p - class Person{
9 z) m: I2 S6 N - function __construct(){
; l0 ?2 {( B! s1 S8 [, n3 Y; g - echo 'I am one!';
% E$ h( @3 G/ `/ p9 r - }
: Y) I5 u- K4 O3 k/ U) l - }
复制代码- //name.php
, y) y/ g/ Y0 R9 M- y3 I$ f - require_once './1.php';2 G9 x. p! `& g& V$ z2 v
- , {/ C) X2 r& m. E5 t. e N7 ~
- new Person(); //输出 I am one!;
4 R+ k% O3 r# A/ M& a - new \Person(); //输出 I am one!;
复制代码
6 g- ^- _! @; p) p' M( e# {3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php4 I$ G! G" t1 i6 ^& {( G+ R8 b4 q
- require_once './1.php';
; Q$ J) n7 A' t& k. A - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
( F, f7 D u7 c. G B4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
- //1.php 8 c3 w0 A9 f# \5 D! @& e' {
- namespace one;
- Y7 ? `2 G0 W4 }& P+ T - class Person{( O5 }; h6 [6 v/ n6 l0 q
- function __construct(){( ^! h2 A3 y; Y0 Y6 I
- echo 'I am one!';
% r7 R+ V0 J6 h. I1 o/ z - }
0 [9 y/ R \; Z. E% ]2 h - }
复制代码- //name.php
" H% ]4 Z% |6 m3 u - require_once './1.php';
$ M0 w8 k0 z5 l w8 p& B - new \one\Person(); //输出 I am one!;' u* y& r5 ?( ?2 b, a/ [
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 : Q6 `# }5 ]$ n h1 j. s* \
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
% E, F6 k- I- X' t+ |5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。6 `3 U$ a8 I, L1 L
- //1.php # u2 \/ {6 u, K1 P/ D" w! h
- namespace one; o4 ^$ P* Y" x
- class Person{* d8 }. h/ Y6 U s' C5 U
- function __construct(){# h5 S9 F+ H) \$ O1 K
- echo 'I am one!';* r/ ^# D' U0 U% T
- }
8 B0 |& W6 P% R3 r9 m5 X% @+ [4 S7 D - }
复制代码- //name.php
( m6 D, t- D" N( E, v - namespace test;
4 g ?6 E8 O* q- | |$ f+ \ E - require './1.php';
( q9 u. J8 D2 ^# j0 n3 q+ { - new \one\Person(); //输出 I am one!;
" m- Q; C: p9 f - new Person(); //这里结果会是什么呢,猜猜看
/ ?' \+ u. k2 L! g2 P - 最后一行结果报错:
8 R9 i7 Q7 F/ x - Fatal error: Class 'test\Person' not found
复制代码
0 `2 w# `" c5 i' ^$ D2 @, M1 M* r+ C5 p3 Z! H3 Q
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
' b I3 w1 c$ _7 F6 M n9 M- r$ h4 F
结果报错:
- Fatal error: Class 'Person' not found
复制代码
7 ?% j9 F ~# P' o接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
- //name.php
' O' ]* `# H/ x! r - namespace test;) J! H/ I# U: z, ]2 C; Z
- require './1.php'; : ^9 L0 w( o: s) j h7 |0 U! f
- 4 C2 i$ i+ x$ J. A; H* P) o
- class Person{; b+ C9 a8 u; Z4 S
- function __construct(){
* q' c' P# n7 |$ a4 b - echo 'I am test!';
& }/ ^0 B3 S1 J! p - }/ P4 y- M" \$ ?: H' @4 j/ X
- }2 E! H2 M6 @8 n! E. H8 t5 f- J
. R9 f1 S. m( r1 \: T2 x- new \one\Person(); //输出 I am one!;' x. ]* _; Q$ D! u% _, g
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
" p) s( J, l A, L9 n6 O最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
- //name.php
0 k8 Z1 _) t' X, { - namespace test;
* ]* M4 y5 C6 E9 S - namespace one;
h3 H+ q, _& \* F& r - class Person{
, |6 {2 _, y* I; ^ - function __construct(){. f/ S P. b) _; E9 p% q1 H
- echo 'I am one!';9 U0 J- r7 |6 H, R' S B* f: M
- }8 |/ }2 l, X' r9 A+ D* y
- }
7 R% f; }) ]7 j, z8 c4 Y0 T _ - $ C8 N& l- v( ~; {4 L
- class Person{
3 U+ W7 K+ m6 X2 c - function __construct(){
: ]$ z; \! m) z" b/ U - echo 'I am test!';! L) q: t8 n4 g2 v1 |, i
- }1 W A7 ?7 ?3 Q3 o
- }
复制代码
, p! U( M9 h( Q. J! k0 W9 n无需new类,该文件就会报错:
- Fatal error: Cannot redeclare class one\Person
复制代码 , X$ |! m, e$ ^
看来简单的把require理解为替换,在这里行不通。
5 f% E Q% g) Q; M4 X0 i- D0 U- o6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。& U) l& P3 b* V! v
- //name.php
# V& z: s9 v4 Z - . G( Z2 j* q+ [' ^
- namespace test\person;5 h* C3 [ r1 f: x( w: i
- ! \, G( f. k- Q
- class Person{
' d- O+ R% g- _2 [) c - function __construct(){
. i; @' s" R+ H- I: n2 [2 q2 y - echo 'I am test!';+ a5 y Y J+ a3 ^7 o% X2 D P3 y
- }7 s, w" _; f0 j, r# I) d
- }
2 W# A) {! b" ]* r9 ~1 y - new \test\person\Person(); //命名空间里person无法代表类名
复制代码
2 g s4 ^% ^* Y' N2 C不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
1 R! Z& d8 A0 Z' h2 c F i2 X
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
- //name.php0 x, n$ d7 S6 Z( a# w( I3 R
- * |. i. F: Y: b* p
- namespace test;, k- _/ W/ J3 ?, Q9 b
- echo 'zhai14';
9 r5 z/ m- q0 p' j& Z7 s, T - namespace zhai;
: U+ ^/ p' u2 T: D( Y$ M( B - require './1.php';
复制代码 * \9 Q! t4 E& d3 n v" f3 v
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
! n5 I( M) e. b9 S/ Euse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
6 ?1 U3 G7 I! O3 W. Y- //name.php
9 h2 T% V. q: \ @1 p, U
+ i5 Z7 K( _7 Y0 @- namespace animal\dog;
* g1 `. w/ T1 ~5 n - . a- f z6 d" g& C3 Z4 M- ^6 o! j
- class Life{
+ L* O1 K7 D" h9 h$ E' Z0 s: M - function __construct(){
% G1 N) a6 S! ?4 p" ]/ V - echo 'dog life!';2 C4 C! J! w8 a1 g" R2 t
- }
5 W4 \0 H1 U3 v0 h4 D$ u g - }% Q6 O+ k; z7 Q4 l5 ~ b
- $ X1 E7 _+ O2 k& f/ s
- namespace animal\cat;
4 @8 @: k& L& ]: z S - * N7 W% T5 |: _
- class Life{
7 Z. ~$ e) D: z) S9 Q m - function __construct(){
$ t& j8 o7 |1 L3 H4 l' R/ ] - echo 'cat life!';8 O/ P. w# ^" Z$ e" ]: Q2 `5 w
- }, J4 A( Q1 Y! R6 L
- }
) T8 ?' L4 R1 U5 b' E5 W - 9 D% e4 s$ R- R8 a# o
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间' }5 z3 P& @5 ]# M9 Y
- new \animal\dog\Life(); //A
4 P+ z' ^$ ~% c3 N
9 Q# o h& L: i2 L- use animal\dog; //a
, `2 }( Z5 s; `; X& Z - new dog\Life(); //B; @( O; W* b) g, O. z4 y% t0 {
- 7 `8 w9 x& r ]( E: K2 U) J
- use animal\dog as d; //b+ k0 N$ p! h) k6 i8 H
- new d\Life();
复制代码
4 a: @! G/ \0 C- |3 Z通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
* w- C# v7 p" Y通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
6 r# c8 \8 |8 k3 h" P( u w7 t
相当于
& g% F& h5 V: n |; L0 M2.namespace后面不建议加类名,但use后可以。& Y. ?/ p2 u* y9 L0 u
- //name.php
# d# b7 N7 L5 ^6 E7 P
5 [: O& P6 B- |" ~1 P- namespace animal\dog;
1 A" X- i2 [6 O) W - 2 M' L- d* L( p, B
- class Life{; I6 {' h$ J0 k; }: c; P7 V$ }
- function __construct(){5 n4 L3 k* A9 e6 o7 W
- echo 'dog life!';6 c/ [3 j% H8 ]1 }1 E
- }* B# {+ ~2 d4 y. l8 h+ T
- } A {7 j8 n4 t$ O
. W5 Q7 l1 {% U0 ]- namespace animal\cat;( z+ j4 @. ^- K& y
0 r6 C) u/ E- V( U' e) Z- class Life{
# ^2 M. W; Q) D - function __construct(){' f/ U! M7 f% y6 x5 b. `& m
- echo 'cat life!';
' ]% d9 O' j& [: k5 X, R( u - }
! u7 z( l$ w! H' G% K7 L - }% i+ b( P9 H( d* @4 d: X6 T4 v0 u
! A6 x' o, \3 b& P& d1 H- use animal\dog\Life as dog;
0 n, |1 f. E% ^' b9 o - new dog();
复制代码
; S5 d; O1 z/ u2 @3 ^0 a如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
- Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
& g* ^# R% Y$ {5 N# d* c* m. d( j因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
- //name.php: e: D# s, \1 `* w
- ( C) V+ J+ b2 g$ \- [/ G8 l
- namespace animal\dog;
6 \! u2 S- i8 t7 S0 K - ) M% r3 N2 T/ ]. A9 s& o
- class Life{
L5 u( }6 _0 E - function __construct(){/ l) p' L+ Z! x& ?7 S; q
- echo 'dog life!';
( ]1 R. Z7 w' H, J% ^ - }
/ R5 f3 G. U4 }- ~$ M - }
! m- `8 M' a% K, c$ j2 ]* Z+ c - class Dog{. T% Y6 f! |7 k
- function __construct(){$ r4 }/ H* }5 V% J+ I1 a3 q, u
- echo 'dog in dog!';
# w5 c' C( j9 {- r) d5 S - }
0 K8 N* l* X' N9 ?# ^+ ] - }
- I& d- `% q4 f. n/ ^! Q! _
. {) a9 n2 ]( d' @8 G- r- namespace animal\cat;' g `8 x& O3 u7 w' c# t
- 0 K! @3 u* w4 W0 @$ n
- // class Dog{
" r, ~% V# U* R* t2 X - // function __construct(){& W/ u- q: P" @% O X! R( ~2 t
- // echo 'dog in cat!';
2 z' i Z- X% o2 F8 [5 } - // }( z% s! z9 _: @$ s% @* [/ S" c+ d
- // }5 n$ ?* W* ^. w! I/ X- N7 x: v7 ~) b
- class Life{
: X9 V; D, |3 K# {$ ~' ?: n - function __construct(){$ v0 S4 q+ I' ~# u* m6 N( w. ?% l
- echo 'cat life!';
+ }+ \' b: s1 T; X! F# [ - }# o( y! y `, _7 b9 N6 G9 _% `3 d% m8 X
- }+ x: c1 X! R, R6 ` e e
# M2 k0 y p) T) W- use animal\dog; 4 i1 U* M2 m- I, J! o' |
- new dog\Dog();
复制代码 3 L& w* t7 K# p- {; D
如上,使用了
. Q. c8 ~5 z: fcat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
8 B: T* f6 t' Q: Z
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
0 a8 v3 _2 g& ?) I5 G' s
/ H7 t7 f8 D6 E9 P, s. Q( r8 D5 ?; a7 W
* n" ^- w, i6 D! y) M4 I3 z
1 K& ]& P3 Z F- d9 [- o$ F& b" P/ h) I$ h4 c
欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |