|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
, n! a! ?1 [* Y文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
6 p$ g0 k4 ^& E6 h" W! Q4 V j5 ]8 S/ L- N( F% u1 N5 I
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
3 r7 d& P* Y) E# J据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) ( J& { D( P% ^: \
结合使用方法来进一步理解它的使用目的吧。
# C: R* T; h" h+ r
$ D6 m1 S2 C6 }namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;8 ]4 ]% n( c b/ L d5 q* L
- namespace One;
5 O# y# y+ O( f/ Z, D. q r - namespace ONE;
复制代码 n# ~. ]5 f# }0 z4 E
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) $ A9 k7 m' \5 m8 N: z R
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php : `5 v6 i# L3 A! i$ H) S
- class Person{
% l$ g' O! K' s3 s1 o - function __construct(){6 d$ G) o' M% B& |2 K$ k4 w* w
- echo 'I am one!';8 F+ M+ ]$ d! N( t$ A- ~
- }
+ N) g" l) E" i1 e - }
复制代码- //name.php, q( I s8 ~2 S o9 v- c, n; O5 y
- require_once './1.php';) u* ? g' J8 z: Q- a( F3 s; q& _
- & x S8 b* `, x3 g4 B- ~9 a
- new Person(); //输出 I am one!;; |, p6 D; f7 S* `
- new \Person(); //输出 I am one!;
复制代码
( m3 |: _7 J9 y9 S3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
- f- `+ l5 H! d+ s3 ^ - require_once './1.php';
% z/ P5 p5 n& `5 m- u7 E+ M - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 2 m |7 B% ^* Z8 M* Y
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
' o E. F7 w, ~2 w/ |5 W - namespace one;1 ?" }- {3 ~4 U4 n& \' w, D
- class Person{0 p. u6 G$ k0 l0 ?
- function __construct(){( R* h+ x N; B* H6 k
- echo 'I am one!';/ t8 K; }; Y, d3 K
- }4 J4 x, p' f- ?5 L
- }
复制代码- //name.php# h0 U6 V% t; _8 |) p
- require_once './1.php';
) B* J6 O" {( G2 S- S/ m9 O - new \one\Person(); //输出 I am one!;
7 M8 N$ H7 `% K" K- Y }5 o- t9 C - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 ) _/ n* N1 h+ }, N, g! i/ |
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 + y3 {* ]+ G) C! }$ c
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
' `5 f/ J/ y5 ]5 }/ W7 X) z- //1.php
+ Q4 a: M0 x* k9 P; g6 ] D - namespace one;
# b! X& z b- K( ]1 `1 g+ N" t" Y7 P - class Person{
0 \* ]* S) S3 `4 W8 W7 F - function __construct(){
, m7 \+ I" ~3 K. `9 o3 h7 d1 a" p - echo 'I am one!';
- h3 \" z p& }, ^0 Q( L - }! y. V# M) C# n" i. g* h
- }
复制代码- //name.php5 l( x9 k5 `3 `+ `0 `
- namespace test;* V4 D# a: i! L
- require './1.php'; , x4 g! Z+ r3 z
- new \one\Person(); //输出 I am one!;
+ V2 q& P3 E: y, u+ H3 ?4 y- ] - new Person(); //这里结果会是什么呢,猜猜看
/ t. P5 Q$ M/ D. i2 @$ X9 Q& ` - 最后一行结果报错:% I- h- \ [; e
- Fatal error: Class 'test\Person' not found
复制代码
, j+ m" z# k3 ?+ w' ~$ k& Q, I$ x& D F( M8 O# M7 }
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
7 S0 P7 r; ]' ?: C3 {& M$ j结果报错: - Fatal error: Class 'Person' not found
复制代码 % q: A2 _- h5 }4 A8 e' J t
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
2 P8 t! V9 W1 m+ r6 f - namespace test;9 S2 H1 L2 k7 A7 @6 F5 I. W+ O. h
- require './1.php';
* _% U9 x- Q% r2 W - 0 z5 @% H+ s. U; v( w+ M& S
- class Person{; i9 M! b# A: i9 i% G
- function __construct(){# Y! w7 F* ^/ S& E: H2 g, i y+ ]
- echo 'I am test!'; K* v, Y$ }& g7 t+ W
- }
1 _+ D2 m, X" `$ e( B. r L - }
) v8 z; R0 a* H- [5 X$ l1 w3 T7 V - + K$ g2 Q8 _. \' A6 P9 h7 P7 U
- new \one\Person(); //输出 I am one!;
% a7 }) z) T" w' @7 f0 s - new Person(); //这里结果会是什么,自己猜猜看
复制代码 M: ]8 T# q1 a; j' E
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
+ a9 I) }+ b! z - namespace test;
1 h! {$ O+ s, H - namespace one;
7 ` f7 x' D) B0 d9 x$ z - class Person{- W/ r/ ^; y: ]/ I" E; g
- function __construct(){
7 b: k5 }+ Z+ l$ k2 h6 } - echo 'I am one!';
" H# [" V) {0 i - }: C( t' l& z6 U# H
- }2 T w: r7 |! ]' D, Z
( A. N0 }6 ?. A4 [- class Person{
& Y5 {; k8 s2 Z0 a8 p4 G$ u# b - function __construct(){ f6 @9 ]" h& J" @5 S. g: z
- echo 'I am test!';
K, |% }( K- n* B - }, T9 R: K E$ _! j" h3 R6 b( i, u
- }
复制代码
7 u6 A1 J) `% H; ^9 _$ V" m# w无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
" }& r- ]2 k4 s* ^看来简单的把require理解为替换,在这里行不通。 9 l" |6 k) W$ m, ^
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
" l* ^" ~ B+ }& o9 {- //name.php
/ K: W/ j0 ?0 V/ y% }+ v* W - ( G; K2 D- W# f, J
- namespace test\person;
7 l6 b7 k- l* P. g3 ?
1 @8 P: `5 y- c8 L2 U- class Person{1 Y T6 d% H9 G
- function __construct(){; ?2 x6 h3 Z3 K+ @
- echo 'I am test!';
/ I5 c# f- u6 D7 b) \& ~( y% P" ~2 a - }) |# c; ^+ d8 {. z+ s
- }( @- z' Z! s$ P7 E4 G1 G) _: w
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
% z' \0 w; N0 l" K( f- Y不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 c+ Z+ b1 ]$ l9 i# A8 v! N6 W
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php7 L4 H$ n5 U/ f9 n0 D
- n; C! N! X3 C- \8 [0 T2 h
- namespace test;
% r, h+ G. U/ m5 t$ J - echo 'zhai14'; V6 i' M7 ~, F5 r# w$ X5 b6 W
- namespace zhai; s5 \0 R u/ k; ^' f
- require './1.php';
复制代码 : P& }0 z) T4 J$ b. g$ `
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 2 G3 @. V+ M6 s' r4 V. _1 Z
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
v- @" R# I4 E! H8 O- //name.php
! g; a3 _9 u+ X7 |/ d* d+ Y - # [0 F0 e2 e0 J3 i( }. h3 [
- namespace animal\dog;
" `+ ^# n; _0 L
; s8 O- p$ k. E. @$ {2 O2 Q. I/ p- class Life{. I# M: A+ k$ V7 v5 b2 B
- function __construct(){
5 Z' ^) ~" E; W9 X/ { - echo 'dog life!';
$ u/ g1 K, O4 h) h: |. _4 h# Y - }: }/ Q& k! \; ^: f8 t
- }
0 {" l$ y f0 Y+ y) h" o. W" H - 2 x1 U8 Q4 E E9 K0 ^% e
- namespace animal\cat;
) b B( z+ v3 a G/ V7 y$ z - 0 g/ O6 C+ C) k Y: {
- class Life{
9 n) v2 J# p% [! |" |, a O - function __construct(){2 a6 [* Q/ S! F
- echo 'cat life!';, Z( ?" A, N' ~# \
- }6 G' `" V6 k2 q
- }: H! v" d) N7 u- v* R
- , l# `. i* }* y# t
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间7 @+ e. f+ `9 A6 M* z7 c/ W" M
- new \animal\dog\Life(); //A& q( d4 J+ P8 M+ B
4 S4 b6 ^1 B0 V; Q( |" D- use animal\dog; //a
& o0 U u* O2 q' l/ g$ u: G - new dog\Life(); //B
( T. u4 U* o- K2 j$ w \ - 3 C6 R, |( c* q% k( T5 E
- use animal\dog as d; //b; w# d5 V0 t; D" {1 a
- new d\Life();
复制代码 % Z# I0 x- ?, k$ j
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 . V9 ]6 ?% B, ?# V$ Z( t: g
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
) p1 _: d4 M5 E6 g+ v. T相当于 ( F( Q" P# h% o$ w
2.namespace后面不建议加类名,但use后可以。
5 x6 E$ c2 v/ v$ _ V2 o" t$ I- //name.php
0 f4 Y+ y( R- N+ Q1 U2 o) i - ( h! T1 c( v1 [- o' R
- namespace animal\dog;
9 \4 v8 l2 B6 M. o( Z. @7 `
& o8 l1 v/ f0 D$ h8 i$ N- class Life{* j$ l7 K8 Y; g. _- [
- function __construct(){7 g1 e. r/ [" R: C: z% H
- echo 'dog life!';
: ~) c/ e3 }: v - }. Q3 ^$ Y+ w! ?6 k! e
- }2 a' G5 |% p' D8 S2 {7 p- f5 S
# E+ U6 o0 u3 z7 s- namespace animal\cat;; a% t) B3 A7 V$ q5 i# i- s
! }0 w* ~% F/ y9 b0 i% V/ \- class Life{3 R* Q8 F/ v5 v* [
- function __construct(){
, w( ]8 ]9 K% g0 Z3 V! ^- ~) R - echo 'cat life!';
9 y/ f- L5 g+ X. u; N6 r - }
/ [# r2 I1 f- `, | - }' g h, `. ~$ q. N* J( y7 i
- + p3 E/ d% q- [
- use animal\dog\Life as dog; 0 e" I0 V+ I1 k+ c* r. ~! U9 I
- new dog();
复制代码 D( j3 H" l4 r% w, C
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码 ?5 N5 d5 z5 H( P. E d5 F
因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
; P( I T, `0 e: B! e
0 U3 ^: B1 G! U8 o* d- namespace animal\dog;( j) r7 l6 u6 N
- ) \) q) l4 h- F+ F" o
- class Life{
1 b0 B" m2 Y, e0 }1 ~/ x U, g3 M - function __construct(){
3 u5 i& B; p. H% @, a - echo 'dog life!';3 c8 w* X1 T/ x4 P' M) i+ ]
- }8 I- S- B9 d, M+ k" _5 E) L
- }1 Q1 g" N, x( _
- class Dog{
4 V) }$ u( J1 {% N, V - function __construct(){
* {3 F) v& A/ r1 {1 W3 ^* T - echo 'dog in dog!';+ U7 w# a9 R' t
- }
: d0 ?6 t1 g8 e; Z. P; q$ t4 E( S9 c6 g - }4 m, K, b% |* i6 t. L- H
6 ^* |5 t5 w4 V) H* q- namespace animal\cat;2 h4 \/ a9 }3 k1 [
$ Y. M+ w, _- Z- // class Dog{
7 f; @) W# M& f; i& M8 h2 \ - // function __construct(){
' O e+ P; `4 }. N8 q' ] - // echo 'dog in cat!';
* ~% b/ R" S1 X0 K0 o' f - // }; k0 r* Y+ S" ^ ?
- // }
0 k8 q, x) E' A7 V - class Life{
" c) `5 W* a& b! z5 c, Z - function __construct(){' e/ Q; Y% D, O W2 m, o) F
- echo 'cat life!';9 z6 H1 t* p" l) A2 u- t2 b
- }$ M' S* ?8 a& B- [; M
- }
: q& F( W5 P4 |6 M
9 {9 H; J1 N5 T1 C/ H7 }, |6 l- use animal\dog; ! G6 L) }- T+ R# Z+ I
- new dog\Dog();
复制代码 , Q) R% q2 U3 a' h
如上,使用了
7 O7 k" f' K8 t" a/ x! k3 vcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ! {$ n) p6 |! |) K
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
1 @/ A7 ]1 d# o6 N5 K/ }+ L
! y: T' t' s, N& h: g1 {/ I0 m* P$ i3 K- X
. Q4 ^" N' Y& o: I) Q1 A% C L- G4 Y$ j8 z7 M X
|