您尚未登录,请登录后浏览更多内容! 登录 | 立即注册

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

cncml手绘网 门户 查看主题

PHP命令空间namespace及use的用法实践总结

发布者: admin | 发布时间: 2020-7-1 23:37| 查看数: 15333| 评论数: 0|帖子模式

以下皆为本人自我理解内容,如有失误之处,请多多包涵。

' M8 [# p( E- z' |0 a: f
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
/ m3 h( B. N4 h/ l9 T# ?  o. I* h
: m8 a% ~: q0 ]. b" T( l5 z& H
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
9 ^. u9 C9 F4 r9 ?' ?
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
3 b1 Y1 G+ [; ^  l# r
结合使用方法来进一步理解它的使用目的吧。

/ A, Q$ _6 }# @8 Y
, p: G, E& p5 J9 }7 v$ Qnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    , H6 c5 q: G0 u6 S5 f- Q+ X
  2. namespace One;$ s9 ]8 u1 E4 e
  3. namespace ONE;
复制代码
* U& v+ |9 ]; z+ I2 N
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
& f5 G/ ^5 E" w+ b
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
    . I1 s# P- n0 Q" g& E0 e
  2. class Person{, n4 \, |# t  b  I- p9 h- p
  3.     function __construct(){
    4 t4 U3 C9 M8 f
  4.             echo 'I am one!';  N( r9 c$ \& b5 \
  5.         }
    7 \  m# G- h7 n; k! `8 r
  6. }
复制代码
  1. //name.php! R" \( B+ D  l+ q0 ?
  2. require_once './1.php';
    & l& X+ V  ]9 J3 F# p9 E

  3. 6 E6 h, S# Y0 X" E+ }4 B
  4. new Person();     //输出 I am one!;0 j* ^4 n3 N! L, {9 K
  5. new \Person(); //输出 I am one!;
复制代码

- K+ e' M: o: W# u7 R3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    5 [$ Q& `% U+ k" w/ R  P/ Y3 ]+ X
  2. require_once './1.php';2 U+ C4 ]! v& H; x" w
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

% {/ j2 |  H8 f" n4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   
    * C+ i5 V0 {  S8 A2 z
  2. namespace one;- f) E. A+ h+ [9 n/ [# i  s% U
  3. class Person{
    9 M" n' j1 H. P9 O9 |
  4.     function __construct(){
    # t' e/ S! Y" [& t8 q
  5.             echo 'I am one!';
    ' s' n9 d- \/ t6 n5 ]" o+ h2 T
  6.         }+ ?) _, L5 E9 D' @
  7. }
复制代码
  1. //name.php) ^! n' D+ K2 L( R
  2. require_once './1.php';
    2 b# @; \' J$ x$ M5 v3 p, \5 f
  3. new \one\Person(); //输出 I am one!;& Q% A# H4 l# n3 R2 F3 u! ~0 E. M! x
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
7 n7 Q* t- ]' g, g
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
$ \/ E. L, T$ n( i3 P, p( o
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。) z2 p% A. X, i+ i
  1. //1.php   
    * m& F4 G  @3 ?# a$ g
  2. namespace one;6 m$ J1 `. [: d7 e" r2 ^
  3. class Person{
    / P$ v# `6 h- J
  4.     function __construct(){: ]$ w0 R" t; d& a. A' W8 K
  5.             echo 'I am one!';1 a4 e0 W: J" A) H7 r
  6.         }. V( D: g% W# c
  7. }
复制代码
  1. //name.php
    + j3 E' u3 E: g
  2. namespace test;
    9 B9 A* d4 A# T
  3. require './1.php'; 9 ~( y" M  |5 z' M- s5 E9 k
  4. new \one\Person(); //输出 I am one!;
    * {) C2 k. P0 X/ W* ]2 v8 I  C0 _
  5. new Person();      //这里结果会是什么呢,猜猜看
    3 u- @3 j4 r7 E4 G1 ^
  6. 最后一行结果报错:7 |8 i& p4 v" I& i6 G
  7. Fatal error:  Class 'test\Person' not found
复制代码

9 `; S& P% s0 h( _
* }2 x+ b0 p& D
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

* Q$ n' o" r3 [
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码

3 o! y& n1 x* g' M" ^4 F
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    , ^8 T* p' L6 e
  2. namespace test;
    2 N4 u, h( B$ Y6 B0 [
  3. require './1.php';
    4 L' q. M2 V; y1 Q* F/ T
  4. 6 j' W0 [9 g+ s
  5. class Person{5 G1 N8 G+ x% L0 `" [1 P
  6.     function __construct(){- P% S. F8 N0 M# r" W/ d
  7.             echo 'I am test!';! M6 T, s( l/ E8 c+ e0 C* @
  8.         }+ Y. K: M4 Y  v
  9. }
    / T$ E7 \; C& T3 e5 l. {

  10. 8 J% v/ l( Y& K' x
  11. new \one\Person(); //输出 I am one!;! c  k/ f. B/ F( m9 `
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
, |9 a! V6 ~( X7 \* `7 ~
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
    2 [1 N3 q8 |/ a
  2. namespace test;/ t& X- D. q) A. }$ U
  3. namespace one;
    , _; _0 a  K4 I& ?- m
  4. class Person{2 Y2 ^; g! v3 o; m% ?: k
  5.     function __construct(){) O; Q: `; c. t- ~0 p. u7 X
  6.             echo 'I am one!';
    / s8 y5 c0 _6 g% U5 |5 G, G- I
  7.         }
    , \# Q/ [( O% K8 h
  8. }
    - ~$ c3 j1 e4 g7 S3 E
  9. 1 @+ ^, q5 T8 X2 G
  10. class Person{
    6 B6 c- }7 w. I, e( l! j7 S6 T6 G. f. A
  11.     function __construct(){
    6 ^+ L0 y/ l' N% u9 c( b
  12.             echo 'I am test!';- U& V# v( H5 W* K% K
  13.         }! W- a) G- F) C, z/ A. Y
  14. }
复制代码
9 F6 D& P7 z$ M8 e0 E/ ]( x
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

  Z" i/ h3 T6 Y8 b3 T
看来简单的把require理解为替换,在这里行不通。

+ x! y5 a  Q- y  K6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
# S0 w8 X9 A& B+ `
  1. //name.php' O4 u. @1 h9 n$ f, r9 D

  2. : Y2 ^3 V4 K; J" _% f
  3. namespace test\person;( b; K7 u' ^6 O
  4. ; f; g- l  K. [1 v1 R; g
  5. class Person{
    : d% v" V& v8 |. n
  6.     function __construct(){
    * ^- t) `8 g0 E" S
  7.             echo 'I am test!';# y; l; k! D. c& l' L
  8.         }3 s2 p/ L; R. F% q; R, V, O
  9. }
    : z" W( s( L/ J! S( C" ?
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

) k( P. v' K: Q' ^6 a
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

/ p: @+ a; i# P, \7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php/ Z6 Q' s# m: m  W! I* P3 K

  2.   F# ]+ c! X% \4 t) |3 S
  3. namespace test;
    3 A, P- c& k- M# z* p
  4. echo 'zhai14';
    8 C: \: `% W3 @5 ?" ~0 _
  5. namespace zhai;
    1 w* v$ K, \1 ]4 e5 l
  6. require './1.php';
复制代码

5 S: A6 ~, r; {% D$ x
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

9 [# C1 S  q$ a2 G1 K! ~use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
# s( [6 V  ?2 z+ [
  1. //name.php$ Y3 X: U, h% F3 _7 v; h6 t
  2. 2 K1 s# x" Q: T6 G
  3. namespace animal\dog;
    0 s2 B6 S3 H$ }" Y

  4. 9 a7 o) v! R  v( G
  5. class Life{3 }) k( I$ C, s, i/ I6 l
  6.     function __construct(){: f" O2 ^3 u$ Y, r, L( U9 J
  7.             echo 'dog life!';
    0 d: C& a* x4 n1 i" S9 ^# W
  8.         }$ Y, s9 n, c. B9 L. G
  9. }
    ' L$ m+ `5 l) K

  10. 4 ]! X; K& V" D! p2 ]$ v4 F
  11. namespace animal\cat;) q- C. M  G) r* u

  12. ( q5 l2 u7 P; j! ^) w
  13. class Life{! [( g# K; A; N! H/ \! n
  14.     function __construct(){
    & }+ K% `" N: n! \% ^
  15.             echo 'cat life!';) V; Q' r9 D/ z# j
  16.         }
      R8 @$ P0 O3 [( ?5 ^
  17. }2 K, `6 m$ h# d% j! ]$ ]

  18. . z: x  A$ L2 h: j9 v
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
      p' A+ t, w/ s
  20. new \animal\dog\Life();  //A% w: t( _. V, h; ^5 a

  21. + [6 x% G0 V" p
  22. use animal\dog;  //a
    " V3 q0 ~4 ^# z3 e) U$ |
  23. new dog\Life();  //B0 m- l( e" Q% M! @% V2 c2 q) l) N
  24. . I4 h& g7 c* v
  25. use animal\dog as d;  //b; S5 y6 X, o1 f" B. A" @
  26. new d\Life();
复制代码

) y0 v0 {- F, I3 c( T7 l: w
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
/ w; R7 _" r* Q; h
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

7 x1 y4 a2 o8 l4 z9 n  G
相当于
  1. use animal\dog as dog;
复制代码
# H0 z2 l( Y3 m  u  k2 T
2.namespace后面不建议加类名,但use后可以。
$ ^2 _' W5 @$ F
  1. //name.php
      q! ^9 Q) y7 T; p( W  ^

  2. 2 @$ Y! P8 \5 b4 F7 ]1 {# U
  3. namespace animal\dog;( j+ q9 {8 [8 ~; |9 R

  4. * m% H- ^8 @. T' n9 A
  5. class Life{; L6 i. n" k+ C, N
  6.     function __construct(){8 U% |, Q3 i# g* U) L; [
  7.             echo 'dog life!';2 W) E7 w9 o/ W5 E% {/ t) C
  8.         }$ k1 j1 f2 F! ]& C
  9. }4 l7 X  L, B- @

  10. 7 @# H9 i2 J3 g  q: ?/ w
  11. namespace animal\cat;! T8 e* j3 f6 M8 r. z7 C- |) D
  12. ( s6 k1 D, ?7 \7 E* e3 l" k% W: O' s
  13. class Life{7 _& w, w# e1 A8 ^) p: E1 V
  14.     function __construct(){
    ' K" C' @. k  s
  15.             echo 'cat life!';, c, G' I) t) e1 S- ~( G
  16.         }
    / V5 n* r& u0 X6 u, t
  17. }
    % b6 c2 x: c+ ^4 \7 Z

  18. ) Q- F) m( J( z3 U/ e
  19. use animal\dog\Life as dog;  
    , O! R, I1 R# Z5 D5 O$ z8 S; D& D% A
  20. new dog();
复制代码
* ^/ A; T5 s/ k6 K7 h0 B
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码

/ F" ~) h0 \3 D. u
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    1 P6 ~$ c1 v* S* j- C) h3 G1 B

  2. % E; l' f3 Q, S
  3. namespace animal\dog;
    7 [; ~) ?/ O0 x. T# U7 x
  4. 8 ~" N" F$ N2 J, O, r6 }4 Z
  5. class Life{
    ( H" @. n' u# A5 w% M9 E; t
  6.     function __construct(){% V, f; i5 @! O, q* _8 K* Q. P- r. i
  7.             echo 'dog life!';
    " i/ P* g0 \; Q. X
  8.         }
    % e. {! }# u. o- D* W* u- J
  9. }
    ) [; o3 f2 x" Z: u# c. _' X
  10. class Dog{
    4 p/ _! a' }" s  L4 ?4 U
  11.     function __construct(){
    3 x  a2 q; \4 W, M* x' z
  12.             echo 'dog in dog!';! _, E( S( W4 }6 i1 p
  13.         }7 [9 K# S7 S+ \5 ?% \' [6 B
  14. }
      d3 K% K7 B( P5 {2 V. e1 m
  15. - e( }) g2 k! E
  16. namespace animal\cat;" F& r  Z  x% Q( U

  17. * A( y/ X% b, C4 A' n5 U
  18. // class Dog{# m) ]- }6 J0 u7 ]- a9 n
  19. //     function __construct(){
    9 t* d$ J: i8 p8 L5 P
  20. //             echo 'dog in cat!';
    ; Y  t; @& `: z  a
  21. //         }4 K6 [5 t) W; q/ L
  22. // }2 T" A5 l( h; _& i) O" H1 s
  23. class Life{
    / N' F% f% }. s) p8 D
  24.     function __construct(){
    " T" b3 e4 }6 Z: a
  25.             echo 'cat life!';* g# Y0 X) S4 {$ r+ H* A
  26.         }
    7 b! F! W# R) I  k$ e$ R0 g) J
  27. }
    . U/ \$ O* F$ `6 ^+ f

  28. 3 n$ o5 `2 M5 L& W( Y; P
  29. use animal\dog;  
    4 V8 y' I9 k. P. a  q3 B
  30. new dog\Dog();
复制代码

' ?" w. Q' M7 y
如上,使用了
  1. use animal\dog;
复制代码
  G" ]: @; R! S/ ?$ v& P6 ?. |( ^
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

* }8 l/ Y- T% }6 l5 p
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

5 k+ k3 M* L) R( \2 _0 d1 [  w9 `2 \9 I/ Z

# Z! z& G. n$ U- m, Z
, n% `$ k8 V1 T
- x: o: U+ Y! Z+ t7 ]) l

最新评论

GMT+8, 2026-3-16 13:31 , Processed in 0.052799 second(s), 19 queries .

Copyright © 2001-2026 Powered by cncml! X3.2. Theme By cncml!