需用session+input采集行为、model封装聚合逻辑、路由适配动态报表url、chart.js实现可视化。codeigniter需手动管理history数组长度,model须手写sql支持漏斗分析,路由需配置通配符或改用query string,api响应禁用xss过滤并设json类型。

搭建一个能实时采集用户行为、聚合访问路径、生成转化漏斗报表的CodeIgniter数据分析系统,需要在轻量框架上平衡扩展性与开发效率。它不依赖复杂中间件,但必须直面原生组件能力边界。
用Session+Input类做基础行为采集
CodeIgniter默认启用文件型Session驱动,配合Input类可直接捕获IP、UA、GET/POST参数和Referer。
在控制器中加载session和input:$this->load->library(['session', 'input']);
记录商品浏览行为时,先获取product_id:$product_id = $this->input->get('id');
从session读取历史记录并前置插入新条目:$history = $this->session->userdata('product_history') ?: []; array_unshift($history, ['product_id' => $product_id, 'view_time' => time(), 'referrer' => $this->input->server('HTTP_REFERER')]);
【注意:array_pop()必须手动调用,否则history数组会无限增长,最终撑爆session存储空间】
只保留最近10条:if (count($history) > 10) { array_pop($history); } $this->session->set_userdata('product_history', $history);
构建轻量级数据管道:Model层封装聚合逻辑
不要把统计代码写进Controller——这是CI项目最常踩的坑。所有SELECT COUNT、GROUP BY、时间窗口切片都应封装进Model。
创建application/models/Analytics_model.php,继承CI_Model:
定义方法get_daily_views_by_source(),内部调用$this->db->select('COUNT(*) as cnt, source')->from('user_events')->where('date(created_at)', date('Y-m-d'))->group_by('source')->get()->result();
关键点在于:原始日志表user_events需提前建好,包含created_at、source(来自HTTP_REFERER解析)、event_type、user_id等字段;CI的Query Builder不支持窗口函数,复杂漏斗需拆成多步SQL或改用原生查询。
若要支持7日留存率计算,必须在Model里手写JOIN子查询——CI没有Laravel Eloquent那样的链式关系定义能力。
规避CI路由限制实现动态报表URL
CodeIgniter默认路由无法匹配带斜杠的参数,比如/report/conversion/funnel/v2,会报404。
方法一:修改application/config/routes.php,添加$route['report/(:any)'] = 'report/$1';
方法二:启用URI映射,在index.php同级新建report.php入口文件,绕过CI主路由;但会导致无法使用CI的Security类和Session自动管理。
【必须关闭translate_uri_dashes选项,否则/report/conversion/funnel会被转成report_conversion_funnel,路由完全失效】
方法三:改用Query String模式,访问/report?tab=funnel&ver=v2,后端用$this->input->get('tab')提取参数——牺牲RESTful风格,换来零配置兼容性。
用第三方库补足可视化短板
CI本身不提供图表渲染能力,必须引入外部JS库或服务。
推荐方案:在View中直接嵌入Chart.js,通过AJAX请求/application/api/analytics/chart_data接口获取JSON数据。
该接口由ApiController提供,返回格式严格限定为{labels: [...], datasets: [{data: [...]}]},避免前端解析失败。
禁用CI的XSS过滤器对API响应体:在对应方法顶部加$this->output->set_content_type('application/json')->set_output(json_encode($data));
若需导出CSV报表,用PHP内置fputcsv()写入临时文件,再用force_download()推送——不要尝试用CI的Zip类打包,它不支持流式压缩大文件。











