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

QQ登录

只需一步,快速开始

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

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

[复制链接]
跳转到指定楼层
楼主
发表于 2020-7-1 23:37:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
: y( A! n7 M+ k" j
文章大纲:
使用namespace的目的
namespace的使用方法
使用use的目的
use的使用方法
3 b8 i) s8 e$ \1 M* y

# z) `- ~: ?: X" w使用namespace的目的:
团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
8 d+ @; ]1 _# @0 g/ X, K# Z
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)

/ }/ p9 b  U, n( i9 c: c! h7 W结合使用方法来进一步理解它的使用目的吧。

2 Y, m0 v" P5 C' ^- n
0 g6 t, x) L" i/ b! Y. @  D: wnamespace的使用方法:
为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。
1.namespace后命名的定义不区分大小写
  1. namespace one;
    ; o( [6 l: y( N; A% ^# Z
  2. namespace One;' t) u* [+ \3 q0 g
  3. namespace ONE;
复制代码

% B' _& B  |! M
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)

; Y$ w3 I! Y* [) ?1 ^2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。
  1. //1.php   ! v0 |3 I6 y" ?! Y
  2. class Person{
    % p) m. ~! ]1 v0 E, E2 o0 _
  3.     function __construct(){
    , Y9 ?5 f3 |; ?' n5 c
  4.             echo 'I am one!';: S; Y, V) _* g' y9 ]' E
  5.         }
    ) N0 l8 R8 H% q. z- B7 \9 W9 e( {
  6. }
复制代码
  1. //name.php
    6 G4 H/ \0 Q3 @% H( P( F
  2. require_once './1.php';
    5 k1 n5 J* N6 h. F6 j9 h
  3. . r! V. h6 [; m7 D3 M( s. ~
  4. new Person();     //输出 I am one!;
      y, Z$ N% Q1 H* F' W& @: L; T( }
  5. new \Person(); //输出 I am one!;
复制代码
) \9 P" J  y% T9 `
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。
记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
  1. //name.php
    2 Y5 m* [6 ^  j" q' h
  2. require_once './1.php';
    . b0 h2 t/ q* O$ u. p5 O
  3. new /Person();  // 代码报错:Parse error: syntax error, unexpected '/'
复制代码

6 o) D. d# f* I4.类在指定命名空间下, new类时,一定要带上指定的命名空间。
没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。
  1. //1.php   8 k  y8 g5 f. m/ e0 r3 ~
  2. namespace one;, l. G" d( r& p; Z
  3. class Person{
    + N* F& E2 y; l
  4.     function __construct(){6 Q. P6 u# W! w( K
  5.             echo 'I am one!';
    8 `) |/ G* }" t: {
  6.         }6 |! m2 Y# u3 U5 X
  7. }
复制代码
  1. //name.php
    . J8 g* k! l3 j
  2. require_once './1.php';
    + R) e, k/ E6 r
  3. new \one\Person(); //输出 I am one!;" T* q9 V+ B4 K- F4 |9 C% B3 `1 |
  4. new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
3 W& D6 }8 e7 d
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
+ B) z3 Z8 V& Z4 S8 Q
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
( N4 a% x: R' z: _  N
  1. //1.php   
    / a% n5 f8 e0 w$ |) R- ]- ^
  2. namespace one;$ u8 V% t( [$ `0 l, d. N& @# A
  3. class Person{
    " @1 j/ r6 V7 ~7 e6 ^2 E
  4.     function __construct(){$ j) \) I4 M) i+ w, [" G
  5.             echo 'I am one!';' x- w& R: Q9 n2 Q% u
  6.         }9 A1 s9 f: ?8 R; X. V: {/ h
  7. }
复制代码
  1. //name.php
    8 h! b! W3 T5 y$ q; `; A0 M! U
  2. namespace test;
    % H/ j3 O, E- j5 B) Q
  3. require './1.php'; ; f: d8 u; T5 }0 C( v3 E
  4. new \one\Person(); //输出 I am one!;# s5 f! Y7 u% @4 ?: w+ g% S
  5. new Person();      //这里结果会是什么呢,猜猜看
    # ]8 v3 e4 i1 p7 _( W1 [  H) h
  6. 最后一行结果报错:
    8 W" j* L0 ]: f" P
  7. Fatal error:  Class 'test\Person' not found
复制代码
; `! w3 @. `* c4 E; V
1 v& k( h! k: O+ Q% ~! W
首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。
在这里,有了命名空间,有和没有反斜杠的意义就不一样了。
最后一行换成
  1. new \Person();
复制代码

& ^% I* ]5 {2 _( ~) {# I+ [
结果报错:
  1. Fatal error:  Class 'Person' not found
复制代码
+ O* D  f2 d6 ~9 _) H
接着,就说说当前这点。
我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。
进一步加强验证,我修改了name.php文件如下:
  1. //name.php9 g9 ~0 ?1 k8 M7 W. k% h
  2. namespace test;
    * R$ Z' ^1 g: |, M6 e1 \
  3. require './1.php'; 5 e5 S: B- I! z1 {; e7 v7 w: u% A; P

  4. 8 z/ W3 h# {0 E2 ]' e
  5. class Person{, l) N; G7 V, }# Y5 s' m! {3 L# K
  6.     function __construct(){
    ! G  Y  ~( v/ s8 ?
  7.             echo 'I am test!';
    4 R3 ?6 s2 x2 G. h& g% L. A8 p
  8.         }
    , r1 K! B; {8 B9 h8 q5 u& A
  9. }
    : J( D7 [5 }; \: S/ G) Q8 f0 d5 ~
  10. ( j% q7 S& t: A
  11. new \one\Person(); //输出 I am one!;
    & v2 x7 d3 _/ r
  12. new Person();    //这里结果会是什么,自己猜猜看
复制代码
# a+ Q: u3 z+ L. `, W: G4 i) I6 [
最后,这个例子刷新了我对require的认识了。
按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里:
  1. //name.php( M; m7 @1 J' A$ c8 s- M  w
  2. namespace test;: \; e7 F" `# \. a
  3. namespace one;
    1 u8 p6 }# W/ `+ A4 _1 \# @
  4. class Person{/ v. E" D, _& w/ n
  5.     function __construct(){# d9 n( m$ i5 _5 C" ^# w
  6.             echo 'I am one!';
    3 t6 f1 S5 g5 [9 E% r8 }
  7.         }5 X% S, L: }1 z+ A8 ?$ E! y5 t
  8. }8 y1 t  C/ S" G7 w

  9. / n$ ~3 D% _& b4 V
  10. class Person{
    + U- I1 ^5 R) \# e9 \$ h2 Y. G
  11.     function __construct(){
    8 F3 {( g; l* O/ m( {; T
  12.             echo 'I am test!';& `- j* r0 f# ?) T
  13.         }) k" l! o' [, \! h1 h; |2 f/ x
  14. }
复制代码
" W5 }! q. q- R5 G& t7 {3 Q
无需new类,该文件就会报错:
  1. Fatal error:  Cannot redeclare class one\Person
复制代码
6 o' f8 j& I" s! f
看来简单的把require理解为替换,在这里行不通。
7 W! W9 \" S& r. `) i( _
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
3 \$ u# I# o( @" M0 ?
  1. //name.php9 d+ N; T. V$ n7 I, ?4 z0 W
  2. . b' t( E) j. e0 A2 [
  3. namespace test\person;
    & A6 a: k. V. F  h# a. d

  4. . b$ m  j$ o, W, W' H/ s$ Y1 a
  5. class Person{
    & b2 j% o7 k9 }
  6.     function __construct(){
    * K1 E# ~0 t6 o9 r) T& I4 D
  7.             echo 'I am test!';. `: M8 E* a, l
  8.         }6 E& o: ?; D5 \9 @, `; `
  9. }
    ) y2 M+ J/ k# U- F7 U
  10. new \test\person\Person();  //命名空间里person无法代表类名
复制代码

0 K/ ?3 a7 E. O
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
: L0 t+ m; }* u9 z  h  w, L% [
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。
  1. //name.php
    + C9 @. A4 f  P3 J, x

  2. / A! j7 u( e) M, G; g! A  F
  3. namespace test;
      e  i2 J* o9 ^5 W; E/ X* d1 j+ I% ^
  4. echo 'zhai14';
    " ~6 X' E% ~1 x, G, f9 D: b( \5 e
  5. namespace zhai;. B3 @% K8 V+ t' f& z
  6. require './1.php';
复制代码
) s  u7 y' f. I! _4 n1 G! A
php命名空间namespace告一段落了,接下来说说use的用途。
使用use的目的:
在命名空间字符串过长时,使用use可以相应的缩短命名空间。

, V  C& X2 ]0 nuse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。" @( o/ r/ v$ [" g' m! V
  1. //name.php
    ( f* b% |; G: k! O3 n. a1 ?

  2. 7 {8 M) y# U1 H# d$ K. _$ M. y: ]
  3. namespace animal\dog;0 H- a$ {# S+ v$ R' @% n! q8 i' V1 o
  4. , n" |4 b& Q8 o* k  f
  5. class Life{$ b7 V6 n9 j! v- N+ E) H9 X
  6.     function __construct(){
    $ V9 z) p# B% |+ N) d6 c: o* T. ?
  7.             echo 'dog life!';& B& H" S+ N0 Y. F+ H" ?# T- k% ?
  8.         }
    / E! a: A8 I( b% }" z( f# L2 A
  9. }
    / Q# {9 J3 a4 d, M
  10. 3 p4 m! \! }, D0 M1 T/ f' b
  11. namespace animal\cat;
    , n4 r6 V4 ?7 _7 ]: c2 h
  12. 1 H. W4 O6 U: b1 A+ {/ c% u; h
  13. class Life{
    : B+ G6 J9 u/ {( i" D
  14.     function __construct(){
    ; F+ U* o0 v. t6 s) y7 h
  15.             echo 'cat life!';3 y" h' \2 U5 I1 W# d, G! C1 }
  16.         }
    1 l3 L3 Q" N5 {2 x7 q
  17. }. N, B# G4 _8 K. [! s% ~6 Z

  18. 4 t2 L9 x* a2 f2 H+ u
  19. new Life();  //按照代码执行顺序,这里默认animal\cat这个命名空间
    5 G, C; [. y" R( Q4 q% u0 i
  20. new \animal\dog\Life();  //A& Z8 q) u6 J5 {
  21. ' `) z# V+ d2 i
  22. use animal\dog;  //a
    + [# ?5 |% _: s3 i* [
  23. new dog\Life();  //B3 ?. m2 [; h/ _" y+ j

  24. 8 m( p6 u5 \8 F& T9 o- L0 l* L
  25. use animal\dog as d;  //b
    / _, ^$ S/ Q4 b4 q, F
  26. new d\Life();
复制代码

8 c$ L: E% E  g3 R% H
通过A、B行代码比较,需要注意:
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
5 S. }5 Q& Q9 N
通过a、b行代码比较,可以理解:
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
  1. use animal\dog;
复制代码

5 P5 |2 k9 j1 U7 o1 M
相当于
  1. use animal\dog as dog;
复制代码
8 N' J( ?6 t& D: e% F* X
2.namespace后面不建议加类名,但use后可以。% I: [! e) t, P9 H8 R2 U8 l
  1. //name.php
    # O: B8 M- ^5 o3 L0 P' x9 q
  2. 2 K) b' T, a2 }6 G. h+ ^
  3. namespace animal\dog;
    ) S3 G% A5 D$ u" |, Z

  4. 9 d0 r9 q" ?3 `7 b; L/ u) y3 v
  5. class Life{- \2 F7 i; a# {! w+ w2 x4 G
  6.     function __construct(){
    ; t( H  u# E* @
  7.             echo 'dog life!';
    , N& p3 I( j) S& Y! d: d! U
  8.         }
    & O! O' }0 v1 ^
  9. }
    4 x6 A( K' J( A* O4 K

  10. ) N9 S4 E  a8 q
  11. namespace animal\cat;5 l( e' l& I  I

  12. 3 w$ H6 o* Z& b9 d7 Z8 z
  13. class Life{
    / s) u1 n2 i" E( H% v
  14.     function __construct(){
    2 z0 R) G  B% a2 _, C
  15.             echo 'cat life!';% d* n$ W" {$ h  D& K. A
  16.         }
    : o4 ^, k7 B7 m+ C' z- m
  17. }
    2 t7 s" N8 d: ?- d$ H

  18. 2 j- ~2 v! L/ w
  19. use animal\dog\Life as dog;  
    ( N- g! x2 T8 K4 N$ L
  20. new dog();
复制代码

" B/ z, ^/ X) t) g2 s2 M
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
上面不用as dog就会报错:
  1. Fatal error:  Cannot use animal\dog\Life as Life because the name is already in use
复制代码
8 Y) q; y1 O3 A
因为cat下也有个一样名称的Life类。
可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
  1. //name.php( _6 R# V- l6 y, [

  2. * z8 _9 ~! @, l% W* L; p+ X
  3. namespace animal\dog;
    % m* q" |  s+ F# m, Z

  4. ' y9 N. I5 H! M* `0 z
  5. class Life{. `5 d* P3 w- S9 X8 f
  6.     function __construct(){
    3 c0 I9 }. P( E
  7.             echo 'dog life!';
    . _2 r& }+ v% u( H' H
  8.         }* Z: H( ?" y3 w
  9. }" v1 _7 x! J2 D5 O
  10. class Dog{
    0 h% {4 [' E% K
  11.     function __construct(){( g5 V& z9 ?% D# J) w% h
  12.             echo 'dog in dog!';
    ( e6 s% A6 d" \$ p! k# O1 f0 ~
  13.         }
    4 P, i- {# \6 M. n
  14. }
    1 O! P& n2 e5 F  S9 L

  15. ; `% K0 _9 H/ X
  16. namespace animal\cat;
    9 {$ P. O; C, S* n$ I1 j' q
  17. 5 s! w* r' h3 d# `  D# _, R- S& q
  18. // class Dog{
    3 a% R% @: j7 d! h
  19. //     function __construct(){
    3 x8 o4 }- E- L7 D2 O  B% `
  20. //             echo 'dog in cat!';% _# }, `8 r  ^0 f7 d+ X
  21. //         }# c% J6 Y: A3 p: J9 L, B3 ^" v) A  l
  22. // }+ _: X" i# R% g" q
  23. class Life{
    / \$ f7 c) Z' Y, M0 e% |3 I8 b
  24.     function __construct(){
    & `- c0 Y& N( K/ L
  25.             echo 'cat life!';* M9 |' |9 m: {: }
  26.         }( u/ X% ^( N4 B; T% u  {# Y2 G" U
  27. }% _  a0 |9 g7 y; s! R9 S) p  }
  28. $ }/ b# |0 I* q+ }" z" L
  29. use animal\dog;  8 J. m' H$ I1 ~# p# j( r' X# }
  30. new dog\Dog();
复制代码

0 \; C2 P9 p: S6 [* ~
如上,使用了
  1. use animal\dog;
复制代码

# N) B' L. r- _" ]! `9 w
cat
通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。
, a- N: |. G( d+ B$ }8 O6 e0 w
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。

  I  O4 j; Y% j* a  k& E6 N; q& C# O$ E/ L* m

1 h0 @' A- y6 o$ ~8 D: g- N9 A1 w

/ h4 J6 w* L5 M$ j
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2024-6-26 07:35 , Processed in 0.114291 second(s), 20 queries .

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