cncml手绘网
标题: PHP命令空间namespace及use的用法实践总结 [打印本页]
作者: admin 时间: 2020-7-1 23:37
标题: PHP命令空间namespace及use的用法实践总结
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
0 y9 ^2 Q* Z! z, Q' z; r
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
& o4 e! O3 A3 _9 v Z( A) c" b6 f& r ^* C9 P7 H$ v! s( q* b
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
/ z6 N+ n; H" o* E
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
: W: R+ }/ c8 C- X( z. G* p结合使用方法来进一步理解它的使用目的吧。
/ u; ]( j8 M1 j- k% B
9 O$ c8 a: _; lnamespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写- namespace one;
7 J& L' d, N" g; O - namespace One;( ~5 {( @& d; r+ A7 r+ j
- namespace ONE;
复制代码
' H+ M7 U9 Q! Z- k如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
) d+ i+ g; L) J! r) V2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 1 c3 U6 H9 q2 r; S4 s5 P
- class Person{9 x& @+ {0 J) b. {
- function __construct(){
3 y/ V4 Y' {0 a8 U0 P! o- S - echo 'I am one!';
0 v0 \7 r2 X/ } - }
" B# d2 B( z$ d+ ^2 S H - }
复制代码- //name.php! N' |* B# A8 k% r3 N+ |. ]
- require_once './1.php';& s7 n! q# P! I7 v/ q* o7 [
- % _# }' u1 Q8 Y& T2 K9 Q
- new Person(); //输出 I am one!;, U5 {1 K1 Z9 k; O
- new \Person(); //输出 I am one!;
复制代码
; K! ~; Y! j) H' [# N6 K3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
: n6 i M5 X. U3 i; u9 e - require_once './1.php';: C0 I) | c" H$ E1 l
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
1 V) `3 a- E( b; j9 d% F1 [4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
- //1.php
" x( T# i1 P( A j1 V5 L - namespace one;, h: e- e& J' {* {! A$ Q( h1 a
- class Person{# F# f1 b: {8 D; T! a; K3 M
- function __construct(){" _" l2 x' M( U. f) X f
- echo 'I am one!';
. @4 V& d6 R9 F) @ - }" V: k4 u( A8 b9 x7 T. J
- }
复制代码- //name.php
0 a% s2 F Q4 S7 B) D - require_once './1.php';
r: ^" E, m. m - new \one\Person(); //输出 I am one!;
& M6 E* k6 l5 f6 z - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
) f+ F4 I% Z$ _可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
6 N D, |- c, V0 N5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。+ r) p- z' a0 Q- k
- //1.php
: ~1 b$ Z8 e( M+ d3 k, \# \ - namespace one;
' @9 q- J3 h+ _5 c) Z - class Person{
* M& \4 {* M" k - function __construct(){1 Q/ P* O" n0 I2 h, s& h1 \
- echo 'I am one!';/ S3 H: S9 c2 l* W
- }9 e( S; v! Q6 I- S" d
- }
复制代码- //name.php
Z" k0 m! n5 x5 \ - namespace test;' Q, O- u" V. z- v6 n
- require './1.php'; 9 ]6 i6 _' v6 U3 S
- new \one\Person(); //输出 I am one!;9 O7 @, M2 A- f" v# ]( z
- new Person(); //这里结果会是什么呢,猜猜看. f2 W. P% j# N4 D" {$ a' j
- 最后一行结果报错:) U: k2 [ P2 J6 f! B
- Fatal error: Class 'test\Person' not found
复制代码 & I A: m& W. b: O( ^" @
# i* s3 l/ v% v2 E K
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
# T" `8 c5 S4 {结果报错:
- Fatal error: Class 'Person' not found
复制代码 U1 R* M. S; ]+ Q) J$ I7 _
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
- //name.php
- _2 c* ^' B' `# q( d - namespace test;
6 z, H8 a& n+ @1 }1 t - require './1.php'; 3 X9 T# H! x+ F/ e/ |2 i
6 c- u, a6 n! v, f/ z$ x0 g- class Person{
& r& z" ~1 z$ f$ A8 s - function __construct(){
+ u' J, }5 b$ b# r' P - echo 'I am test!';
+ e9 W: h- b- ]+ A6 J - }" W3 R( i9 @# G2 v" C6 [
- }- |; f7 b: V; r/ Q0 d" ]5 y
! Q4 i5 n* a) @3 z* g: M- new \one\Person(); //输出 I am one!;
( e' W+ g6 ^6 u3 r8 T# l - new Person(); //这里结果会是什么,自己猜猜看
复制代码 ' e1 a9 c' G# r+ ?' B; }6 o
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
- //name.php
% P: P7 O; x- k- W% v: K - namespace test;6 R# A9 w8 T( h
- namespace one;, d. Y3 \5 {9 K1 R8 C0 d c0 U
- class Person{2 P6 U0 x7 z; A* t1 A
- function __construct(){
' T8 g4 S/ Y! o3 s - echo 'I am one!';
( z/ C7 a# A H d. |2 T - }% b! |/ B1 t% c. _7 q5 r
- }6 e# x( p, q& T. M7 t
- ' ?( ^/ |$ R4 j, L y6 \3 V/ `, [
- class Person{
# S9 r7 t+ N2 G0 A2 o; E - function __construct(){$ ]. M* u# j. ]4 C% O' a
- echo 'I am test!';( o8 N: r* v/ m
- }3 I$ G0 e- v( |
- }
复制代码 . ?) p/ w; T1 L3 A1 Y! K3 q9 r/ J+ W
无需new类,该文件就会报错:
- Fatal error: Cannot redeclare class one\Person
复制代码 W/ ]3 w- _: s% Z
看来简单的把require理解为替换,在这里行不通。
7 m5 M; b. X1 [6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
6 Y/ D0 b' D/ {- //name.php0 Q; z. K: i6 _. R0 ~
1 }" u' h) U; E& [# s g- namespace test\person;
2 e' l/ U' {4 i8 q6 N& O: ? - # I4 @$ J4 \' G# d4 D
- class Person{
7 v v# x. Y) Z0 N1 S8 }( W - function __construct(){
3 t, a. ~& i4 l. }# R% Y" f - echo 'I am test!';$ c* d! _ d$ t9 E4 m3 |5 b
- }
8 w9 Z1 ?' Q8 P0 ^5 n - }
# N0 y+ B( g w7 a c( ? - new \test\person\Person(); //命名空间里person无法代表类名
复制代码 : i8 B2 A7 E# b8 j
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
; T* }2 v4 E9 }) I; J1 B) e7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
- //name.php
* C$ d0 I8 |+ k) g5 ?" [! i - 7 z2 V- v( P% K
- namespace test;
. Q: K$ A/ C0 ^* Y - echo 'zhai14';4 a0 y8 V- o7 H$ R0 Q* z) \
- namespace zhai;
& G5 ]7 }. K- Z! p; j0 ] - require './1.php';
复制代码 : t6 @% H) Z' J) ^: T+ i8 a5 {+ v, B/ r
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
5 P6 P8 H5 @) Q7 _0 e2 ?; fuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。% C3 y3 {/ i5 p4 M
- //name.php
/ }4 F# f5 N% V& W. U# ? - , E! Z# z- D4 ?4 E9 w9 z
- namespace animal\dog;2 S$ x) e& G; K9 E- G* {$ r2 ~
- ! @3 r V& O8 J* @
- class Life{6 N- y/ Q3 Y( r# ]5 U
- function __construct(){% R: a# P/ p; a& P/ g+ s
- echo 'dog life!';! T" a2 d; e8 k% P: W7 o
- } c$ B. `/ ~' d6 m7 W) @: a; o
- }; _ M4 b/ P' @
- 8 T. [; q' T# T% }8 |2 x# z. e
- namespace animal\cat;3 J. I( a! Y4 y) b
- 1 ^- t) ^- H% e: I3 h( ^- b
- class Life{4 A g O/ b: ~# C4 b# d7 w6 p
- function __construct(){( H6 [' Q! [+ K* n5 `" U
- echo 'cat life!';+ d C5 H) X) r: q+ e- T+ W
- }
( {5 Q% n9 q' e3 {! h - }
5 N j- ^! Q0 e) {9 h - 0 p( a3 x1 X) k( c" q
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间1 P, _5 f9 }& m) |* v6 h
- new \animal\dog\Life(); //A: R0 h, ]/ C+ j6 l. {8 z: Z2 ^, h) i& L6 ^
8 p N/ _ Y2 ^2 i, @( F- use animal\dog; //a2 ]' b4 L; N2 j( v
- new dog\Life(); //B0 d4 ~' ^0 l3 L6 g3 d$ J$ F
6 Q1 {2 {3 j4 f# I( G- use animal\dog as d; //b
* g. w0 O* Z u - new d\Life();
复制代码 9 D4 b7 ?8 c- J9 ~ s$ n- `3 p
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
8 S4 a) X' D v8 v) r5 j$ r& o通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
2 X+ x: m! v: `相当于
$ b) D [9 v# e* a% M; g4 I
2.namespace后面不建议加类名,但use后可以。1 J+ n. E" @; m- X
- //name.php
5 ~) g! j' h s - ' k# B# N$ z0 a, h3 Q( [
- namespace animal\dog;8 d$ N' |& S u: ^8 ]4 v y
6 j! G) H3 |: ?- class Life{
4 ~6 q6 r+ D# u) b( [7 a, O: j - function __construct(){
7 q* N- y# v' {/ c3 l9 q* O - echo 'dog life!';. s: x3 k0 [: W9 w8 n, b) d, x3 j
- }
0 y5 ?# ]: v: D$ w5 @. S" i2 r - }
9 k7 z% S- s0 n% Z" M5 i- j - 2 M2 d# m) I) R. d5 ]& U: ]
- namespace animal\cat;
4 i) G5 V% { p) V. l' [
Y N5 j+ U$ x* d+ v' g- class Life{
3 {4 d# K" I% q1 W" \( a" V - function __construct(){
]4 W# g* [5 }0 r3 S, P - echo 'cat life!';
' a: W; i# |. F, M2 `' Y% F/ p - }/ A0 r1 r* ]' |0 \0 M7 y2 W' q: V( a7 G
- }2 k2 O6 m. s3 D5 q/ c
+ ]+ n- j, [* s7 A y/ f- use animal\dog\Life as dog; ! V6 Q, {6 [# B; L
- new dog();
复制代码
" u- E8 ?# ]. } H0 n2 ^# e& P: ]如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
- Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 7 N; g3 Y* \* B
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
- //name.php' v& o+ s J$ q; p
- 1 v# R7 v- O/ z9 Z$ P! D0 V
- namespace animal\dog;% r+ e$ T* M! w h$ _- v& D# E
- ; B) g5 J1 \+ j
- class Life{
) B; M N' F$ ] - function __construct(){4 L, O' _) A, U8 {8 D
- echo 'dog life!'; O8 C8 x2 q! x9 O1 ]6 ]7 g
- }
b" [7 v. l+ }6 y, r1 W5 b - }0 _2 o3 M9 a8 a6 ~, Z3 _1 |6 u
- class Dog{. K3 _, ]9 V, _( X7 \3 G
- function __construct(){
+ q: F; [% I# ~: l+ D - echo 'dog in dog!'; B" y6 h$ G7 Q- T% _% _
- }: ^+ {8 W/ d0 B
- }% K/ [* m# @" `
6 R; I6 j/ `$ }) P0 J5 N7 g& c0 H- namespace animal\cat;
5 t7 K' v4 z. T% N
" ^8 `6 G+ Z+ X) a: y. }- // class Dog{
+ g, g' }5 W' Z! M, }1 a - // function __construct(){
1 F+ _1 Y4 m. k& |% i$ Z6 J' i+ K - // echo 'dog in cat!';3 N0 Q2 a- Y( D; [) x# f' ?
- // }' Z6 w' J+ u4 ]5 E4 Z% C7 W; }
- // }
/ ~5 {1 ?! U% C- a - class Life{% i% P# A; g9 {9 o) T
- function __construct(){
' [) F! X& h2 x- Q - echo 'cat life!';
$ k# t% E1 w3 K! k - }
# p; I# h: c: B - }
2 `# r/ M5 k/ ^2 X' Q
2 t! M8 O; ~8 D& l* Q- use animal\dog; ! A: q" X; J# L, S
- new dog\Dog();
复制代码 2 D# a: O; h4 k6 h3 o& o5 z
如上,使用了
2 J. x0 ^! U' M0 D! p/ I" ^; F7 @
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
5 W+ y( G# d4 f- w g简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
7 W+ b5 {$ U% F
! u% r9 K) z' ^% V8 P
8 n4 M8 L) `5 g6 i
2 D! m. H- F) s [( Q
" G' @- q% \8 M" A' X
| 欢迎光临 cncml手绘网 (http://bbs.cncml.com/) |
Powered by Discuz! X3.2 |