控制器劫持

  • 控制器劫持是指不修改原app代码的前提下,对控制器进行劫持,以便达到自己的修改目的。
  • 下面就是一个我们的成功案例分析。

1、场景再现

  • 项目名称:商超
  • 代码获取:svn:https://app.ec-os.net/svn/shangchao/branches/current 或者联系孙进荣获取代码包
  • 描述:储功彪
  • 需求:在商品列表页点击编辑后跳转到编辑页。要在不更改原来app代码的前提下对编辑页进行修改。

    如下图所示:

  • 劫持前效果:
  • 劫持后效果:
  • 通过劫持前后效果我们可以发现:1区在“劫持”前是下拉列表,“劫持”后变成默认选项,用户不能自由选择;2区是输入框,劫持后看似没有变化,实际上劫持后也不能进行输入。那么这个效果是怎样实现的呢?

2、实现步骤

2.1原理

上述的效果是怎样实现的呢?劫持究竟是怎么一会事?怎样劫持?这样的问题会出现在我们的脑海里。我们首先来分析一下上例的劫持过程和劫持点。上例中“编辑”链接是指向b2c_ctl_admin_goods_editor这个class的edit方法。原代码如下:

<?php
...
    function 
edit($goods_id){
        
$this->goods_id $goods_id;
        
$oGoods = &$this->app->model('goods');
        
$goods $oGoods->dump($goods_id,'*','default');
        
$this->_editor($goods['type']['type_id']);
        if(
is_numeric($goods['store'])) $goods['store'] = (float)$goods['store'];
        if(
is_array($goods['product'])){
            foreach(
$goods['product'] as $k=>$v){
                
$goods['product'][$k]['store'] = $v['store']!==null ? (float)$v['store'] : '';
            }
        }
        
$this->pagedata['productkey'] = serialize(array_keys($goods['product']));
        
$this->pagedata['goods'] = $goods;
        
$this->pagedata['app_dir'] = app::get('b2c')->app_dir;
        if(!
is_array($goods['adjunct']))
            
$this->pagedata['goods']['adjunct'] = unserialize($goods['adjunct']);
        else
            
$this->pagedata['goods']['adjunct'] = $goods['adjunct'];
        foreach(
$oGoods->getLinkList($goods_id) as $rows){
            if(
$rows['goods_1'] == $goods_id){
                
$aLinkList[] = $rows['goods_2'];
                
$linkType[$rows['goods_2']] = array('manual'=>$rows['manual']);
            }else{
                
$aLinkList[] = $rows['goods_1'];
                
$linkType[$rows['goods_1']] = array('manual'=>$rows['manual']);
            }
        }

        
$oUrl kernel::single('site_route_app');
        
$goods_url app::get('site')->router()->gen_url( array( 'app'=>'b2c','real'=>1,'ctl'=>'site_product','args'=>array($goods_id) ) );
        
$goods_url substr$goods_url strlenapp::get('site')->base_url() ) );
        
$url $oUrl->fetch_static( array( 'static'=>$goods_url ) );
        
$this->pagedata['goods_static'] = $url['static'];

        
$this->pagedata['goods']['glink']['items'] = $aLinkList;
        
$this->pagedata['goods']['glink']['moreinfo'] = $linkType;
        
$this->pagedata['goods']['goods_setting'] = $goods['goods_setting'];
        
$this->pagedata['IMAGE_MAX_SIZE'] = IMAGE_MAX_SIZE;
        
$this->singlepage('admin/goods/detail/frame.html');
...
    }

2.2 注册一个service

在app\shangchao\services.xml加入如下代码:

<services>
...
    <service id="desktop_controller_display.b2c.admin_goods_editor.edit">
        <class>shangchao_ctl_admin_goods_editor</class>
    </service>
...
</services>

2.3 添加class

在app\controller\admin\goods\目录下添加文件editor.php主要代码如下:

<?php
class shangchao_ctl_admin_goods_editor extends b2c_ctl_admin_goods_editor{
    function 
get_file(){
        
//$this->xiangou_add();
        
$goods_id=$this->pagedata['goods']['goods_id'];
        
$db = &kernel::database();
        
$supplier_name=$db->selectrow('select sdb_shangchao_goods_supplier.supplier_id,sdb_shangchao_supplier.supplier_name from sdb_shangchao_goods_supplier,sdb_shangchao_supplier where sdb_shangchao_goods_supplier.supplier_id=sdb_shangchao_supplier.supplier_id and goods_id="'.$goods_id.'"');
        
$supplier_name;
        
$obj_editor kernel::single('b2c_ctl_admin_goods_editor');
        
$obj_editor->pagedata['supplier_name']=$supplier_name['supplier_name'];
        
$obj_editor->pagedata['supplier_id']=$supplier_name['supplier_id'];
        if(isset(
$obj_editor->pagedata['sections']['basic'])){
            
$obj_editor->pagedata['sections']['basic']['app'] = 'shangchao';
        }
        return 
'admin/goods/detail/frame.html';
    }
...
该方法是要完成对劫持后页面要用到的数据的获取然后返回一个页面frame.html。在frame.html这个页面里我们主要完成对要劫持的页面的处理,如:通过加入JS代码使劫持页面的下拉菜单无法选择。在经过数据准备,然后在frame.html加入JS代码完成我们的需求后,我们通过return 'admin/goods/detail/frame.html'将我们的处理结果再返回到b2c_ctl_admin_goods_editor的edit方法中输出。
  • 最后,运行cmd update即可得到劫持后的结果。
    D:\php\shangchao\app\base>cmd update
    Scanning local Applications... ok.
    ?Updating base_application_service@shangchao.
    Installing service passport
    Installing service pam_login_listener
    Installing service pam_account_login_name
    Installing service api_signup
    Installing service desktop_controller_display.b2c.admin_goods_editor.edit
    Installing service desktop_controller_display.b2c.admin_goods_virtualcat.addNew
    Installing service desktop_controller_display.b2c.admin_goods_virtualcat.edit
    Installing service b2c.order.act_ext_btn
    Installing service site_controller_display.b2c.site_cart.loginbuy
    Installing service site_controller_display.b2c.site_gallery.index
    Installing service member_index
    Installing service b2c_addtocart_check
    Installing service b2c_promotion_solution_tpl_apps
    Installing service b2c_cart_render_items_apps
    Installing service b2c_cart_render_items_goods_apps
    Installing service api.shangchao.goods
    ...
    Installing service b2c_mdl_goods.filter
    Installing service b2c_mdl_goods.extends_cols
    Applications database and services is up-to-date, ok.
    

內容目录

上一个主题

最佳实践

下一个主题

替换控制器

快速搜索

输入相关的模块,术语,类或者函数名称进行搜索