|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 7 v0 V m) a* U b$ x
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法
8 {3 K) }3 [, l H! r0 y( H& N
; f( A j7 b* S* w, N5 t8 z使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突;
6 x. T, u& T& L* I) n据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高) : d. ?2 g& x6 U/ F
结合使用方法来进一步理解它的使用目的吧。 ( A7 T7 e$ t. Q- r7 u- ]
. J# s1 c; f+ V
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;
6 M5 N: j1 U! n; A/ | - namespace One;; P7 V- G9 w2 A' b9 ]
- namespace ONE;
复制代码
+ s4 m" f! Y* K3 s5 b8 s如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈)
0 R( R; J* I4 m8 s8 s7 s2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php
. v, I6 R* ~" B* N - class Person{4 N* K- X6 O# l; b- f; }
- function __construct(){
: @) x/ `: q3 r" j3 B" W - echo 'I am one!';
) J7 n2 T' d8 h5 o( q - }
# |: p- V/ ]5 p5 x# N& n, Q+ C8 c - }
复制代码- //name.php& J# f/ V# Q3 Q7 i7 A- k0 _% E
- require_once './1.php';( P! G- a3 v) B1 s& e
- " P7 D' E# E8 a/ b" ?+ ^ P! s
- new Person(); //输出 I am one!;
% Q$ U& x7 ^/ x. z* x - new \Person(); //输出 I am one!;
复制代码 " P% O7 Y/ M7 L& H& v
3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
9 E1 G& u: C/ n5 g; }( i - require_once './1.php';7 [# b& x$ I5 k* X# ]
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 1 h& Q2 y/ \3 U! ]1 ~. s
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
) e* x9 C$ ?5 b4 {- G - namespace one;6 m; [& B2 G* o# d0 E
- class Person{
9 |' |7 q8 u+ Y7 ]' y5 j! I - function __construct(){8 A s8 ]7 D) @+ M, J# V
- echo 'I am one!';
, g* V9 F9 k7 @9 \7 v' B. e - }
- m( V" M3 p+ I - }
复制代码- //name.php
3 U' g) b- n0 N1 |, ], e0 J - require_once './1.php';
# L8 `# k {: x! K& s0 f - new \one\Person(); //输出 I am one!;; c- d r R% e! @% W/ _. g" H4 H
- new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码 * L9 y, a1 M7 c& Z& B
可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。
1 w& H% J, P1 W2 l9 n5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。) b7 h! b9 b, {- c+ O) S% U
- //1.php
3 X/ F; N( y1 Y( D9 | - namespace one;7 l! F3 L4 E, h* r" `; C
- class Person{3 k% P5 t: g" B2 W
- function __construct(){: F5 a/ i5 u( S% n; Z$ n9 y& z
- echo 'I am one!';, h+ B: K- P$ @9 J
- }
- y; s- J+ i8 C+ F- A$ j - }
复制代码- //name.php& [6 m! B g" y3 R
- namespace test;
; L* a% Z9 E& T4 U - require './1.php';
, Q; S0 L9 \, E* U# D9 T2 e! [: o9 n - new \one\Person(); //输出 I am one!;
% I) J* }1 [, y% O - new Person(); //这里结果会是什么呢,猜猜看# a7 ]% Z* k: h6 I* z3 `* V+ b' }
- 最后一行结果报错:( n8 r( h) q8 a: X$ L/ A
- Fatal error: Class 'test\Person' not found
复制代码 7 V" E3 Q8 U9 d5 c4 g! g, v2 m
+ V' H E( L( ], f& K首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成
* y& b$ ~" \, q* h5 ]+ ], Y结果报错: - Fatal error: Class 'Person' not found
复制代码
) @' }( g2 s. f% i3 ^/ Y! V接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
1 @+ I6 ~. a/ y3 R" _2 X- T; h2 O - namespace test;* i8 K& a: W0 x
- require './1.php'; ; q( `/ j7 i. ` e
* R. M2 D8 p# E) U- class Person{
, D S6 x$ |8 y+ U6 }5 e/ {, i) H - function __construct(){7 o ^( |/ Z( R2 h5 q+ N
- echo 'I am test!';
: U$ a) ^/ k8 }9 G8 b1 E* x5 o# ~ - }
2 |" k% X( F1 i$ n, ~ - }8 O7 f1 }: `+ ^4 ]
" f- N) n# t& [2 b( t2 p/ w- new \one\Person(); //输出 I am one!;5 X* h5 P9 m, p" L# w
- new Person(); //这里结果会是什么,自己猜猜看
复制代码 2 g; j9 h( S; l E* k6 o! |' k
最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
2 i9 M& f* C& m( i# u Y - namespace test;
: e& ?0 C1 j: m* T X# a - namespace one;' c6 \! Y; V9 }
- class Person{7 h. g* C: o0 q7 p' v& X! \
- function __construct(){& _0 [7 }) m! n$ p5 y. H
- echo 'I am one!';) {' u' e: ~4 ?, A) a+ \
- }8 y$ q6 e. i: r* ^0 m7 s
- }0 |" A/ V' X* t w) J
; t# ? I# {' X- class Person{
( r/ T* ~) Z! S! S1 q3 {8 p - function __construct(){
8 D9 L( v( i# j - echo 'I am test!';$ l0 `: J" b ?5 |
- }
, R; r- I9 s+ u' l' W - }
复制代码 8 A s' _" A, e
无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
3 W4 n' ?6 ]" V5 |4 F$ u, \看来简单的把require理解为替换,在这里行不通。 * S% M4 N9 B1 e! [ `
6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
9 j7 j/ h( O% ]5 W, s( p0 C- //name.php. v1 M- G2 j) p/ l* d$ U0 A
- v& [" z6 h5 f$ n: l, a- namespace test\person;
* N+ u$ K1 I8 F - % A9 K: G4 Q) O; J
- class Person{; b4 b! F7 d6 w, C9 k
- function __construct(){
9 U0 B) J! k% Y- D1 c2 T1 Z - echo 'I am test!';
- B+ k6 r! A5 q7 D3 s3 A2 ~ - }
* i# p; f: i4 D - }/ \# S" p$ f4 A+ c3 W$ e
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码 7 r- q5 r! E, o$ `1 r
不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。 5 b5 v$ G6 v8 |' e
7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php4 z7 M2 S, @3 e5 [" B6 Z
- ! M0 F" a; b$ n2 p: c7 X7 C
- namespace test;
! f& y% ?) @# E" N- J0 K; A( V& O - echo 'zhai14';/ a. q: C& V2 H k, J1 ^) ~& x
- namespace zhai;
x! P+ b! z4 z$ q6 p& t2 F1 A; y4 ? - require './1.php';
复制代码 2 J1 J, b+ o, J) F
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
8 s& S& U& ]6 ?use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
" Y2 C1 g0 n$ L1 p- //name.php
* @& A* i* i" M* v) _- S8 d - % s+ _/ Z, I; F5 i" m5 T9 G
- namespace animal\dog;0 [3 v2 S& O& g( e2 k' m
- & W* a1 K5 j0 G( Y, R
- class Life{
# ~$ [; w4 X3 i - function __construct(){
1 }- ~' h$ `8 C/ k; _- g8 _& Y - echo 'dog life!';
2 f) `9 y% b+ w* x6 z: G2 { - }, {( F l8 A: y8 L* |
- }
& g8 s8 h/ z+ Q- r6 ~4 X% h8 X3 G - . l9 `9 E! n. f6 I& D
- namespace animal\cat;/ b# s! L% I8 u, j# j" M0 T
- 3 Q2 e V8 ~1 g/ x
- class Life{
- j, E' ^) J& ], p& }! t - function __construct(){
7 Y& @- N# `( ^ - echo 'cat life!';
3 y2 f! ?: i6 N: j) g6 k% }- S* a; P - }
7 B$ o" ?$ g* @$ ]: B! ^! Z - }& _; C' l$ B% I0 f
- 1 ]7 ~, _+ p" [' G- n5 ~
- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间
# h; L4 L/ O8 d$ ?, ]: o7 y5 {7 w - new \animal\dog\Life(); //A: s/ t. Y) y; |/ ?1 |
- & b% Z* F( p% W R! E8 m8 b1 _
- use animal\dog; //a! N' F- `! U6 @% L6 t8 h/ S
- new dog\Life(); //B+ p- Z, f* w, F/ j8 n
- 7 w3 M0 }1 |4 f
- use animal\dog as d; //b
}' t8 q/ ~* A0 T6 f7 R9 ^ - new d\Life();
复制代码 % l4 G- z2 {( C, w# A
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠 6 }, i) f7 ]- a( Y8 m( k
通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
0 W& v. T2 H+ ]) I5 J: S2 U: W- z相当于 / E! y$ q# m! `# M" y
2.namespace后面不建议加类名,但use后可以。; l$ \8 t( j: O+ t9 q. ~4 }+ S
- //name.php
H5 a! t6 m+ [8 X% }6 c
. c! ?# T$ Z/ i1 ~( l- namespace animal\dog;
! J i) G; q$ T# I: Q6 p
5 {7 a* a$ F" }. m! Y5 A( m3 @& T- class Life{
$ w' g H% e. r, r( r - function __construct(){' b, {' F* f6 }4 |
- echo 'dog life!';) p! L! o V# z- @9 @! d
- }
" |/ U3 S5 r9 Z/ d+ h% X: @ - }
8 n l/ z# f! t) Q - V6 t$ O* P0 i& D
- namespace animal\cat;/ r1 q) O% \- R- v; {% n' a; q8 S* r9 g
$ B1 E) k1 p/ J5 _- g' q- class Life{
' i' Q5 q# R- f: {$ N/ E - function __construct(){
5 Q1 t6 H( o9 w1 X( M/ h: D4 o - echo 'cat life!';
0 Y$ x2 @$ s$ X( t. B7 C; b - }1 ^1 T' W v, l' N4 M
- }
8 T5 e; M$ _$ S
3 O k9 Q0 s0 M. D- use animal\dog\Life as dog; ; o4 M ^5 ~2 p, D
- new dog();
复制代码
9 N5 f, q' ?8 ^! o* R0 j如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
* _% Z* I7 K! S* t4 H: o; i因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php" r6 K) \- l O3 t4 o7 ?% e
' \7 C1 e% X2 O7 d! k- namespace animal\dog;3 h6 z/ r8 W# j1 n& }
- ( a1 F6 f6 a% W
- class Life{
% K2 M A4 r' ]3 s - function __construct(){. y* y8 r$ n' V/ V
- echo 'dog life!';
1 i( `2 @0 ~. o - }) ]' ^! h3 W5 `& X5 `
- }
9 Q5 p) [! l3 h- R. s* _+ b7 P - class Dog{
" g8 d# x9 }' \ - function __construct(){
2 X5 x9 Q, h8 w3 T$ K8 u+ c# y - echo 'dog in dog!';$ y% D8 w. P5 Q) N" K4 w
- }
( T7 ~. K% G3 `3 W' m - }1 v/ H' A2 u. j l ~
- , {( ~3 [; g Y- l
- namespace animal\cat;
) K+ Z5 }4 K3 Y% a/ \0 ~" p4 H6 l% h
! E- ^8 d. |/ [' H( K- // class Dog{1 C, r9 A6 q3 j
- // function __construct(){6 v/ w& [9 F. Q( a8 v; Z
- // echo 'dog in cat!';: g3 d/ {. L2 S& I- M$ v/ p3 z
- // }
. w4 g& D. }, X6 r9 W - // }
$ s& t1 C0 ~. K K - class Life{7 N# {- q0 i* j! y6 y1 ?4 c, Y
- function __construct(){! `9 |6 b1 N& x; ~1 c/ [
- echo 'cat life!'; F7 N9 z7 I, N6 ?6 E9 b" n
- }4 h7 e# ?, j( j+ X, Z3 i' R. O# C
- } e/ o! u- I" k: v: \; {
) S9 v0 F2 m& X* A8 u3 m- use animal\dog; , x& |1 p+ H! z( ?, S
- new dog\Dog();
复制代码
1 ]' O% V7 g' ?如上,使用了
9 l9 [0 q r' G6 x1 _- {cat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 7 K( l# d# n! ^2 }/ A; W x" w
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
! `2 K; v0 | n; |* b
, |; S: [+ n$ X( Q- I. f1 K5 @% S2 d4 k! ^+ i+ e _) v3 t
) y) L, V7 u& [* o' g2 _; s
7 A1 f) v7 |4 |( `8 l* A
|