|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。 ; X: I+ |5 i2 |9 n: C% c) {
文章大纲: 使用namespace的目的 namespace的使用方法 使用use的目的 use的使用方法 ( k9 S$ }% @+ r2 D3 F
4 L- @& s9 u+ J* E ^
使用namespace的目的:团队合作项目时,避免与团队其它成员新建的类发生冲突;个人负责项目时,避免前后新建的类发生冲突; 2 |4 j$ b* c9 I3 z( U
据个人理解,用到所需要的类时,需要先require或include引入,所以会发生类重定义的错误的前提是:两个相同命名的类都有被引入。目前有些php框架会自动加载(即include)所有新建的model类,所以为了避免你新建的model类和项目框架原生的核心类发生重名冲突,采用了namespace。(想了想,与团队成员新建的类产生冲突应该通过沟通避免,即使事发后也应该重新调整类名即时维护,避免后期造成因为对类的理解混淆而带来维护上的复杂度提高)
3 c% `$ H- z$ g+ g$ h结合使用方法来进一步理解它的使用目的吧。
% ~7 u# |. P0 a& K' \7 N; m( J% m$ e+ f3 r
namespace的使用方法:为了进行测试,我将创建3个文件:1.php和name.php(此文件用来执行测试),后面将不再说明,请自行注意代码的变化。 1.namespace后命名的定义不区分大小写- namespace one;) N# z. A7 j, b, [
- namespace One;: I7 d! c! Z* ?. |" t7 X
- namespace ONE;
复制代码
# Y" E4 W [ E5 @2 _如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) 7 P, x; a& B/ @1 x2 @& t5 ?& D
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 0 R) q7 e: ~( [/ g* X+ p2 `0 F2 w
- class Person{# K! E7 q. u0 V) i- A* j
- function __construct(){
9 [9 N8 ^/ v; h" l - echo 'I am one!';' }, C& C( s1 b
- }9 R. Z# D+ O( x6 A6 s2 O
- }
复制代码- //name.php2 a7 \- S8 e& i# W0 a
- require_once './1.php';
, s! j- c- X6 t4 }- B
& U8 w$ }; g5 P6 Y5 [* N, z- new Person(); //输出 I am one!; f6 g& m7 d0 P: h. I p* a
- new \Person(); //输出 I am one!;
复制代码
]' k+ M$ f' \3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php( N& t1 H: I" N9 e: j/ ?: s
- require_once './1.php';4 D) h& X3 P8 f" {( Q0 ~1 B
- new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码 1 M- n& f. ?- V
4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php
1 T! c3 z6 r% Z" ] - namespace one;
9 [$ v: D5 g% C& ~' _, d; ^ - class Person{$ r! Q7 X& ~# X, @
- function __construct(){
" T+ p( G7 h N& ^ - echo 'I am one!';( j( L! j/ {; ^5 @
- }
1 A9 x3 n6 L/ z. O/ u - }
复制代码- //name.php
7 t# i# s% ?- t2 i# \2 F5 l - require_once './1.php';) E; i; i0 x. m. R1 p/ V
- new \one\Person(); //输出 I am one!;
" Q. M* C+ C: e X' }" \ - new \Person(); //代码报错:Fatal error: Class 'Person' not found
复制代码
; e( I, T8 E& R8 _' b% Z可以举个这个通俗例子来理解:带上指定命名空间代表某人的苹果(在他手里),顶级命名空间代表苹果箱里的苹果(在箱子里)。现在要找某人的苹果,就将某人的命名空间带上,否则就会从箱子里找某人的苹果,结果当然是找不到。 3 ^. \3 G! W, P! m' ^3 c
5.命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。- Q! i. I3 D2 o0 V
- //1.php
# I* D' d- B' K# L - namespace one;' S5 Z6 q q2 ]/ D: h7 N5 O
- class Person{
, |2 D8 r! X2 E: D8 |: y# h4 O - function __construct(){% X% T% Q" ~' R- i k
- echo 'I am one!';' |9 p! D. `- ~; p; c7 s9 H% H
- } G* b. Y- g l
- }
复制代码- //name.php
& _8 k3 S5 K2 \, h4 _. k - namespace test;
( G) q4 n# S' j3 j1 [ - require './1.php'; 9 R( g* j- x* U. s
- new \one\Person(); //输出 I am one!;( Z3 B p# g; Y9 h8 Q* p
- new Person(); //这里结果会是什么呢,猜猜看
' I! E" J; t: c& T( [; @" R* L - 最后一行结果报错:
( }$ h( _( r3 g s4 u1 ] - Fatal error: Class 'test\Person' not found
复制代码 ! f* a2 M* B1 Z: X- R: w2 D
3 [( X5 ~" I0 U) ^
首先,这里与第2点比较一下: 第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 * H" m1 a, T d! M
结果报错: - Fatal error: Class 'Person' not found
复制代码
, X; E, ]% @- S: X9 c接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
) e7 r n; v! ~( g5 \. i' |* j* e - namespace test;9 v) k, X. V" |
- require './1.php';
6 R" F( w2 y$ l- `! U4 v
' w1 n6 J3 n* x' b; s- class Person{! N9 J' ^; v6 t% a
- function __construct(){ u; j) v# Y# h3 u' u8 m
- echo 'I am test!';4 Q6 Q3 i4 O) Z' b9 r
- }
6 F: v) Z5 I. `3 Y9 r; @ - }
n; b% }: g1 S4 K* |) [
9 C7 v( ^; Z8 w2 W# J9 l- new \one\Person(); //输出 I am one!;
8 k+ x( j' m% e - new Person(); //这里结果会是什么,自己猜猜看
复制代码
+ X2 o8 B( b2 o0 d1 k最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php; u! q' x5 h" u, F( | G8 B$ \. @! Z
- namespace test;- b( y1 f6 E- r7 r
- namespace one;
( W4 w6 F( W& h. U, v - class Person{
! J' @$ J1 R n - function __construct(){& i; l- Q( P. x y8 E$ Y2 b: O* H
- echo 'I am one!';
" T* L2 a" N: r$ I; m - }4 D i; t) s6 X y V v2 Q
- }
% }4 R2 \' G( g5 A+ N6 D - . d# i, i6 {. N
- class Person{5 W3 P: B; v; w0 n8 e$ h6 C
- function __construct(){$ o* j, L1 `) f. a7 D; I
- echo 'I am test!';
$ s7 B9 ^) S' G% O% p - }
0 J J* }0 h; J2 s# R - }
复制代码
" A/ S3 o8 K4 Z+ G无需new类,该文件就会报错: - Fatal error: Cannot redeclare class one\Person
复制代码
+ }, E1 s: R* D' u2 ?看来简单的把require理解为替换,在这里行不通。
' D- O, z2 ~9 C- b$ ]( i6.namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
5 g7 ~" ^/ }) g" p, o+ x- //name.php
* H& q: {5 |: `! d% a
/ K) ^8 \7 B M- R# w* X- namespace test\person;" G. `- |& c6 ^$ U8 M2 }! G
2 i7 S r6 M: l* Y- class Person{
2 U/ H# m7 A9 w+ Y6 T$ X - function __construct(){
9 U1 U8 t5 v; G: I" g; T - echo 'I am test!';; b# I! K; Q; [; T* D3 B
- }2 F9 i0 S$ {; T* ? k- o5 f7 P
- }. S" v4 W' ~; j4 u
- new \test\person\Person(); //命名空间里person无法代表类名
复制代码
7 p, h& q) \9 l8 p: M: g不过这样纯粹是画蛇添足,直接干脆点,namespace里不要带类名称就好。
/ i. k. q) ^1 L! A! I7.一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php( r$ I+ @- L8 Z
- ) I+ }& y" f, J, B8 Y
- namespace test;+ ~+ L4 d3 F% Q6 a
- echo 'zhai14';: X% w" s- }* r. e5 T& U) u
- namespace zhai;
* H2 z" C1 X5 f- v4 v7 U - require './1.php';
复制代码 & W: x* y( z- w3 b/ `
php命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。
r7 n9 W0 R6 @" Duse的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
' Y( Q2 e: d4 j9 S3 i# a/ N, e2 ^: [- //name.php7 x- i# V+ n7 W( ]2 X& h
- ; a( o9 \0 o3 }* N
- namespace animal\dog;
$ u9 `; ]: o; F) b" k2 _2 O2 M
Q I# V( A6 \# {( D6 t4 X1 s8 Q& N- class Life{
) {! k! j9 s) p. `- q/ y - function __construct(){
3 R. b, w/ @# u* v/ Q; P( i4 u - echo 'dog life!';5 L8 J. V: _8 J6 [4 l3 K; q6 t/ n
- }
3 Y% f$ Z& B9 |8 w1 S1 I, r - }. s0 G/ F7 O; s( J% P
2 f( K6 E5 A% U. ]% k \! P7 F: ^$ V- namespace animal\cat;
* u# P* K5 i& c: c9 c
0 [! U5 s( @" D+ V& `- class Life{/ P4 ~# N) `% J2 S% K7 Z( D
- function __construct(){7 Y% P$ ~. O) ]3 U% @+ j9 m0 P+ A
- echo 'cat life!';! G' }8 i. u, G" u2 C5 c8 p/ I
- }* s" @& r( g/ f& p G1 U
- }- b `- c0 [2 X( O! q0 X3 N
, K1 K, B3 j8 z' {- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间( l+ }0 b! c6 S( e$ ~& i) @. O
- new \animal\dog\Life(); //A3 N0 G% T1 z3 ~- j; b4 X5 w
- # U7 r5 j* w& X+ H
- use animal\dog; //a
b% H R6 E1 Y' \ - new dog\Life(); //B: S, H$ |% J& f& {8 N2 t1 p$ r
- + g* F3 \/ p' y1 J/ Z
- use animal\dog as d; //b/ O- h5 U1 S1 P; K, M
- new d\Life();
复制代码 : `$ l( o, \' U# O
通过A、B行代码比较,需要注意: 使用use后,new类时,最前面没有反斜杠。 没使用use时,命名空间最前面有反斜杠
h: o( I3 d/ w5 W+ {2 X通过a、b行代码比较,可以理解: use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: ' x5 G" N4 s- C( G3 w" t# x
相当于 . M% b' f2 R2 K+ }9 V) c
2.namespace后面不建议加类名,但use后可以。
$ E2 ~! ]4 F2 C5 u, |- //name.php( L) u( h+ t3 \8 t
( r$ f9 R6 q1 N9 n# @! @- namespace animal\dog;; [$ O* J5 i1 m* r1 H/ b0 g
/ | K8 V4 x$ Q. R5 A- class Life{$ g: p0 ?0 W+ k0 b A: [
- function __construct(){8 W1 K8 M' A7 O
- echo 'dog life!';
4 ~* F0 ?: u# P5 |! o j6 m - }
3 n# w) T* I2 ]2 C2 U! W& g. ^ - }
" u; ]5 F8 h% X7 g6 _
% {7 ]4 i4 [6 S+ h* Z- namespace animal\cat;/ {, Z/ r7 C) ^6 h
' c) j( m) e4 G, Z" _ G5 F: ~- class Life{. s0 ?4 j, U4 c9 T* U3 ~. Q; d1 {6 f
- function __construct(){ t% F0 \7 ~7 {2 e( c
- echo 'cat life!';
8 Y, t% D+ R+ S% P1 C8 `2 u - }
: E+ ^, K* c7 f8 n/ s, y; F+ G - }6 e/ ~2 W* d5 _0 \
- 9 T) m S# C+ ?
- use animal\dog\Life as dog;
& X4 o. |! S% r* k - new dog();
复制代码
: i% ?' ] ^: d& P! d如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - Fatal error: Cannot use animal\dog\Life as Life because the name is already in use
复制代码
3 p1 \+ B. v9 p因为cat下也有个一样名称的Life类。 可以理解为,使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
, R9 J- Z, |2 `( j9 d6 v - " J# C( p( W0 |( Q6 G
- namespace animal\dog;
2 b$ i3 d& |& q; o - . [. N" p% K- ^& y ^' T! v1 c
- class Life{
1 F; o* K$ n6 R# c5 { - function __construct(){# F# Y3 M. L0 _0 D
- echo 'dog life!';: [ g6 ]7 E+ E: H' @) g
- }
6 r; x+ N) ?2 t. R5 Q2 [) b# ^ - }
4 J- d* S* t5 \1 \ - class Dog{+ N. j* ?5 e8 o0 B+ Z- L' Z
- function __construct(){
4 f- f" Y+ i, S8 | - echo 'dog in dog!';2 H1 |2 i I1 S# h* a
- }
2 {* a, A* p* i% k- K' g% i) X - }
* y( s9 Z3 P& O% @' e1 _+ i
# `7 w% ?( e" f* N3 e. w. V( ~- namespace animal\cat;
+ x: s# T. W, V: W' k
" u7 H [! s% _" l* Y- // class Dog{5 R% j9 j( r, r: L
- // function __construct(){
) Q" i- t! v9 Q! @% L; |+ s5 ?( T+ j - // echo 'dog in cat!';
( j& [: a$ I4 Y Q - // }
; @% D9 _7 ]$ Y, {9 b0 \ - // }
+ X# ~# V* N) T& t0 ?* s - class Life{) v+ K k5 b' }! g4 j
- function __construct(){4 _6 Y7 }( g. d
- echo 'cat life!';) K7 @% @7 R; k; |5 ?% j& T) a \
- }
" I# _6 j- Y8 d0 f s6 @ - }" Z' r, t, h# p9 R1 O
- Y: O' h1 s3 A4 S: U& }2 g- use animal\dog; & n5 Q, ]! } K" m% k7 m S- G
- new dog\Dog();
复制代码
" {9 @5 N- l8 s$ D' o- T x9 b z如上,使用了
4 Z1 V& P0 }" qcat 通过上面代码,我想使用use的目的效果(缩短命名空间名称)就很明显了。 ; Q1 L; l6 [- @8 s7 _
简单总结一下: namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。 use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。 + e/ J/ y. ^2 [5 ^; `1 n
0 O+ L8 e# n* g0 K1 j# H3 N6 P8 z) b- C* o' I8 n# m2 S4 x
. |6 u3 W/ D# S |2 ^! R- o+ h
. R: O! t. f1 B0 u! A# W/ \* e& F
|