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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 15990|回复: 0
打印 上一主题 下一主题

[php学习资料] PHP命令空间namespace及use的用法实践总结

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
6 G( E% h! v% P( L% D  c3 B$ r
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
! ]* V4 p0 @6 n3 _( j+ m( T. t& u( V

) d2 l3 \# ?( T% q使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
. ]' I- ^2 [3 M! |& t1 m2 J
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
! w3 R' ?  x* t  f
结合使用方法来进一步理解它的使用目的吧。
: k" \$ V8 x  |6 i) P9 x/ R# c
7 I4 J, d! |: _* n% J+ W2 z1 t9 Y
namespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;' d$ F  s- O  s3 ]$ x0 C
  2. namespace One;4 ^- [, a# a9 X; U: m4 ?
  3. namespace ONE;
复制代码

% s( y4 R0 J& ?) b
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

" o! t; w* Q3 I1 k7 h1 m0 c2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   
      `, ^$ g* V! G
  2. class Person{/ y- n4 B9 Z( G3 B3 y) S
  3.     function __construct(){
    / d' [$ m  w( q) M9 |  C& H9 l% R
  4.             echo 'I am one!';
    7 S  r3 L$ V' X. p: i; h
  5.         }' d7 T$ X; z+ ?6 H) G( q  a
  6. }
复制代码
  1. //name.php8 S0 X- W; ^1 S5 P2 d% e$ `
  2. require_once './1.php';( J: b" i1 d( z4 F

  3. 5 l% E; f. q, z3 J
  4. new Person();     //输出 I am one!;* y, G4 ?# a+ \6 f; G4 g* [
  5. new \Person(); //输出 I am one!;
复制代码

! M7 {5 C2 L+ t6 B+ Q* L3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    # w" X+ C. m6 l% I
  2. require_once './1.php';" a) L% i4 F4 ?  l1 i
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
4 J/ M$ o9 @: `. f0 a$ P
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   " }- B$ c8 {$ \+ R9 n. _, }
  2. namespace one;
    & @+ v( u$ h+ P$ M# D8 [/ {
  3. class Person{& u. q8 m7 b( P
  4.     function __construct(){/ e% _' J) s7 Z! [
  5.             echo 'I am one!';$ j8 i$ j! V9 I% @7 ]# }2 W, w4 X
  6.         }) J+ x- {* f! V$ Z
  7. }
复制代码
  1. //name.php3 I& j- Q% c. y& d! x
  2. require_once './1.php';
    ; L: M, n/ r/ ^
  3. new \one\Person(); //输出 I am one!;5 u& S8 b; y% K% e7 @
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码

8 j  n9 V8 R: A; k! y+ n1 l: ~
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。

  @' l/ H- r5 }7 G$ F* G4 X5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。$ T) w, U$ I5 o
  1. //1.php   
    * s9 g$ Q& m5 Q- l: T) W
  2. namespace one;/ F& l: A0 m; p/ f* U- j7 \
  3. class Person{
    # l0 ?/ ^' E. C. [- i% O) J
  4.     function __construct(){
    * K  e  `7 t0 P
  5.             echo 'I am one!';: L2 K* R5 Y; t1 |, _& y
  6.         }. ^: s1 f0 L2 K9 S  l
  7. }
复制代码
  1. //name.php
    0 X, f4 ?6 `! q) M- ~' ~/ }/ ]
  2. namespace test;- n$ l4 X! b. c  Z' J9 f: \7 S9 J$ z) Q
  3. require './1.php';
    * `' G/ N5 x$ u9 w. F$ E
  4. new \one\Person(); //输出 I am one!;1 v9 j% }3 v# \& y" h  Q
  5. new Person();      //这里结果会是什么呢,猜猜看
    ; c/ Q& C0 S/ Z. K4 g
  6. 最后一行结果报错:+ `- g( B8 M$ W* ?2 O" Z5 L
  7. Fatal error:  Class 'test\Person' not found
复制代码
) D: E2 [/ A+ C4 X

; I/ |' U& g2 v1 h9 W首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

- g$ B- ~/ Y+ s
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
" j0 J& s* O( B! s9 w: R" D
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    4 B, n6 K& [. \1 B& ]5 a" k8 Z
  2. namespace test;
    / t- U, l3 Q5 o
  3. require './1.php'; + `, U/ U1 r/ Y) c' E

  4. ! O$ @5 d# i2 e& Q3 W( T1 `' C5 N
  5. class Person{
    # T9 M- Y5 K6 @" y2 x& H
  6.     function __construct(){
    9 f- T' y2 r" H1 d* H
  7.             echo 'I am test!';$ m0 c0 g* Y5 H8 k$ C1 R- e
  8.         }
    ( H& a# T. g2 M& t$ d8 s! z
  9. }
    2 j) t2 r% W8 q8 |5 J% W/ z
  10. / D- z3 `0 b! Q$ d  A' T! _* g' [
  11. new \one\Person(); //输出 I am one!;) @% a& r' n$ {) B$ |4 i
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

: {; E/ W: h( C$ d
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php# u7 Q/ H* m/ {- |
  2. namespace test;: @5 E7 C3 }) j" X
  3. namespace one;* _3 Z& |. X) `7 h6 k3 E
  4. class Person{, T* g) u0 P- s. V& V
  5.     function __construct(){" J' h' C7 [7 Q2 u2 V2 w/ w
  6.             echo 'I am one!';
    + v; Y; z! V) G: H
  7.         }
    8 r3 B% h; [4 c! G
  8. }
    . \0 [/ z  N* a6 O2 l$ N' y
  9. : @# a$ V+ Z7 k
  10. class Person{6 h2 q5 ~+ A: U& n8 U
  11.     function __construct(){
    0 \; @+ G! z+ j
  12.             echo 'I am test!';
    + E3 ?$ I; @0 ?/ y" w* L# S
  13.         }
    ; q  ^1 w# G, v; z2 E
  14. }
复制代码

; ~6 J6 o  d) T. r2 V: S+ r
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码

, r' z; @/ v1 [' ^" }
看来简单的把require理解为替换,在这里行不通。
5 w& F. T& C. W/ F3 b! z
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。$ g8 e* D+ y& b# h; _- E0 N
  1. //name.php- B: p- ~/ D! H

  2. 2 y. a# [8 J$ b1 X8 V
  3. namespace test\person;
    2 k2 C+ @  f2 M! B* V6 d9 t  ?
  4. ( w& |. @  L8 ~- h  m
  5. class Person{
    & T: J  y  O, ~8 @# S1 d. h
  6.     function __construct(){( a0 [. W* r1 d4 W0 ]- t, u0 b) R
  7.             echo 'I am test!';
    + v& c4 Z. A8 Z) r  s2 W5 Y
  8.         }* K8 ^9 ^5 J7 t/ i' N- m
  9. }& D8 |2 L! \* y4 t2 w0 p( q: u  m- c
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

: W1 a* r6 ?: {' i( }$ Q( n
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
8 f/ f+ d1 h' g8 y1 z$ H5 W$ T
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    " a) R1 z3 g2 ?9 }) l! j  L: `
  2. % m: s% N' d0 f3 K/ O, q
  3. namespace test;. ?5 ~6 B/ s0 E) i9 d2 T. F) g. d3 u
  4. echo 'zhai14';
    3 A1 j5 Q" v. @( c' J) g$ f9 ^
  5. namespace zhai;' V: q# C8 n3 S5 c6 I- h
  6. require './1.php';
复制代码

! s- N6 n! E% Q- X/ v
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

9 o9 E' i* T" e$ v# E& Suse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。# J! h1 \7 u( d7 a$ t3 ^; w, {
  1. //name.php% B! i3 X1 n7 T0 i6 h
  2. ; _4 _4 g" N# v& [/ j, R
  3. namespace animal\dog;
    $ ^+ l1 Y7 D9 c3 D" ^2 E. i
  4. ' R) L# r, {: [) I. T# W: d
  5. class Life{; W9 S4 ?! x7 Y# {: Q1 C
  6.     function __construct(){$ h# l. P- K% j/ N
  7.             echo 'dog life!';
    ! O" O* P8 ^, Y( f4 Q7 n
  8.         }2 I1 J1 u; `7 }
  9. }% d  Q2 u4 T( ]% w' U1 b+ |3 d0 z
  10. 2 y" z0 N4 M, Z1 _- I, S
  11. namespace animal\cat;& W8 ?: E+ l/ h) j1 w

  12. 1 m) Q/ }  ~6 |4 e, n/ ~
  13. class Life{
      V4 J1 C1 J* S. f1 t& A( `4 i
  14.     function __construct(){
    ) N8 o6 S1 l0 i: T* G
  15.             echo 'cat life!';
    - L) A. }6 g' x5 e4 t6 P
  16.         }
    # d8 C+ |3 W% }! m9 Q
  17. }- h( y3 f5 s5 z8 ^+ P" e

  18. ' L8 U$ R& I, F2 N; `" P6 h; o
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    ' N& b6 B( q" G. k6 N0 s  p8 M
  20. new \animal\dog\Life();  //A
    , t7 q9 W0 o8 m8 y# B6 Y( z# J: G

  21. * Z" `5 P5 |9 m8 `, J; n1 t
  22. use animal\dog;  //a7 H5 S" b% T% h# I* I* c
  23. new dog\Life();  //B
    ( R, O& R# N- N$ K8 `' ?
  24. ; l7 J7 {& f2 E9 }2 H8 w4 C, M. ?- X
  25. use animal\dog as d;  //b, k5 }1 r: ~4 Y7 ?, ~2 y) q+ P
  26. new d\Life();
复制代码
/ L7 L) p+ |9 A
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
) [( ]2 ]/ m0 N
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

" O( L5 g$ N: e# W
相当于
  1. use animal\dog as dog;
复制代码
( z* k1 |# |) E+ t
2.namespace后面不建议加类名,但use后可以。5 v9 q- g" R6 j$ Z7 x1 [7 R3 _' G
  1. //name.php7 @  T. s- e# \- k: ^

  2. - g( C" ]5 E7 W
  3. namespace animal\dog;
    * e& y( z7 L) I: t8 z

  4. 9 z$ M, R  ]: g. v# q
  5. class Life{
    ' s! G- h' K( M8 g! Y
  6.     function __construct(){3 L) G2 l& R! u6 j7 A4 a( z
  7.             echo 'dog life!';: z* R8 B2 U6 A; o, z
  8.         }( Q6 l) h& f* x3 h; Z
  9. }
    , Z- f+ t; z$ F8 V0 C

  10. 5 t  y7 O9 {2 u" d
  11. namespace animal\cat;. {+ X" H/ [, y: x% M- q4 }. b

  12. ; A( P- H; F4 C' u8 l# U
  13. class Life{
    ; t0 u6 \8 c# X: N& z; }
  14.     function __construct(){3 I/ C0 F- h" _/ P6 f
  15.             echo 'cat life!';
    5 r1 v2 B0 g. o; ]7 {0 i( o
  16.         }0 S9 M( D3 f) y# e+ G, M, D; W6 T" o
  17. }( r/ l: h8 \* r; f9 r

  18. - ?1 G2 M- E) x, C
  19. use animal\dog\Life as dog;  
    # K: {% i* |  ?0 ]/ g7 l
  20. new dog();
复制代码

  o( g& F+ i/ x/ ]
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
0 \% A* K$ ?5 G
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    0 r% b# u! {1 e2 ^5 u' }

  2. ( i, R$ R8 q, H( D  \2 P- G
  3. namespace animal\dog;' |  r- a- r) m( ^* S

  4. + O+ [4 I$ i$ [4 v# u) n
  5. class Life{* s6 r( N4 y+ E" x3 [% c
  6.     function __construct(){
    : i6 c9 a! C4 [5 P2 h6 o: j5 J
  7.             echo 'dog life!';
    * a# t. H; q8 c7 G, \5 g1 \
  8.         }5 u5 J2 E5 i4 D  X; u8 e* U% j! P' q
  9. }( O4 g# C9 q' @. W# ?
  10. class Dog{
    & X  `, S* t5 T( I4 T
  11.     function __construct(){
    0 Q( F: l& G3 Q- J- l
  12.             echo 'dog in dog!';$ Y1 f. u" M1 `7 B$ F$ l
  13.         }
    $ G2 s' y+ q& R5 {6 u
  14. }6 `" S; O5 l" `2 v1 f

  15. 5 P5 F) k8 _) o) M
  16. namespace animal\cat;5 ]4 n( x* j. ~: j  F. u
  17. . b& M8 c! p0 d0 i( |: t
  18. // class Dog{
    ) o; V' |' u' K
  19. //     function __construct(){
    3 Y7 q  X0 ~) {7 p. X
  20. //             echo 'dog in cat!';
      Q' M5 G6 B1 C2 |/ [0 t" ?
  21. //         }
    6 ~& C4 ?# A# |5 Q) h2 w' H
  22. // }
    ' i6 b/ i& ~9 q, h- C; C& F
  23. class Life{
    - [& t5 e' @1 T- A% E& ^8 e
  24.     function __construct(){
    # }- p; [1 h+ W' Q
  25.             echo 'cat life!';- h" X1 k4 }& Y: U+ a7 ?' Y
  26.         }
    , ]; c( y! i  e; R  Z, v) x
  27. }$ T; S: k8 z2 A; s+ h7 Y9 U7 @
  28. 9 F; O3 u* N0 T" l
  29. use animal\dog;  1 n) {6 C. w: q% G4 A1 H
  30. new dog\Dog();
复制代码
- {1 w* I6 H3 H8 f5 d. Z
如上,使用了
  1. use animal\dog;
复制代码

1 L4 o# ^& s) i, g! `0 k
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

; }; r' Y7 R2 [  D0 O
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
: [5 E; ~* e. ?2 L  N

# g( p+ s3 D5 K9 y) B3 ^/ W# O! x- N) f2 s8 e8 z8 t0 d

3 j! {1 G& y. V/ {+ d/ }' y7 F% U' g1 k4 ^8 _
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-6-19 22:30 , Processed in 0.053270 second(s), 19 queries .

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