|
以下皆为本人自我理解内容,如有失误之处,请多多包涵。
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后命名的定义不区分大小写- namespace one;
. D/ |( x! ~0 u9 ^+ v+ x/ G+ [ - namespace One;
5 G- H/ F4 d6 H# [ - namespace ONE;
复制代码 ; j3 E5 f/ I- r" D$ w+ S
如上写法都可以,选择一种作为自己的规范即可。(后面代码我采用第一种进行测试哈) : g H W9 e! G L
2. 没有定义命名空间,就理解为使用顶级命名空间。new类时,可以在类前加上反斜杠\,也可以不加。- //1.php 6 j( X0 p! R% t; x: c6 O0 C
- class Person{! x/ k) y) T) ?
- function __construct(){
) S( d4 k R7 k% Z1 |' B* D - echo 'I am one!';
/ R& M0 N4 F: ?% Z7 t8 k6 x }5 A - }
3 }0 V1 k/ z2 H8 P' r9 f) N( t) w - }
复制代码- //name.php3 ^' l1 x7 X# ]
- require_once './1.php';
+ ~9 m% k6 f3 g
6 w3 w; E" ~* c* t- new Person(); //输出 I am one!;+ Q. {8 B! l, B& s; }6 o6 e* Z
- new \Person(); //输出 I am one!;
复制代码
" Y i( Y6 z6 v4 C% a: m+ ~3. new类时,带上命名空间时,之间一定用反斜杠字符,而不是顺斜杠。记忆方法:按找%中斜杠的顺序理解为顺斜杠。(有时说反斜杠,自己都不知道是哪种方向,以前按自左向右上升方向这种方向记忆,现在感觉这个太不靠谱了)
- //name.php
5 q& _6 e" k2 `6 E3 V& ^ - require_once './1.php';
* Y6 Z& y: Y9 s+ T - new /Person(); // 代码报错:Parse error: syntax error, unexpected '/'
复制代码
4 Z' y T* Z- t8 N9 b4.类在指定命名空间下, new类时,一定要带上指定的命名空间。没有带上指定的命名空间,按照第2点,php就会从顶级命名空间里找这个类。切记:这里不能按照顶级命名空间包含一切其它的命名空间来理解。而应该将顶级命名空间完完全全与其他命名空间区分开。 - //1.php ( {4 M) y& U6 j0 b- k
- namespace one;
, ^! v$ R- A1 R/ @ - class Person{
- Z4 i& V8 M+ ? - function __construct(){3 N8 V# Q% m% \5 c0 O
- echo 'I am one!';
2 u3 C, W, n7 e& R" J* k% s: B - }1 O6 a L/ l7 V/ |
- }
复制代码- //name.php6 s# |+ i6 Q O6 m
- require_once './1.php';% j1 C' _: E5 P% [0 w
- new \one\Person(); //输出 I am one!;: k6 b# d! c) u' o
- 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.php 3 v" Y) t" t2 ]+ ?+ h/ ^% c
- namespace one;
& z0 ~" W: s/ I# M3 N - class Person{( @5 w L& @: T9 o2 F, _/ N2 ^
- function __construct(){
# Y8 C7 O+ g4 L9 o# v3 v - echo 'I am one!';
# x3 O/ C# g9 ~8 r# m$ N. q - }7 `6 z& o7 d0 p4 [& L5 u
- }
复制代码- //name.php
% b u; o& ^2 c9 u$ R8 Y. s5 T% t: h - namespace test;9 y, {5 I3 s% L4 {2 a' W- J
- require './1.php'; 3 P5 o; ^7 n( i1 w' d
- new \one\Person(); //输出 I am one!;7 F5 d; }, _) I6 I$ S7 `
- new Person(); //这里结果会是什么呢,猜猜看
1 s1 U. `2 D5 {0 s# \8 A: @7 O - 最后一行结果报错:
I p. ~/ F0 b! ~ - Fatal error: Class 'test\Person' not found
复制代码
/ a/ W8 c( P0 q0 ]
3 ` \6 R0 t: q% B7 v5 A首先,这里与第2点比较一下:
第2点,我说,没有命名空间时,new类时,有没有反斜杠意义一样。 在这里,有了命名空间,有和没有反斜杠的意义就不一样了。 最后一行换成 5 v& ], K% W) }9 \6 ~( P" i
结果报错: - Fatal error: Class 'Person' not found
复制代码 ) R- a8 ?8 M# V* k5 t
接着,就说说当前这点。 我们可以发现,最后一行代码对应的命名空间为test,并没有受到require文件里的命名空间的影响。 进一步加强验证,我修改了name.php文件如下: - //name.php
% j! T0 n, I4 [1 P3 T8 M - namespace test;
. M; }" u; c; C - require './1.php'; * M& n& E$ _& N8 K, j
& E( j" E4 A9 l) }- class Person{
( \; H# s* z, e9 b* M2 `' @ - function __construct(){
. ` r5 B8 J6 |0 D4 ^ - echo 'I am test!';
4 N. s( N) _- @7 c - }
: z# P ~6 {2 ^1 | - }
) `# b# c4 E) G6 `4 H- ?+ o
/ ~; R$ M9 A% H$ e! H- new \one\Person(); //输出 I am one!;
$ M4 M6 C$ }* k$ Q, ~( O9 v - new Person(); //这里结果会是什么,自己猜猜看
复制代码
( e8 E$ U- v* [4 i3 K+ z" q9 a最后,这个例子刷新了我对require的认识了。 按照我以前对require的理解:PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部分。所以我常常就简单的理解为替换,只不过把抽离出来的代码再放回原处而已。然后我试了将1.php文件内容放到name.php里: - //name.php
A# _4 _' u6 U - namespace test;
: A0 d8 T, |6 }( J - namespace one;8 h) q, ?" ^% h+ u1 b
- class Person{* J& ~) I* q" |+ j
- function __construct(){
. Z: J; \' P% f9 c( F - echo 'I am one!';
4 i9 y6 z0 D7 k - } w( D- D! D- m6 Q
- }
/ v& b: c: y( J" ~+ P* g2 d - ! w. H( \( u5 N; I, g
- class Person{
7 I/ c+ P2 G! I; n$ T$ H, [2 z - function __construct(){
% u8 T; d5 e5 x; Z7 }( K - echo 'I am test!';
/ \# x# N" [5 X/ X2 i - }
9 m. I/ m, z* G4 s4 D( B. Q- k( B; ` - }
复制代码 ) |0 r6 S' ?5 a# G
无需new类,该文件就会报错: - 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
- //name.php
+ [4 I: v; S7 T0 r/ X9 I0 x9 J
3 O& I: m" t- ? Z# R/ W6 ]- namespace test\person;
, t7 k" _% [9 J0 n' h; c
: k) D# y2 e! n& [" Q- class Person{; l% o: a9 N3 R2 P
- function __construct(){$ G& Z& Z9 c1 _9 m, s7 {
- echo 'I am test!';
1 o7 I* w) g7 j. s6 H1 U - }
$ X, c6 F% I. E, B: z$ P - }
) a1 o( o. P* g - 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文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。只说第一个命名空间前不能有任何代码,之后的命名空间之前可以有代码。这个自行测试即可。 - //name.php$ @$ }2 ~' k+ S2 ]6 D
' S( e5 t! V( g+ S. Y1 a2 J) V- namespace test;7 K8 b2 R; A" `) D
- echo 'zhai14';0 H' Z6 [9 M. n( ?5 m0 X
- namespace zhai;
" ? X8 x7 u4 i" z$ z - require './1.php';
复制代码
{1 s# F% D+ \' d& I4 mphp命名空间namespace告一段落了,接下来说说use的用途。 使用use的目的:在命名空间字符串过长时,使用use可以相应的缩短命名空间。 ! \0 a2 u) S% @7 x
use的使用方法:1.new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
& }8 Z1 y8 {: G3 J- c# N, A- //name.php
8 _8 K* Z$ B& d
" R# }4 A* P# q" \: v- namespace animal\dog;- B m3 U. o% r2 o2 s8 l( V+ d% v) d
/ @0 b; O7 n5 p- class Life{* t: ]; N9 ~% t7 K) [8 @8 {
- function __construct(){9 m6 e: k$ C4 ]* I4 D
- echo 'dog life!';
% z$ B1 t1 }2 u8 q% v" M - }+ ]+ E* B# i& C; t/ z1 X$ Z
- }4 w; z, W6 T; y9 s
# ]: S. o. Q7 v8 K- namespace animal\cat;; ~/ R3 F! V( r* p. u/ M7 A
- # r% \% ?, x- \& o% @) {
- class Life{
! x3 n8 M, ?* K! g, z0 w, L - function __construct(){& b5 M9 c. e$ |- a; f; b$ \. ^
- echo 'cat life!';
7 Y/ ]& ? u" ~( d$ f. r' K - }
/ I0 ?9 Q, L& Q7 Q - }
* I: T1 X0 k5 r" g. [1 v2 s
% I! h& h; j0 g6 l& i6 X- new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间8 v" O8 G Y4 d: k {1 `
- new \animal\dog\Life(); //A
7 J7 X5 c) p4 e - / ]; x% B6 Q& g% w
- use animal\dog; //a) O7 p: Z L8 s q0 l
- new dog\Life(); //B
0 Z ~' C9 p1 V- S G A7 o' y - 8 P4 x$ p0 ^( ? Z
- use animal\dog as d; //b
( b' }+ I5 h( @1 _9 j - 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时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的: 7 |( w7 p2 D! l& ~/ z- ?* }0 Q
相当于
' r' l! d7 Y' S0 U4 d2.namespace后面不建议加类名,但use后可以。$ S2 T9 x" u0 f. N' O. G, c+ Z# J
- //name.php3 X' r4 s% j+ Z/ t1 |
- ! i F3 Y8 B1 |& n) d% c: m# e& S' A
- namespace animal\dog;8 [8 ~( F" {; \) p- V. p+ \1 l) U
- ) a5 e" z4 ^" r. F
- class Life{
1 }/ g8 `# Z( u8 P7 f' S C+ v4 v0 @ - function __construct(){3 E1 v }$ t* \' Z4 w. f' _$ p
- echo 'dog life!';. W+ ^2 c8 n6 a8 A+ U2 X7 N
- }9 U; Q! u7 n6 q
- }8 |& z+ t! `! ?( x5 \
- 0 V# r6 v6 l. j3 b9 d( E7 G
- namespace animal\cat;
) H, z: L* {' l6 H" N q7 D
3 C* Q2 |0 I! ^# k0 s- class Life{% x5 J) g( @+ z9 U) o; W6 W
- function __construct(){/ x W8 {* C3 c; ]+ v. n
- echo 'cat life!';% J/ _- Q! D# s7 A* P
- }
2 w" ?8 Q. v8 ^4 ?, _ - }
- K. @+ k! w* T7 m - 8 b, r/ M; X( j, f& {$ ^
- use animal\dog\Life as dog; / h4 I G/ o# a& {5 k# `
- new dog();
复制代码 0 h% O! k) _( n8 Y
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。 上面不用as dog就会报错: - 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后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。 - //name.php
: V( k6 r* D( |$ ?$ ]' A. u4 t
9 ]! U- s$ d% j: A1 E$ E9 A* E/ c- namespace animal\dog;
7 Y% U3 |+ K* t
9 {; z) D$ K- _3 Z% h% O: t- class Life{
; L5 a. Y2 @ i* q N0 Q - function __construct(){8 G3 n/ x. {5 W7 q! f. E; _
- echo 'dog life!';
$ s( d' g4 ^( u+ v2 {* R/ I - }9 r. K/ @" p2 l+ M1 [" I! d
- }1 l6 m K: p4 O: ~8 H, s# Z9 b
- class Dog{1 f- @" J8 Q) }
- function __construct(){% l9 Y, u1 H5 w, b {
- echo 'dog in dog!';
x- T/ M0 \( F$ u- _2 c - }
; h. E2 _' J' d: j - }0 k8 @! Q+ V1 r9 ]7 i2 h
- 7 E g; X' K4 P9 v
- namespace animal\cat;" a" u6 n& o0 p$ H: O2 l* m7 X2 Y
- # q) Q' E0 {& w) l. d/ M
- // class Dog{! Y0 G6 x' n2 G: a
- // function __construct(){) O7 ~7 i' b3 h6 |" N& U6 y% z
- // echo 'dog in cat!';
2 `( ]& D$ y8 v+ g1 C4 t - // }
9 K( V. ~2 w) K% X h8 s7 P% Q+ }& i - // }7 S3 p+ b8 o1 G, g5 |# ^8 \$ V+ {& k
- class Life{
w% o( g6 {; s/ Y - function __construct(){
$ C1 m% [; o8 z! f - echo 'cat life!';
* ^" W0 t$ r& X' s0 x5 ~, Z$ A - }
. B* w [3 v8 C5 `. g I4 f - }! {. [& d4 O' X6 [- ?' G* j; S
- M, \* M' p, g! Q* x% c# k# I
- use animal\dog; F/ @+ E# S& T: I: O% O
- new dog\Dog();
复制代码 7 u! ^" x' v2 Q, m+ K( q
如上,使用了
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
|