这样做也可以减少代码出问题的可能性,配置文

2019-07-13 作者:编程   |   浏览(157)

PHP 是一门自由度很高的编程语言。它是动态语言,对程序员有很大的宽容度。作为 PHP 程序员,要想让你的代码更有效,需要了解不少的规范。很多年来,我读过很多编程方面的书籍,与很多资深程序员也讨论过代码风格的问题。具体哪条规则来自哪本书或者哪个人,我肯定不会都记得,但是本文(以及接下来的另一篇文章) 表达了我对于如何写出更好的代码的观点:能经得起考验的代码,通常是非常易读和易懂的。这样的代码,别人可以更轻松的查找问题,也可以更简单的复用代码。
降低函数体的复杂度

本文实例讲述了CI(CodeIgniter)简单统计访问人数实现方法。分享给大家供大家参考,具体如下:

本文实例分析了CodeIgniter控制器之业务逻辑。分享给大家供大家参考,具体如下:

本文实例讲述了CodeIgniter扩展核心类的方法。分享给大家供大家参考,具体如下:

在方法或者函数体里,尽可能的降低复杂性。相对低一些的复杂性,可以便于别人阅读代码。另外,这样做也可以减少代码出问题的可能性,更易修改,有问题也更易修复。
在函数里减少括号数量

废话不说,先上代码:

前面分析了公用控制器按模块分发,方便对特定模块的控制,而具体的实现类则是放在library中。那放在library中是否合适呢?以及控制器中更多的业务逻辑该放在哪里?

CI中对核心类、辅助类和函数的扩展是相当方便的,配置文件中指定了subclass_prefix扩展前缀,默认为MY_,扩展时需要以该配置为前缀,下面整理下扩展方式。

尽可能少的使用 if, elseif, else 和 switch 这些语句。它们会增加更多的括号。这会让代码更难懂、更难测试一些(因为每个括号都需要有测试用例覆盖到)。总是有办法来避免这个问题的。
代理决策 ("命令,不用去查询(Tell, don't ask)")
有的时候 if 语句可以移到另一个对象里,这样会更清晰些。例如:

控制器文件:

先说下对CI中几个文件夹的理解

1、扩展核心类

 if($a->somethingIsTrue()) {
  $a->doSomething();
 }

/application/controllers/hello.php 如下:

helpers、libraries: 存放一系列辅助函数、辅助类,用来辅助控制器、业务逻辑实现功能。他们中的方法应当尽量避免与CI依赖,依赖越紧越难以复用。以邮件发送为例,发送邮件时很多参数是不变的,如编码、协议、端口等,我们可能会在config下进行配置这些参数,然后library封装一个邮件发送的类,并在其中获取CI实例后读取这些参数。此时就出现了与CI实例的依赖,该类就只能在CI框架中使用,其他系统要用到,就只能重写了,没达到复用的目的。如果发送的类只是接收参数,并封装发送方法呢?所以说,尽可能的让helpers、libraries变的简单,职责变得单一。

核心类位于system/core下,其中大部分类会在初始化的时候自动加载。扩展核心类的方式有两种:替换核心类和继承核心类。

可以改成:
                    $a->doSomething();**
这里,具体的判断由 $a 对象的 doSomething() 方法去做了。我们不需要再为此做更多的考虑,只需要安全的调用 doSomething() 即可。这种方式优雅的遵循了命令,不要去查询原则。我建议你深入了解一下这个原则,当你向一个对象查询信息并且根据这些信息做判断的时候都可以适用这条原则。 小鱼儿玄机30码,使用map**

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Hello extends CI_Controller {
  public function index()
  {
    echo "Hello CodeIgniter!";
  }
  public function showval($name){
    //访问路径:http://localhost/ci/index.php/hello/showval/Tom
    $this->name=$name;
    @$num=file_get_contents('./num.txt');//加上@屏蔽警告提示(第一次运行没有TXT文件会有警告提示)
    $num=$num?$num:0;
    $num  ;
    $arr=array('v_name'=>$name,'v_num'=>$num);
    $re=fopen('./num.txt','w');
    fwrite($re,$num);
    fclose($re);
    $this->load->view('test_views',$arr);
  }
}

controllers: 控制器目录。控制器主要用来接管程序,起到连接的作用。通常情况下,我们会把业务逻辑写在action中。但随着业务变得复杂,action代码将越来越臃肿,难以维护。

替换核心类

有时可以用 map 语句减少 if, elseif 或 else 的使用,例如:

视图文件:

models: 模型目录。CI的模型的主要职责就是和数据库打交道,获取数据。很多时候也会把业务逻辑放在模型中,但业务逻辑与模型实际上是两种东西了。模型只是获取数据,业务逻辑可能是把这些数据根据业务需要进行组合,组合方式可能有很多种,放在模型中会让模型难以维护且不利于复用。说个碰到的例子,对数据按一定条件做缓存,获取数据和缓存结果两个流程写在同一个方法中,但同样的数据需要做另一种形式的缓存时发现,获取数据的方法就没法重用了。

当application/core目录下存在与system/core同名的文件时会自动替换掉核心类。以Loader.php为例,当创建application/core/Loader.php后会自动加载该类,由于该类为系统核心类,所以,如果Loader.php未实现CI_Loader类中的方法则会报错,如:

if($type==='json') {
  return $jsonDecoder->decode($body);
}elseif($type==='xml') {
  return $xmlDecoder->decode($body);
}else{
  throw new LogicException(
    'Type "'.$type.'" is not supported'
  );
}

/application/views/test_views.php 如下:

third_party:第三方类库目录。拿到一个类库后不要直接使用, 可以在library中进行一次封装,让其更适应于系统,其他人使用起来难度也会降低。

class CI_Loader
{
  ...
}

可以精简为:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>访问统计</title>
</head>
<body>
<?php echo $v_name;?>是第 <?php echo $v_num;?> 位访问者
</body>
</html>

可以发现,每个文件夹都有自己的职责,每个模块都有自己的家,都有自己的职能。那业务逻辑该怎么办?

替换核心类需要重写其中的所有方法,以免影响核心功能。但大部分时候并不需要重写整个核心,基本上只是增加某些方法,这个时候可以采取继承的方式。

$decoders= ...;// a map of type (string) to corresponding Decoder objects

if(!isset($decoders[$type])) {
  thrownewLogicException(
    'Type "'.$type.'" is not supported'
  );
}

运行结果如下图所示:

既然这样, 我们也应该给业务逻辑安个家,建立一个唯一的目录用来存放业务逻辑,暂且命名为service。控制器主要负责接收参数并调用service,service来调用模型,各层各尽其责。

继承核心类

这样使用 map 的方式也让你的代码遵循扩展开放,关闭修改的原则。
强制类型

小鱼儿玄机30码 1

下面看看怎么实现:

继承核心类需要以subclass_prefix为前缀,如扩展Input类,需创建application/core/MY_Input.php,并且MY_Input需要继承CI_Input类,如:

很多 if 语句可以通过更严格的使用类型来避免,例如:

更多关于CodeIgniter框架相关内容感兴趣的读者可查看本站专题:《codeigniter入门教程》

我们可以重写MY_Load,增加service方法,直接通过

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Input extends CI_Input
{
  function _clean_input_keys($str)
  {
    $config = &get_config('config');
    if ( ! preg_match("/^[".$config['permitted_uri_chars']."] $/i", rawurlencode($str))) {
      exit('Disallowed Key Characters.');
    }
    // Clean UTF-8 if supported
    if (UTF8_ENABLED === TRUE) {
      $str = $this->uni->clean_string($str);
    }
    return $str;
  }
}
/* End of file MY_Input.php */
/* Location: ./application/core/MY_Input.php */
if($a instanceof A) {
  // happy path
  return $a->someInformation();
}elseif($a=== null) {
  // alternative path
  return 'default information';
}

希望本文所述对大家基于CodeIgniter框架的PHP程序设计有所帮助。

复制代码 代码如下:

2、扩展CI类库

可以通过强制 $a 使用 A 类型来简化:

您可能感兴趣的文章:

  • CodeIgniter多语言实现方法详解
  • CodeIgniter读写分离实现方法详解
  • php实现仿写CodeIgniter的购物车类
  • codeigniter实现get分页的方法
  • CodeIgniter实现从网站抓取图片并自动下载到文件夹里的方法
  • codeigniter中实现一次性加载多个view的方法
  • CodeIgniter采用config控制的多语言实现根据浏览器语言自动转换功能
  • CodeIgniter生成静态页的方法
  • CI框架中$this->load->library()用法分析
  • CI框架数据库查询之join用法分析
  • CI框架简单邮件发送类实例
  • CI框架支持$_GET的两种实现方法

$this->load->service('user_service');

system/libraries下实现了一些辅助类,当有需要扩展这些类时,和核心类的处理方式是一样的,只不过目录变成了application/libraries

return $a->someInformation();

来调用。
但业务逻辑很多都需要获取CI实例,这里可以参考模型的方法,core建立一个MY_Service,其他service均继承该类,这样子service里用法就跟控制器里一样了。

3、扩展辅助函数

当然,我们可以通过其他方式来支持 "null" 的情况。这个在后面的文章会提到。
Return early

class MY_Service
{
  public function __construct()
  {
    log_message('debug', "Service Class Initialized");
  }
  function __get($key)
  {
    $CI = & get_instance();
    return $CI->$key;
  }
}

辅助函数存放于application/helpers目录下,辅助函数的“继承”方式与上面相同。因为CI的辅助函数都有使用function_exists来判断是否存在,所以也可以达到“重写”的目的。如在array中新增一个数组排序方法:

很多时候,函数里的一个分支并非真正的分支,而是前置或者后置的一些条件,就像这样:// 前置条件

其实主要思路还是需要有一层用来处理业务逻辑,java中都有这一层。随着对CI的不断熟悉,发觉这里需要这一层,达到解放控制器和模型的目的。和这种类似的做法还有很多,如果系统中有很多地方需要用到web service 或者说cache之类的,其实也可以按照上面的思路单独放在一个文件夹中处理,方便管理。

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * 对二维数组进行排序
 * 
 * @param array $data 需要排序的字段
 * @param array $sort_field 按哪个键进行排序,如果不是所有键中都含有该字段则返回原数组
 * @param array $sort_type 排序方式 SORT_ASC 升序 SORT_DESC 降序
 * @return array
 */
function array_field_sort($data, $sort_field, $sort_type = SORT_ASC)
{
  if(! is_array($data)) {
    return false;
  }
  $sort_arr = array();
  foreach($data as $key => $val) {
    if(isset($val[$sort_field])) {
      $sort_arr[$key] = $val[$sort_field];
    }
  }
  if(count($sort_arr) == count($data)) {
    array_multisort($sort_arr, $sort_type, $data);
  }
  return $data;
}
/* End of file MY_array_helper.php */
/* Location: ./application/helpers/MY_array_helper.php */

本文由小鱼儿玄机30码发布于编程,转载请注明出处:这样做也可以减少代码出问题的可能性,配置文

关键词: 小鱼儿玄机30码