不要写死路径

本文导航

  1. 总结
  2. 结语
  • 作者:KK

  • 发表日期:2016.7.19


有过两三年经验的程序员应该都吃过这个亏,有时候出bug就因为写死的路径在特定情况下出错

写死路径的不良后果有如下(欢迎留言补充):

  1. 迁移环境后,路径不适用或无权限

    如果代码中含有include('D:/projects/shop/mysql.php')这样的代码,那么很明显当这个代码放到linux系统上的时候就会报错,因为linux系统没有D盘,然而实际上还是有程序员犯这个错误或遗漏

    • 解决办法:

      使用相对路径或者与项目目录的路径进行拼接:

      include('mysql.php'); //假设当前文件是 D:/projects/shop/index.php
      include('../mysql.php'); //假设当前文件是 D:/projects/shop/lib/db.php
      		
      include(APP_PATH . 'mysql.php'); //大部分人都用过TP框架,你懂的,换了项目目录就只要重新修改APP_PATH的定义就好,别的一些框架也有这常量
      

  2. 修改项目的目录结构或者换了个目录名后,大部分写死路径无法使用

    好了这下大家不从根目录开始写了,什么"D:/a/b",什么"/data/www/a/b",程序员已经开始写../lib/db/mysql.php类似这样的相对路径了

    这假设有lib目录往上再迁移了一个级别,那这个include代码又得跟着改路径了,而且如果有很多个地方都写了include('../lib/db/mysql.php')的时候,就得到处搜索来修改,还容易改漏

    • 解决办法:

      给lib目录定义一个常量:

      define('LIB_PATH', realpath('./lib')); //在项目初始化的地方
      include(LIB_PATH . '/db/mysql.php');
      

      这样的话,lib目录迁移到别处也没啥问题了,只要相应地修改常量的定义,这下只怕db目录也重命名

      其实根据工作经验,通常是lib这样的上级目录进行目录位置调整,里面的子目录调整并不多,所以这个既不好防御也不用多担心

      不然你真害怕db目录也被改的话就定义个DB_PATH要不要?

    一个项目是有发展过程的,并且它的技术架构和目录结构并不是一开始定下来就是正常并且不用再调整的,有的项目可能长时间不用调整,有的过半年左右就会发现问题进一步调整等

    所以比如lib目录被改成extend这样的名称,那些写死了路径的代码又得跟着改了,看你吃不吃亏?


  3. 后来的需求要允许让外部传入路径进行控制,于是写死的路径又不能用了

    有些功能是这样的,它的逻辑要对一个特定的文件进行处理,起初代码可能是file_get_contents('a/b/c.data')这样写死的

    并且在这个功能中,对文件的读取,修改,删除都是写死了的,起码有四五处代码

    后来由于功能扩展,需要允许外部调用的函数传入一个自定义文件来进行处理,但是里面写死了对"a/b/c.data"进行处理呀,所以肯定要改成一个变量,然后这个变量由外部提供咯

    如果当初就设定成一个变量,所有操作都针对这个变量来处理,变量初始值为这个路径,以后别人要传进来时就取消初始化,在函数的参数表里加一个变量名做参数就行了


总结

其实很多框架都有别名这个概念,我主要是利用别名功能来代替一些路径目录,比如在Yii框架里:

Yii::setAlias('importPath', __DIR__ . '/../import-data'); //在框架初始化的地方

//一个导入业务逻辑
$importPath = Yii::getAlias('@importPath');
foreach(['shoes', 't-shirt', 'cap'] as $dataDirName){
	$importFiles = scandir($importPath . '/' . $dataDirName);
	//...更多处理逻辑
}

在没有别名概念的项目里,起码应该用常量来定义目录路径


结语

如果你这半年里写下的代码还有写死的路径,那你基本上还处于新手阶段,不管你懂多少函数、懂多少插件的用法,这只是积累了简单的工具使用知识,但从编程思想和编程经验上来说还是个新手而已