phalcon 这个轮子 都说不错,可是 对于 看惯了 python源码的人 ,还是很有意思得,下面是对phalcon 的一点理解 跟 一点不完全的代码。项目 是用 phalcon-tool 命令行自动生成的。

框架的 入口文件 是public 下 的index.php, 具体内容如下,

try {/*** The FactoryDefault Dependency Injector automatically registers* the services that provide a full stack framework.*/$di = new FactoryDefault();/*** Handle routes*/include APP_PATH . '/config/router.php';/*** Read services*/include APP_PATH . '/config/services.php';/*** Get config service for use in inline setup below*/$config = $di->getConfig();/*** Include Autoloader*/include APP_PATH . '/config/loader.php';/*** Handle the request*/$application = new \Phalcon\Mvc\Application($di);

这个 文件 主要主要做了 几个事情,实例化了 FactoryDefault , 这个 东西主要是管理 各种对象 的容器。下面include 跟的是 各种组件的路径,会被扫包 。对 application 注入 容器 ,处理request 请求,当然这是很初级的一个 启动方式,你可以 把一些 公共服务  比如 router ,session ,validator等 服务 ,统一写在一个配置文件里,方便清晰。

router  路由 需要自己 定义,在 程序开始 就被 注入容器,成为一个 服务,对于 url 请求 路由  是通过 router handle 方法处理,具体源码如下。

public function handle(string! uri){var request, currentHostName, routeFound, parts,params, matches, notFoundPaths,vnamespace, module,  controller, action, paramsStr, strParams,route, methods, dependencyInjector,hostname, regexHostName, matched, pattern, handledUri, beforeMatch,paths, converters, part, position, matchPosition, converter, eventsManager;/*** Remove extra slashes in the route*/if this->_removeExtraSlashes && uri != "/" {let handledUri = rtrim(uri, "/");} else {let handledUri = uri;}let request = null,currentHostName = null,routeFound = false,parts = [],params = [],matches = null,this->_wasMatched = false,this->_matchedRoute = null;let eventsManager = this->_eventsManager;if typeof eventsManager == "object" {eventsManager->fire("router:beforeCheckRoutes", this);}/*** Routes are traversed in reversed order*/for route in reverse this->_routes {let params = [],matches = null;/*** Look for HTTP method constraints*/let methods = route->getHttpMethods();if methods !== null {/*** Retrieve the request service from the container*/if request === null {let dependencyInjector = <DiInterface> this->_dependencyInjector;if typeof dependencyInjector != "object" {throw new Exception("A dependency injection container is required to access the 'request' service");}let request = <RequestInterface> dependencyInjector->getShared("request");}/*** Check if the current method is allowed by the route*/if request->isMethod(methods, true) === false {continue;}}/*** Look for hostname constraints*/let hostname = route->getHostName();if hostname !== null {/*** Retrieve the request service from the container*/if request === null {let dependencyInjector = <DiInterface> this->_dependencyInjector;if typeof dependencyInjector != "object" {throw new Exception("A dependency injection container is required to access the 'request' service");}let request = <RequestInterface> dependencyInjector->getShared("request");}/*** Check if the current hostname is the same as the route*/if typeof currentHostName == "null" {let currentHostName = request->getHttpHost();}/*** No HTTP_HOST, maybe in CLI mode?*/if !currentHostName {continue;}/*** Check if the hostname restriction is the same as the current in the route*/if memstr(hostname, "(") {if !memstr(hostname, "#") {let regexHostName = "#^" . hostname;if !memstr(hostname, ":") {let regexHostName .= "(:[[:digit:]]+)?";}let regexHostName .= "$#i";} else {let regexHostName = hostname;}let matched = preg_match(regexHostName, currentHostName);} else {let matched = currentHostName == hostname;}if !matched {continue;}}if typeof eventsManager == "object" {eventsManager->fire("router:beforeCheckRoute", this, route);}/*** If the route has parentheses use preg_match*/let pattern = route->getCompiledPattern();if memstr(pattern, "^") {let routeFound = preg_match(pattern, handledUri, matches);} else {let routeFound = pattern == handledUri;}/*** Check for beforeMatch conditions*/if routeFound {if typeof eventsManager == "object" {eventsManager->fire("router:matchedRoute", this, route);}let beforeMatch = route->getBeforeMatch();if beforeMatch !== null {/*** Check first if the callback is callable*/if !is_callable(beforeMatch) {throw new Exception("Before-Match callback is not callable in matched route");}/*** Check first if the callback is callable*/let routeFound = call_user_func_array(beforeMatch, [handledUri, route, this]);}} else {if typeof eventsManager == "object" {let routeFound = eventsManager->fire("router:notMatchedRoute", this, route);}}if routeFound {/*** Start from the default paths*/let paths = route->getPaths(),parts = paths;/*** Check if the matches has variables*/if typeof matches == "array" {/*** Get the route converters if any*/let converters = route->getConverters();for part, position in paths {if typeof part != "string" {throw new Exception("Wrong key in paths: " . part);}if typeof position != "string" && typeof position != "integer" {continue;}if fetch matchPosition, matches[position] {/*** Check if the part has a converter*/if typeof converters == "array" {if fetch converter, converters[part] {let parts[part] = call_user_func_array(converter, [matchPosition]);continue;}}/*** Update the parts if there is no converter*/let parts[part] = matchPosition;} else {/*** Apply the converters anyway*/if typeof converters == "array" {if fetch converter, converters[part] {let parts[part] = call_user_func_array(converter, [position]);}} else {/*** Remove the path if the parameter was not matched*/if typeof position == "integer" {unset parts[part];}}}}/*** Update the matches generated by preg_match*/let this->_matches = matches;}let this->_matchedRoute = route;break;}}/*** Update the wasMatched property indicating if the route was matched*/if routeFound {let this->_wasMatched = true;} else {let this->_wasMatched = false;}/*** The route wasn't found, try to use the not-found paths*/if !routeFound {let notFoundPaths = this->_notFoundPaths;if notFoundPaths !== null {let parts = Route::getRoutePaths(notFoundPaths),routeFound = true;}}/*** Use default values before we overwrite them if the route is matched*/let this->_namespace = this->_defaultNamespace,this->_module = this->_defaultModule,this->_controller = this->_defaultController,this->_action = this->_defaultAction,this->_params = this->_defaultParams;if routeFound {/*** Check for a namespace*/if fetch vnamespace, parts["namespace"] {if !is_numeric(vnamespace) {let this->_namespace = vnamespace;}unset parts["namespace"];}/*** Check for a module*/if fetch module, parts["module"] {if !is_numeric(module) {let this->_module = module;}unset parts["module"];}/*** Check for a controller*/if fetch controller, parts["controller"] {if !is_numeric(controller) {let this->_controller = controller;}unset parts["controller"];}/*** Check for an action*/if fetch action, parts["action"] {if !is_numeric(action) {let this->_action = action;}unset parts["action"];}/*** Check for parameters*/if fetch paramsStr, parts["params"] {if typeof paramsStr == "string" {let strParams = trim(paramsStr, "/");if strParams !== "" {let params = explode("/", strParams);}}unset parts["params"];}if count(params) {let this->_params = array_merge(params, parts);} else {let this->_params = parts;}}if typeof eventsManager == "object" {eventsManager->fire("router:afterCheckRoutes", this);}}

这么多 ,前面一大堆 判断,用处大得就两个 方法,getCompiledPattern 取出 uri  所有样式,然后调用 preg_match 方法来比较 请求 得uri 跟 自己设置得uri  样式是否一致,一致得 话 就 调用checkcontroller 方法 跟 checkaction  方法,找出正确得 视图 跟 方 action。

当 uri 的 request 来到正确的 controller 跟 action ,就该调用 model 层 跟 数据库 交互。常见的是这种交互方式,基于视图的交互方式,贴出源码

 $this -> view -> setVars(array('categoryList' => $categoryList,'article' => $article,));$this -> view -> pick('articles/write');}

view  服务 是 自己 找到 view视图类 文件夹,然后注入容器的,关键是 这个pick 方法做了 什么?下面贴出源码

public function pick(var renderView) -> <View>{var pickView, layout, parts;if typeof renderView == "array" {let pickView = renderView;} else {let layout = null;if memstr(renderView, "/") {let parts = explode("/", renderView), layout = parts[0];}let pickView = [renderView];if layout !== null {let pickView[] = layout;}}let this->_pickView = pickView;return this;

这个方法主要作用是 把 查询出的变量 渲染进模板 ,返回给B端。

关于 restfiful 风格接口 一点设想,可以借鉴django

方法 URL 操作
GET /api/robots 检索所有的机器人
GET /api/robots/search/Astro 在他们的名字与 'Astro' 机器人搜索
GET /api/robots/2 检索基于主键机器人
POST /api/robots 添加一个新的机器人
PUT /api/robots/2 Updates robots based on primary key
DELETE /api/robots/2 删除基于主键机器人

好了 ,有时间 明天继续看。

关于 PHP 的框架 phalcon 学习(一) url 路由过程。相关推荐

  1. 定时任务框架APScheduler学习详解

    定时任务框架APScheduler学习详解 APScheduler简介 在平常的工作中几乎有一半的功能模块都需要定时任务来推动,例如项目中有一个定时统计程序,定时爬出网站的URL程序,定时检测钓鱼网站 ...

  2. SSM框架入门学习记录

    SSM框架入门学习记录 //项目结构 在这里插入图片描述 在这里插入图片描述 包名多种多样,命名习惯问题. 流程:Controller(接受请求)-->Service(biz)(bl)(写业务函 ...

  3. Python Web框架Django学习(二)

    python web框架Django学习(二) 目录:  三.Django创建APP  四.创建登录页面,实现用户交互,后台管理用户(非数据库方式) ========================= ...

  4. (转)MyBatis框架的学习(六)——MyBatis整合Spring

    http://blog.csdn.net/yerenyuan_pku/article/details/71904315 本文将手把手教你如何使用MyBatis整合Spring,这儿,我本人使用的MyB ...

  5. (转)MyBatis框架的学习(三)——Dao层开发方法

    http://blog.csdn.net/yerenyuan_pku/article/details/71700957 使用MyBatis开发Dao层,通常有两个方法,即原始Dao开发方法和Mappe ...

  6. (转)MyBatis框架的学习(二)——MyBatis架构与入门

    http://blog.csdn.net/yerenyuan_pku/article/details/71699515 MyBatis框架的架构 MyBatis框架的架构如下图:  下面作简要概述: ...

  7. php怎么自己写框架,PHP学习笔记,自己动手写个MVC的框架

    最新在大家自己的博客的过程中,发现各种开源的博客系统都或多或少的用起来别扭.于是想动手自己写个博客系统.既然写,就想好好写.那就先写个MVC框架.一点一点来.写的过程中有很多想法.还希望大家能够多多指 ...

  8. 后端框架flask学习小记

    1. 写在前面 最近在和几个伙伴尝试搭建一个新闻推荐系统, 算是一个推荐算法的实战项目, 里面涉及到了前后端交互, 该项目里面,使用了Flask作为后台框架, 为了理清楚整个系统的交互,所以就快速参考 ...

  9. 深度学习框架tensorflow学习与应用——代码笔记11(未完成)

    11-1 第十周作业-验证码识别(未完成) #!/usr/bin/env python # coding: utf-8# In[1]:import os import tensorflow as tf ...

  10. 关于php中laravel框架的学习--适合菜鸟初学者

    关于php中laravel框架的学习 关于laravel的介绍就不讲了,总之laravel是款比较强大的框架,它是国外框架所以在安装的上面可能比较麻烦. laravel的安装 首先安装laravel之 ...

最新文章

  1. Sql Server触发器的使用
  2. android模拟器怎么与PC通信
  3. python 合并区间
  4. Git关于pull,commit,push的总结
  5. mysql期末考试选择题
  6. 连接moogDB数据库
  7. 【Java】CMD编译Java源码遇到\ufeff问题的解决方法
  8. jni java与c++交互返回三维数组jobjectArray
  9. 一起谈.NET技术,基于CallContextInitializer的WCF扩展导致的严重问题
  10. 你要清楚SEO内容优化注意事项
  11. OSI第三层:网络层功能及作用OSI第三层:网络层功能及作用
  12. 电磁仿真CST软件学习笔记:模型创建篇(更新中)
  13. android手机通过wifi控制数码管,淫技:android无屏操作之adb操控wifi
  14. 条形码生成软件如何制作A级条码
  15. java实现Stripe信用卡支付
  16. 进制数的转换方法大全
  17. Intellij IDEA 10.5 语言设置
  18. writeup 攻防世界 Decrypt-the-Message
  19. 带负载转矩前馈补偿的永磁同步电机FOC 1.采用滑模负载转矩观测器,可快速准确观测到负载转矩。 赠送龙伯格负载转矩观测器用于对比分析
  20. spring(转账为例)四种实现方式一

热门文章

  1. 《断舍离(心灵篇)》-[日]山下英子
  2. 运行时 Entry name .... .. collided
  3. docxtemplater 图片模块_VUE+docxtemplater来处理word模板
  4. [附源码]Nodejs计算机毕业设计基于Yigo平台库房管理系统Express(程序+LW)
  5. 笔记本电脑散热风扇声音比较大解决方法
  6. 面试mysql索引底层_面试必备之MYSQL索引底层原理分析
  7. Centos7 安装mongodb 4.x
  8. 火爆全网的动态曲线图是怎么做的?
  9. JAVA 实现《飞机大战-III》游戏
  10. ☆☆如何学习MATLAB☆☆