cncml手绘网
标题: PHP命令空间namespace及use的用法实践总结 [打印本页]
作者: admin 时间: 2020-7-1 23:37
标题: PHP命令空间namespace及use的用法实践总结
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
+ |) ?$ W+ V" [: o8 L
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
! @# S* Q1 N3 Z' m
2 `! Y7 h$ T5 I! h8 b) ?使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
. R9 w y. T+ H+ E据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
# h3 z2 [3 ^+ l3 A. T结合使用方法来进一步理解它的使用目的吧。
# p0 k+ f( O; l# B
( W. Y9 G! U: C5 z0 Pnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写- namespace one;
: S4 m9 S+ }2 ]) S# M - namespace One;
8 F, n6 ^8 }- [" S9 H3 S8 a+ s6 G0 g3 b - namespace ONE;
复制代码 " _+ i- r3 Y$ [1 ^4 p
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
# X) s. i% C# K( J. ?
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
. d; n0 ^. ~- }" P j3 _! l, l - class Person{
3 `. g" K3 O+ e: C - function __construct(){7 a/ z- \3 X# C0 {
- echo 'I am one!';& ]# Q3 z; W+ M+ d' y: M
- }- Z0 |; m0 i* [
- }
复制代码- //name.php
% x! s6 i9 [- L* J0 z4 Y. j/ m - require_once './1.php';* [. |/ a9 M: a) \" y1 [
- . m: P' I5 d! j- s3 P: O. d
- new Person(); //输出 I am one!;+ ^7 M% g# s4 v4 K0 u" R" t
- new \Person(); //输出 I am one!;
复制代码
9 a8 Z# t5 V# o3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php1 [: c$ ?: Z; ^: H
- require_once './1.php';! e8 Q8 _& C3 K7 H/ f8 T' P0 [9 [
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 # D3 G* m5 S9 T8 {5 H
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
- //1.php
5 l% e$ i9 N+ E3 v - namespace one;8 a* \; ~2 w6 M, `9 ^* Y3 ~/ M4 p- ^
- class Person{
& Y K1 W+ [2 J - function __construct(){: g) W0 @) B! a, S1 D
- echo 'I am one!';
, a6 @5 e; x6 B Y3 J2 W0 ] - }
; a* `$ s/ {% s# @: L - }
复制代码- //name.php
9 |4 f+ ~0 R6 x; f - require_once './1.php';9 R; f8 @& a5 ?
- new \one\Person(); //输出 I am one!;; F8 x7 P# X( q8 A
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
+ H8 K, N2 y8 H u+ g ~/ `可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
- b$ B6 o' j: Y; b! I# x& Z4 D5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
) n& e5 k) b; A }, U- //1.php
5 G1 P8 b; b3 D' ~+ P5 r - namespace one;
% }5 _% S& @4 |. g }4 [ - class Person{- G9 S8 \3 o2 @4 ?# b
- function __construct(){
9 L" |4 x4 h6 {/ Y- y/ B3 t; x - echo 'I am one!';
! H# K/ l( ^( N/ P# [8 o0 n - }7 i4 p! {# D( Y. C
- }
复制代码- //name.php
% ~) e5 g4 t \( q6 f; r - namespace test;9 c9 C( H; A2 o; E
- require './1.php';
# ], S4 j. v/ W1 w4 D. _ - new \one\Person(); //输出 I am one!;7 j7 P6 K: s! [8 h: v
- new Person(); //这里结果会是什么呢,猜猜看
7 |4 V) x. j& M: d' Y+ t% | - 最后一行结果报错:: s7 a* G: Q; y! Z- A. p" ^# a9 D) ]
- Fatal error: Class 'test\Person' not found
复制代码
' Q- I [6 v& J. a; k' _3 V3 A$ A9 q. F- D( ?! L" a$ X
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
2 `/ ?3 H* t/ _! C( y% ^+ V3 [结果报错:
- Fatal error: Class 'Person' not found
复制代码 ) U: I2 O7 j, U- d3 \! F# v
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
- //name.php
3 k: d$ A3 Z. _; ~! P) _ W - namespace test;7 C1 V6 Y! ?. N6 f. G8 ]
- require './1.php';
& s7 J4 P7 c. }; X - * n( ]2 ]4 H9 `, `
- class Person{
. v2 V, d8 Q3 q1 O2 |, { - function __construct(){
% t4 ]; V& I8 ^8 z7 O0 d - echo 'I am test!';- {* S4 Q7 |; s) e2 ~6 B2 ^
- }
9 N! W4 u* y/ l9 V% r. `0 e - }$ U" j+ x3 F' d* W
- # X% `+ S+ V/ v2 T0 V
- new \one\Person(); //输出 I am one!;: x" s O. D+ ]7 i
- new Person(); //这里结果会是什么,自己猜猜看
复制代码
" k! Y/ ?0 C7 T. D* ] k- f最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
- //name.php3 i6 Q* ~; J, Y0 Y) |
- namespace test;
6 m/ j9 s' d# D1 I0 E# u - namespace one;
8 D2 b+ ?9 e w( i: }. g2 U - class Person{ {8 o) a! c& X8 C' _
- function __construct(){
n' p+ v% J( l2 { - echo 'I am one!';# k) U3 g6 Z% G
- }/ ]% e" [9 C8 o& y/ Z) [
- }
8 O# p* e& J/ i
6 K( H- a$ |$ d; Y- class Person{
$ K6 w7 ]5 v9 A6 ` - function __construct(){. A2 N0 [% _) i; E
- echo 'I am test!';
0 j W# J) u1 L k, R, | - }
* I+ w& v2 I0 ?4 @0 E, c6 R - }
复制代码
3 @; V5 Y' Y* y5 \, D无需new类,该文件就会报错:
- Fatal error: Cannot redeclare class one\Person
复制代码
& Y3 r2 U$ z( l9 F# t! z4 O看来简单的把require理解为替换,在这里行不通。
, f+ B0 g1 \5 ] [& E( K6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。/ }9 G- i, _* |2 Z* _ |! t2 \1 ^
- //name.php% |0 v; B0 F7 k! s+ U$ [8 I& B3 J
: I# A8 o6 U" ^6 W! z- namespace test\person;
. [- e4 B. o1 M
8 G, {/ W5 ?/ E3 Y3 _6 {- class Person{" ~8 y& m, g1 k# ~1 {1 V1 z' ?7 H
- function __construct(){
* L, F" R! j7 {( F3 E- M% v6 `; m - echo 'I am test!';6 u3 I5 D" ` ?7 a" c( V
- }
7 x+ w# t3 M0 h - }" ~* M& v7 V0 ]7 I
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
7 w6 w7 o* N6 J# E+ ^4 S! K不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
( ]4 X# s9 b1 |# F; _; K. e# I
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
- //name.php
5 A" ^5 p( H# E. s) a - 9 m0 D! n1 a/ M1 u, ~2 T, i
- namespace test;2 Y3 a/ Q4 B* d* _/ F
- echo 'zhai14';+ p( j8 X. }- @- Z$ c ~
- namespace zhai;
: q0 j1 Y+ e+ I - require './1.php';
复制代码 + K6 h5 x1 Q4 s5 k. [
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
3 j' {8 p! ~# ~use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
/ j" Q% X3 K# ^1 U- //name.php
7 f* G w, \" O3 P+ b+ n - / p) ^6 @6 R( Y
- namespace animal\dog;
" `% X4 J3 P) g7 @$ @& A3 Z
: Q* V/ ~# \5 F/ H. c" i- class Life{
' ?( T$ P U0 W - function __construct(){
# b0 y# t) @' I1 D; e; B - echo 'dog life!';% Y6 D1 @9 n, L! ]5 W
- }
6 D+ t. q! G: \) E - }
) R6 E% R! C4 D+ r - % e% K- ~4 x3 K: Z
- namespace animal\cat;1 i' l% U! ?' Y, n) f% F
- 6 v" e" V( f/ ?
- class Life{
& _% F' y& e3 o% T3 n4 p0 } q9 Y - function __construct(){
^ F' Y: n& x$ ^ - echo 'cat life!';
1 G3 u2 _7 q1 K* Q/ v- T, ~0 y - }
. r2 d. E: t3 g, a - }9 l: S$ Q) ?, `3 d
- * R7 x% I! t3 P, m4 d/ G$ w
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间/ W- e+ v0 O& q6 @2 Y, A* d
- new \animal\dog\Life(); //A: }: Y0 H8 O Y8 z* H2 m! I, x" I
# y `% y5 @$ r, ~8 ^. ?! ]* y4 T- use animal\dog; //a3 K5 O2 G1 M4 ?
- new dog\Life(); //B8 V# s4 {# z$ F' b: d
( ?+ m# M0 {. z# `- use animal\dog as d; //b5 w9 ~3 V3 j: a: u
- new d\Life();
复制代码
( V) m6 ^2 p/ f0 t* z p+ O通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
$ C7 D7 a: L( ^- e$ h3 m通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
9 t. f5 m& r& ? w
相当于
" ?# z; k# y5 w8 G s5 y8 C" \2.namespace后面不建议加类名,但use后可以。
$ p! o0 C% p3 P" D- E' d+ Q1 t9 ^- //name.php
3 O4 P4 k$ @9 |- Z3 K+ l7 l+ }' n
. t: D* V( O0 _) |- namespace animal\dog;$ V2 P4 Z* S+ u! K% t- O O4 v
6 s: n3 i1 ?. ?, Z7 o- class Life{4 Q+ t$ X) W1 n- e* b
- function __construct(){# C3 |( c Y' c4 \8 |$ v* K
- echo 'dog life!';* c. |8 J, I* b" D( S7 z. C* r
- }
& `& a- I5 b/ H. r4 M5 |2 p - }
# t! f9 A# T( k7 _/ q) b+ h - + }7 S# @. C2 Q0 |
- namespace animal\cat;3 l3 @7 Q5 w7 c3 b
, I6 G1 o; C. E9 N) d$ S5 a- class Life{% f, k) h3 C, s, B2 L, p
- function __construct(){ V: E' H# [6 g0 x# O# O* d( a
- echo 'cat life!';* q; @! u" P/ E- p$ ?9 _$ Z2 W: G
- }
9 T X( T. |/ Z- c- N1 a$ z - }
+ G( f: J( ?1 }3 y1 _0 k
) ]* C5 ]! h3 ~* v- use animal\dog\Life as dog;
4 \* s1 _. A0 }3 G3 [' v( J+ V - new dog();
复制代码 ; l- `% J1 D9 h
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
- Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
$ _8 `5 p- y( C! `' G因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
- //name.php
q; b- d+ G$ n' \/ Q; g - ! z( a4 t W8 ^! x
- namespace animal\dog;2 }. o7 P9 ^% E0 F: I& C
- ; g/ \+ n9 |" T8 E7 j$ e2 L5 ^. y
- class Life{3 G, L0 D" n* N: Z+ @7 O: E
- function __construct(){
. w* n4 @0 @) z/ X7 Z* ~; n - echo 'dog life!';
" D9 y9 X: h$ l+ G. I @ - }+ M) C! h# {; A2 H3 b# P1 H
- }3 s) Q! W+ J" e; q6 C0 b
- class Dog{
0 Y& x7 h4 i& _5 Z - function __construct(){7 P5 |7 v2 y" o' l' s
- echo 'dog in dog!';
5 ?8 C7 g% g3 a3 _1 t - }; G: i$ D8 Z8 S5 b
- }
( \* |' {4 h4 Z% [( d/ z - + m% a$ B- X2 k& V
- namespace animal\cat;
; Z# z) H- a& q b3 V: l
* H) P3 F& h2 S+ E. G9 p- Y9 }- // class Dog{4 \' ~& S" P% X. t
- // function __construct(){" B8 {2 c7 J4 Z$ l5 {+ O. C
- // echo 'dog in cat!';( P- m. P" J3 T' g3 l$ B" c
- // }" t; y W2 e8 F4 o1 e
- // }
B2 f T# F- e2 p6 f6 W& p7 N, `% { - class Life{
0 {; P1 _8 C; z9 M- F# H - function __construct(){
4 t7 i" V& Z' L5 B4 H3 V! M" { - echo 'cat life!';% `0 @' b o" d- z
- }
$ a! f- a( [7 V; O. n7 V - }
: N: X8 }5 i+ G2 U" a - $ f! w0 m- s8 }2 n* [2 Q
- use animal\dog;
$ e$ U; |( X" ^, s1 O - new dog\Dog();
复制代码 1 F* D4 D+ z" A2 \' U4 k8 L
如上,使用了
1 y- S. _% Y9 U, ~, Ycat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
T/ Z5 M2 w$ w简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
' z* Z0 `. L3 c2 J& I6 O
& M n7 L+ [8 O* o
& `9 ?; ^0 r/ o. h6 L, C
4 I0 o) n+ \0 S4 T1 |. S# f9 f, o# R5 [1 \$ a+ }8 d' Y3 [8 \: T8 _
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |