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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。

  M. d, |( E2 s+ H5 t6 |+ \
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
" w6 l$ {) J% Z7 _; f" u
4 b4 c  T( P. @$ I& I
使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
( u9 R7 a4 j( s- b" {
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
$ w4 C) K+ ]  F, s
结合使用方法来进一步理解它的使用目的吧。

0 y1 a  g, v! b6 _, @; N3 Z3 m
$ ?  D$ l' e7 D/ r) v! unamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    . D/ |( x! ~0 u9 ^+ v+ x/ G+ [
  2. namespace One;
    5 G- H/ F4 d6 H# [
  3. namespace ONE;
复制代码
; j3 E5 f/ I- r" D$ w+ S
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
: g  H  W9 e! G  L
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   6 j( X0 p! R% t; x: c6 O0 C
  2. class Person{! x/ k) y) T) ?
  3.     function __construct(){
    ) S( d4 k  R7 k% Z1 |' B* D
  4.             echo 'I am one!';
    / R& M0 N4 F: ?% Z7 t8 k6 x  }5 A
  5.         }
    3 }0 V1 k/ z2 H8 P' r9 f) N( t) w
  6. }
复制代码
  1. //name.php3 ^' l1 x7 X# ]
  2. require_once './1.php';
    + ~9 m% k6 f3 g

  3. 6 w3 w; E" ~* c* t
  4. new Person();     //输出 I am one!;+ Q. {8 B! l, B& s; }6 o6 e* Z
  5. new \Person(); //输出 I am one!;
复制代码

" Y  i( Y6 z6 v4 C% a: m+ ~3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    5 q& _6 e" k2 `6 E3 V& ^
  2. require_once './1.php';
    * Y6 Z& y: Y9 s+ T
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

4 Z' y  T* Z- t8 N9 b4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   ( {4 M) y& U6 j0 b- k
  2. namespace one;
    , ^! v$ R- A1 R/ @
  3. class Person{
    - Z4 i& V8 M+ ?
  4.     function __construct(){3 N8 V# Q% m% \5 c0 O
  5.             echo 'I am one!';
    2 u3 C, W, n7 e& R" J* k% s: B
  6.         }1 O6 a  L/ l7 V/ |
  7. }
复制代码
  1. //name.php6 s# |+ i6 Q  O6 m
  2. require_once './1.php';% j1 C' _: E5 P% [0 w
  3. new \one\Person(); //输出 I am one!;: k6 b# d! c) u' o
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
( B5 n6 |8 T" h
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
1 q# r$ f) W7 E
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
" Q& W' N+ O0 {1 w0 }* J( y
  1. //1.php   3 v" Y) t" t2 ]+ ?+ h/ ^% c
  2. namespace one;
    & z0 ~" W: s/ I# M3 N
  3. class Person{( @5 w  L& @: T9 o2 F, _/ N2 ^
  4.     function __construct(){
    # Y8 C7 O+ g4 L9 o# v3 v
  5.             echo 'I am one!';
    # x3 O/ C# g9 ~8 r# m$ N. q
  6.         }7 `6 z& o7 d0 p4 [& L5 u
  7. }
复制代码
  1. //name.php
    % b  u; o& ^2 c9 u$ R8 Y. s5 T% t: h
  2. namespace test;9 y, {5 I3 s% L4 {2 a' W- J
  3. require './1.php'; 3 P5 o; ^7 n( i1 w' d
  4. new \one\Person(); //输出 I am one!;7 F5 d; }, _) I6 I$ S7 `
  5. new Person();      //这里结果会是什么呢,猜猜看
    1 s1 U. `2 D5 {0 s# \8 A: @7 O
  6. 最后一行结果报错:
      I  p. ~/ F0 b! ~
  7. Fatal error:  Class 'test\Person' not found
复制代码

/ a/ W8 c( P0 q0 ]

3 `  \6 R0 t: q% B7 v5 A首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码
5 v& ], K% W) }9 \6 ~( P" i
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
) R- a8 ?8 M# V* k5 t
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php
    % j! T0 n, I4 [1 P3 T8 M
  2. namespace test;
    . M; }" u; c; C
  3. require './1.php'; * M& n& E$ _& N8 K, j

  4. & E( j" E4 A9 l) }
  5. class Person{
    ( \; H# s* z, e9 b* M2 `' @
  6.     function __construct(){
    . `  r5 B8 J6 |0 D4 ^
  7.             echo 'I am test!';
    4 N. s( N) _- @7 c
  8.         }
    : z# P  ~6 {2 ^1 |
  9. }
    ) `# b# c4 E) G6 `4 H- ?+ o

  10. / ~; R$ M9 A% H$ e! H
  11. new \one\Person(); //输出 I am one!;
    $ M4 M6 C$ }* k$ Q, ~( O9 v
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码

( e8 E$ U- v* [4 i3 K+ z" q9 a
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php
      A# _4 _' u6 U
  2. namespace test;
    : A0 d8 T, |6 }( J
  3. namespace one;8 h) q, ?" ^% h+ u1 b
  4. class Person{* J& ~) I* q" |+ j
  5.     function __construct(){
    . Z: J; \' P% f9 c( F
  6.             echo 'I am one!';
    4 i9 y6 z0 D7 k
  7.         }  w( D- D! D- m6 Q
  8. }
    / v& b: c: y( J" ~+ P* g2 d
  9. ! w. H( \( u5 N; I, g
  10. class Person{
    7 I/ c+ P2 G! I; n$ T$ H, [2 z
  11.     function __construct(){
    % u8 T; d5 e5 x; Z7 }( K
  12.             echo 'I am test!';
    / \# x# N" [5 X/ X2 i
  13.         }
    9 m. I/ m, z* G4 s4 D( B. Q- k( B; `
  14. }
复制代码
) |0 r6 S' ?5 a# G
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
; z2 W9 Y, J1 C6 ~& J
看来简单的把require理解为替换,在这里行不通。
( C( A" ?0 J, b+ P
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。2 ]* M4 c' a# ?, c$ M3 Y
  1. //name.php
    + [4 I: v; S7 T0 r/ X9 I0 x9 J

  2. 3 O& I: m" t- ?  Z# R/ W6 ]
  3. namespace test\person;
    , t7 k" _% [9 J0 n' h; c

  4. : k) D# y2 e! n& [" Q
  5. class Person{; l% o: a9 N3 R2 P
  6.     function __construct(){$ G& Z& Z9 c1 _9 m, s7 {
  7.             echo 'I am test!';
    1 o7 I* w) g7 j. s6 H1 U
  8.         }
    $ X, c6 F% I. E, B: z$ P
  9. }
    ) a1 o( o. P* g
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

' W' ~, p2 S0 h! p, r2 m7 o
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。

# N" Y: I. L7 c1 l% u2 X* v7 x7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php$ @$ }2 ~' k+ S2 ]6 D

  2. ' S( e5 t! V( g+ S. Y1 a2 J) V
  3. namespace test;7 K8 b2 R; A" `) D
  4. echo 'zhai14';0 H' Z6 [9 M. n( ?5 m0 X
  5. namespace zhai;
    " ?  X8 x7 u4 i" z$ z
  6. require './1.php';
复制代码

  {1 s# F% D+ \' d& I4 m
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。
! \0 a2 u) S% @7 x
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& }8 Z1 y8 {: G3 J- c# N, A
  1. //name.php
    8 _8 K* Z$ B& d

  2. " R# }4 A* P# q" \: v
  3. namespace animal\dog;- B  m3 U. o% r2 o2 s8 l( V+ d% v) d

  4. / @0 b; O7 n5 p
  5. class Life{* t: ]; N9 ~% t7 K) [8 @8 {
  6.     function __construct(){9 m6 e: k$ C4 ]* I4 D
  7.             echo 'dog life!';
    % z$ B1 t1 }2 u8 q% v" M
  8.         }+ ]+ E* B# i& C; t/ z1 X$ Z
  9. }4 w; z, W6 T; y9 s

  10. # ]: S. o. Q7 v8 K
  11. namespace animal\cat;; ~/ R3 F! V( r* p. u/ M7 A
  12. # r% \% ?, x- \& o% @) {
  13. class Life{
    ! x3 n8 M, ?* K! g, z0 w, L
  14.     function __construct(){& b5 M9 c. e$ |- a; f; b$ \. ^
  15.             echo 'cat life!';
    7 Y/ ]& ?  u" ~( d$ f. r' K
  16.         }
    / I0 ?9 Q, L& Q7 Q
  17. }
    * I: T1 X0 k5 r" g. [1 v2 s

  18. % I! h& h; j0 g6 l& i6 X
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间8 v" O8 G  Y4 d: k  {1 `
  20. new \animal\dog\Life();  //A
    7 J7 X5 c) p4 e
  21. / ]; x% B6 Q& g% w
  22. use animal\dog;  //a) O7 p: Z  L8 s  q0 l
  23. new dog\Life();  //B
    0 Z  ~' C9 p1 V- S  G  A7 o' y
  24. 8 P4 x$ p0 ^( ?  Z
  25. use animal\dog as d;  //b
    ( b' }+ I5 h( @1 _9 j
  26. new d\Life();
复制代码
( m& ^+ j* \. W' V- E
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠

- A5 k7 i! ?4 V# Q6 u; B1 d
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码
7 |( w7 p2 D! l& ~/ z- ?* }0 Q
相当于
  1. use animal\dog as dog;
复制代码

' r' l! d7 Y' S0 U4 d2.namespace后面不建议加类名,但use后可以。$ S2 T9 x" u0 f. N' O. G, c+ Z# J
  1. //name.php3 X' r4 s% j+ Z/ t1 |
  2. ! i  F3 Y8 B1 |& n) d% c: m# e& S' A
  3. namespace animal\dog;8 [8 ~( F" {; \) p- V. p+ \1 l) U
  4. ) a5 e" z4 ^" r. F
  5. class Life{
    1 }/ g8 `# Z( u8 P7 f' S  C+ v4 v0 @
  6.     function __construct(){3 E1 v  }$ t* \' Z4 w. f' _$ p
  7.             echo 'dog life!';. W+ ^2 c8 n6 a8 A+ U2 X7 N
  8.         }9 U; Q! u7 n6 q
  9. }8 |& z+ t! `! ?( x5 \
  10. 0 V# r6 v6 l. j3 b9 d( E7 G
  11. namespace animal\cat;
    ) H, z: L* {' l6 H" N  q7 D

  12. 3 C* Q2 |0 I! ^# k0 s
  13. class Life{% x5 J) g( @+ z9 U) o; W6 W
  14.     function __construct(){/ x  W8 {* C3 c; ]+ v. n
  15.             echo 'cat life!';% J/ _- Q! D# s7 A* P
  16.         }
    2 w" ?8 Q. v8 ^4 ?, _
  17. }
    - K. @+ k! w* T7 m
  18. 8 b, r/ M; X( j, f& {$ ^
  19. use animal\dog\Life as dog;  / h4 I  G/ o# a& {5 k# `
  20. new dog();
复制代码
0 h% O! k) _( n8 Y
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
$ w* C$ o, R6 Z& B4 s
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php
    : V( k6 r* D( |$ ?$ ]' A. u4 t

  2. 9 ]! U- s$ d% j: A1 E$ E9 A* E/ c
  3. namespace animal\dog;
    7 Y% U3 |+ K* t

  4. 9 {; z) D$ K- _3 Z% h% O: t
  5. class Life{
    ; L5 a. Y2 @  i* q  N0 Q
  6.     function __construct(){8 G3 n/ x. {5 W7 q! f. E; _
  7.             echo 'dog life!';
    $ s( d' g4 ^( u+ v2 {* R/ I
  8.         }9 r. K/ @" p2 l+ M1 [" I! d
  9. }1 l6 m  K: p4 O: ~8 H, s# Z9 b
  10. class Dog{1 f- @" J8 Q) }
  11.     function __construct(){% l9 Y, u1 H5 w, b  {
  12.             echo 'dog in dog!';
      x- T/ M0 \( F$ u- _2 c
  13.         }
    ; h. E2 _' J' d: j
  14. }0 k8 @! Q+ V1 r9 ]7 i2 h
  15. 7 E  g; X' K4 P9 v
  16. namespace animal\cat;" a" u6 n& o0 p$ H: O2 l* m7 X2 Y
  17. # q) Q' E0 {& w) l. d/ M
  18. // class Dog{! Y0 G6 x' n2 G: a
  19. //     function __construct(){) O7 ~7 i' b3 h6 |" N& U6 y% z
  20. //             echo 'dog in cat!';
    2 `( ]& D$ y8 v+ g1 C4 t
  21. //         }
    9 K( V. ~2 w) K% X  h8 s7 P% Q+ }& i
  22. // }7 S3 p+ b8 o1 G, g5 |# ^8 \$ V+ {& k
  23. class Life{
      w% o( g6 {; s/ Y
  24.     function __construct(){
    $ C1 m% [; o8 z! f
  25.             echo 'cat life!';
    * ^" W0 t$ r& X' s0 x5 ~, Z$ A
  26.         }
    . B* w  [3 v8 C5 `. g  I4 f
  27. }! {. [& d4 O' X6 [- ?' G* j; S
  28.   M, \* M' p, g! Q* x% c# k# I
  29. use animal\dog;    F/ @+ E# S& T: I: O% O
  30. new dog\Dog();
复制代码
7 u! ^" x' v2 Q, m+ K( q
如上,使用了
  1. use animal\dog;
复制代码

8 }! G$ z# z3 ?1 {
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。

2 x! ?( \+ |$ ^0 [1 V% ?) Z
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

! T# P' |' r& H( j) g% _& m4 L7 {2 k9 x. P) Z- e' m+ ]2 \

& b$ r: o$ E) v* u& t2 |0 z  b& y* h9 f( }/ g
3 d5 {: O( N" y2 ?4 e8 N$ C( e; o
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2026-1-30 08:10 , Processed in 0.057419 second(s), 19 queries .

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