写sql的老手~鸿池

今天再鸿池后面看着他写sql,啪啪啪打了一大串,这么长的一串sql要是我以前看起来根本就是不是我能企及的。可能你们看到我这样说觉得很可笑,个人能力不高,不过贵在努力学习

因为之前工作中涉及sql的操作并不多,说起来有些羞愧,这尼玛还好意思舔着脸和别人说工作经验xx年,工作项目xxxxxx。看看人家这写码的素质~,自愧不如啊~

首先,鸿池先在sql工具里写了第一段的sql作为a取出自己需要的字段检查正确性作为a,然后再在sql工具中写另一段sql取出自己需要的字段检查正确性作为b,然后再取出自己需要的字段。

废话不说上代码~~

select a.voucher_value, a.voucher_number as exp_voucher, date(a.issue_time) as exp_issue_date, a.expiry_date as exp_expiry_date
    , a.expiry_grace_date as exp_expiry_grace_date
    , b.voucher_number as new_voucher, date(a.replace_time) as replace_date
    , b.expiry_date as new_expiry_date
    , b.expiry_grace_date as new_expiry_grace_date
    from (
     select a.expired_voucher_id, b.voucher_value, concat(prefix, voucher_text, suffix) as voucher_number, 
     max(c.action_time) as issue_time, b.expiry_date
     , DATE_ADD(b.expiry_date, INTERVAL $this->_grace_period_days DAY) AS expiry_grace_date
     , a.replace_time
     from $this->_voucher_replace_details a, $this->_voucher b, $this->_voucher_action c
     where a.expired_voucher_id = b.voucher_id
     and b.voucher_id = c.voucher_id
     and c.action_id in ('$issue_action_id', '$issue_action_id2', '$issue_action_id3')
     $value_clause
     AND  (a.replace_time BETWEEN '$quarter_start_date 00:00:00' AND '$quarter_end_date 23:59:59' )
     group by b.voucher_id
    ) a,
    (
     select a.expired_voucher_id, b.voucher_value, concat(prefix, voucher_text, suffix) as voucher_number, 
     max(c.action_time) as issue_time, b.expiry_date
     , DATE_ADD(b.expiry_date, INTERVAL $this->_grace_period_days DAY) AS expiry_grace_date
     from $this->_voucher_replace_details a, $this->_voucher b, $this->_voucher_action c
     where a.new_voucher_id = b.voucher_id
     and b.voucher_id = c.voucher_id
     and c.action_id in ('$issue_action_id', '$issue_action_id2', '$issue_action_id3')
     AND  (a.replace_time BETWEEN '$quarter_start_date 00:00:00' AND '$quarter_end_date 23:59:59' )
     group by b.voucher_id
    ) b
    where a.expired_voucher_id = b.expired_voucher_id
    ORDER BY 2 ASC

留念学习,理清逻辑,其实你也可以做到~~

ie兼容性 真真的坑爹啊~

早上调试到现在,2个问题

1.点击 jquert html 到id里的buttom 不触发onclick事件

再chrome里是有效的,在ie和firfox下无响应

最后解决的办法是 把onclick事件放在了包裹buttom的span里

2.点击request replacement按钮的时候无效,ie报错(SCRIPT1014:无效字符)

上网查阅一番,说是后台ajax返回的数据不是json格式的,胆识我在后台的文件反复检查返回回来的数据都是

会jsonencode再echo出来的。然后找了半天才发现做post的时候sub的值是通过jquery获取的就是

$('#xxxx').val() 这种形势,发现之后果断换掉,直接传递submission_id进函数,问题解决。

 

至此从早上10点一直调试到现在 ,坑爹啊~~~

issue voucher for campaign的流程

代码在controllers/csa.php 的request_issue()里

 /*
  * @desc request issue vouchers for given campaign
  */
 function request_issue()
 {
     //@TODO: Lock table to check if value limit exceed.
     $post = $this->input->post();
     
     $summary = $this->voucher_api_campaign->campaign_get_summary( $post['cp_id'] );
     
     $this_batch_summary = $this->voucher_api->voucher_summary_by_prefix_suffix_no( $post['prefix'], $post['suffix'], $post['first'], $post['last'] );
     $batch_value = $this_batch_summary['total_value'];
     
     $rt = array();
     if($summary['value_limit'] < ($summary['value_pending'] + $summary['value_issued'] + $batch_value))
     {
      $rt['error'] = 'Voucher Value exceeded';
     }
     else
     {
      $option = array();
      $option['first'] = $post['first'];
      $option['last'] = $post['last'];
      $option['prefix'] = $post['prefix'];
      $option['suffix'] = $post['suffix'];
      $option['remarks'] = $post['remarks'];
      $option['campaign_id'] = $post['cp_id'];
      
      $option['from_stock'] = $this->_my_stock_id;
   $option['to_stock'] = $this->voucher_lkup->get_stock_id_by_name ( 'issued' );
      
      $this->voucher_api_campaign->campaign_request_issue( $option );
     }
     
     echo json_encode($rt);
 }

 

主要的流程是$this->voucher_api_campaign->campaign_request_issue( $option );

在models/campign_voucher.php  的 campaign_request_issue()内

 public function campaign_request_issue( $options )
 {
  $prefix = $options['prefix'];
  $suffix = $options['suffix'];
  $first = $options['first'];
  $last = $options['last'];
  $campaign_id = $options['campaign_id'];
  $campaign_details = $this->campaign_get_details ($campaign_id);
 
  $lock_id = $this->voucher_lkup->get_lock_id_by_name('request_issue');
 
  //update vouchers set is_locked = 'Y'
  $sql = <<<SQL
  UPDATE  $this->_voucher a
  SET is_locked = 'Y', lock_id = '$lock_id'
  WHERE prefix = '$prefix' AND suffix = '$suffix'
  AND   voucher_no BETWEEN $first AND $last
SQL;
 
  $this->db->query($sql);
 
  //add into in transfer.
  $batch_id = $this->create_vouchers_batch_by_numbers( $prefix, $suffix, $first, $last );
 
  $request_action_id = $this->voucher_lkup->get_action_id_by_name('request_issue');
  $approve_action_id = $this->voucher_lkup->get_action_id_by_name('approve_issue');
 
  $request_record = array();
  $request_record['from_stock'] = $options['from_stock'];
  $request_record['to_stock'] = $options['to_stock'];
  $request_record['request_remarks'] = $options['remarks'];
  $request_record['request_time'] = date('Y-m-d H:i:s');
  $request_record['request_action'] = $request_action_id;
  $request_record['batch_id'] = $batch_id;
  $request_record['approve_action'] = $approve_action_id;
  $request_record['request_user'] = $this->_user_id;
  $request_record['is_done'] = 'N';
  $this->db->insert( $this->_voucher_request_approve, $request_record );
  $request_id = $this->db->insert_id();
  
  //get campaign expiry date:
  if($campaign_details['expiry_type'] == 1)
  {
   $voucher_expiry_date = $campaign_details['expiry_date'];
  }
  else
  {
   $expiry_duration_value = empty($campaign_details['duration_value']) ? 1 : $campaign_details['duration_value'];
   $expiry_duration_unit = empty($campaign_details['duration_unit']) ? 'DAY' : $campaign_details['duration_unit'];
    
   $row = $this->db->query("SELECT DATE_ADD(CURDATE(), INTERVAL $expiry_duration_value $expiry_duration_unit) AS expiry_date")->row_array();
   $voucher_expiry_date = $row['expiry_date'];
  }
  
  $remarks_info = array();
  $remarks_info['Campaign Code'] = $campaign_details['campaign_code'];
  $remarks_info['Type'] = $this->voucher_lkup->get_type_desc_by_id( $campaign_details['type_id'] );
  $remarks_info['Expiry Date'] = $voucher_expiry_date;
  if(isset($options['remarks']) && !empty($options['remarks']))
  {
   $remarks_info['Remarks'] = $options['remarks'];
  }
  $remarks_text = $this->voucher_lkup->array_to_text( $remarks_info );
  
  $this->voucher_action_insert_by_prefix_suffix( $request_action_id, $prefix, $suffix, $first, $last, $remarks_text );
 
  $request_record = array();
  $request_record['campaign_id'] = $campaign_id;
  $request_record['request_id'] = $request_id;
  $this->db->insert( $this->_voucher_campaign_issue_request, $request_record );
  
  $action_info = array();
  $action_info['campaign_details'] = $campaign_details;
  $action_info['remarks'] = $options['remarks'];
  $action_info['campaign_type'] = $this->voucher_lkup->get_type_by_id($campaign_details['type_id']);
  
  $first_voucher = $this->_voucher_get_by_prefix_suffix_no( $prefix, $suffix, $first );
  $last_voucher = $this->_voucher_get_by_prefix_suffix_no( $prefix, $suffix, $last );
  $action_info['first_voucher'] = $first_voucher['prefix'] . $first_voucher['voucher_text'] . $first_voucher['suffix'];
  $action_info['last_voucher'] = $last_voucher['prefix'] . $last_voucher['voucher_text'] . $last_voucher['suffix'];
  
  $this->load->model('email_notifications');
  $this->email_notifications->action_trigger_notification( $request_action_id, $action_info );
  
  return TRUE;
 }

1.将相关voucher锁住

2.创建batch记录

$batch_id = $this->create_vouchers_batch_by_numbers( $prefix, $suffix, $first, $last );

3.插入记录到 Table -> voucher_request_approve 

4.通过voucher_action_insert_by_prefix_suffix() 插入voucher_action 表

5.插入voucher_campaign_issue_request 记录 campaign_id 和 request_id

6.最后整理notinotification的一些数据发送邮件

 

大致的过程如上。

关于mysql having的使用

以前不常用这个函数having,今天一个东西要对比不同的数据。我就有点摸不着头脑了,应为以前对写mysql sql并不是很熟练,然后鸿池发给我如下SQL语句:

select *
from `voucher_campaign_corporate_conversion` m
left join (
 select b.campaign_id, sum(a.voucher_value) as issued_amount, count(distinct a.voucher_id) as issued_vouchers
 from voucher a, voucher_campaign b, voucher_campaign_issue c
 where a.voucher_id = c.voucher_id
 and b.campaign_id = c.campaign_id
 and c.is_deleted = 'N'
 and b.type_id = 10
 group by 1
) n on m.campaign_id = n.campaign_id
having m.issue_amount != n.issued_amount

 

其中用到了having 对查询出来的数据与表里的issued_amount进行对比,找出数据不相同的行,很好用。

看《如何写出让自己满意的代码》的反省

        今天看了篇文章,名字叫《如何写出让自己满意的代码》有一点我觉得很重要,也是我及其需要改正的。因为我做事情都是急于求成,从来不会先去关心事情之间的结构,所以反而会花更多的时间做无用功,来回改正。比如说这次做voucher的replace,其实内部很复杂,有很多牵扯到的东西,还有这次的在ct里面加search的功能,不是简单的查找,还要根据voucher的不同状态查找历史纪录,而老版本里的历史状态需要查询多胀表,做多种不同状态的判断,所以像文章里说的,花三分之一的时间去把所有的数据结构及其相互关系考虑清除。

 

文章大意如下:

        思路是最关键的。假定采用的技术平台、框架、工具等已经确定了,那么在开始动手写之前,花三分之一以上的开发时间去把所有的数据结构及其相互关系考虑清楚。例如需要定义几个类,类和类之间的关系是怎样的,每个类里都有什么属性,每个类提供一些什么样的方法,等等,这些是最核心 的。这些数据结构要考虑得尽可能细,比如功能实现可能没问题,但是性能上不理想,这就说明你的数据结构设计还需要改进。这些细节要反复考虑,交叉检验,直 到自己觉得很周到了为止。在此基础上,再注意实现的细节、测试用例、代码可读性,就应该可以写出让自己满意的代码。

PHP设计模式-单例模式

    经过良好设计的系统一般通过方法调用来传递关系实例,每个类都会与背景环境保持独立,并通过清晰的通信方式来与系统中其他部分进行写作。

     假如我们需要一个类来保存系统信息,我们要保证系统中的所有对象都使用同一个 1.系统信息对象应该被系统中的任何对象使用

2.系统对象不应该会被存储在会被复写的全局变量中

3.系统中不应该超过一个系统信息对象,也就是说Y对象可以设置系统对象的一个属性,而Z对象不需要通过其他对象就能直接获得该属性的值

 

下面创建一个无法从外部实例化的类:

class Preferences{
    private $props = array();
    private function __construct(){}

    public function setProperty($key, $val){
        $this->props[$key] = $val;
    }

    public function getProperty($key){
        return $this->props[$key];
    }
}

    当然,目前的Preferences是完全不能用的,我们设置了一个不合常理的限制,构造函数被生命为private, 客户端无法实例化对象。

    不过我们可以使用静态方法和静态属性来实例化对象。

class Preferences{
    private $props = array();
    private static $instance;

    private function __construct(){}

    public static function getInstance(){
        if(empty(self::$instance)){
            self::instance = new Perference();
        }
        return self::$instance;
    }

    public function setProperty($key, $val){
        $this->props[$key] = $val;
    }

    public function getProperty($key){
        return $this->props[$key];
    }
}

instance 内部被设置为private以及static,因此不能被从类外部进行访问。而getinstance是public static的可以在脚本的任何地方进行调用。

$pref = Preferences::getInstance();
$pref -> SetProperty('name','matt');

unset($pref);//移除引用

$pref2 = Preferences::getInstance();
print $pref2->getProperty("name")."\n"; //该属性值没有丢失

输出matt

 

    静态方法不能访问普通的对象属性,应为根据静态定义,它只能被类而不是对象调用。但是静态方法可以访问一个静态属性所以当getInstance被调用时,我们会检查Preferences::$instance属性,如果为空,那么创建一个Preferences对象实例并把它保存在$instance属性中,然后我们把实例返回给调用代码。因为getInstance()是Perferences类的一部分,所以尽管构造函数是私有的,但是实例化Perferences对象完全没有问题。

 

    单例模式适用于代替全局变量使用,单例在itong任何地方都可以被访问,所以它可能会导致很难调试的依赖关系。如果改变一个单例,那么所有使用该单例的类都会受到影响。

 

    1。单例模式防止其它对象对自己的实例化,确保所有的对象都访问一个实例。

    2。
因为由类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。

—————————————————————————————————————————————

在JAVA里的单例



因为你每做一次数据库的操作,都必须创建一个session, 这时候用单例模式是最好的,每次都只是同一个实例,就不会象上面那样出错啦 

这个是为了节省资源吧。。

 

  最常见的要数DB类了。几乎所有的PHP框架都是这个套路

关于这次搭建的博客

    之前确实也做过类似的博客,但是后来很久没用就搁浅了。然后总想把自己学习的东西记录在一处,却感觉又无处安放,所以就有了这个博客。

     

    正好新公司要用到Codeigniter这个框架,我就在网上搜索了又Codeigniter开源的代码‘STBOLG’,由于人比较懒,前段时间又已经用CI自己写了个小企业站整体的流程也简单有个了解,所以就不想自己动手写了,这个博客系统还不错,简单朴素,不想花过多的精力去找前端的模板了,反正也是自己当作积累的一个地方,不打算对外开放。

     

    第一步我打算把之前看的《深入PHP 面向对象,模式与实践》中关于设计模式的一些东西用自己的方式记录下来,应为中断了一个多月没看,发现对立面的东西又开始陌生了,本来第一遍看的时候就模模糊糊的。也是因为平常工作中没有机会用到这些设计模式。但这次不同,新公司是有这个需求的。

     

    好了不说了,开始吧…