手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表分类:PHP

typecho 插件开发(一)

看typecho第二天了,不过我还是没有仔细查看源码,只是根据一些其他插件的应用来写自己的应用。

比如,看了Akismet插件后,知道了 Typecho_Widget_Helper_Form 对象还有一个 addRule 方法,用来对数据进行验证。

昨天看了一下源码,并对应我昨天的方法了解Typecho页面中可以被注入对象的地方,在插件的activate中写了两个方法,可以让插件在全局被应用。

        Typecho_Plugin::factory('index.php')->begin = array('DbBackup_Plugin', 'backup');
        Typecho_Plugin::factory('admin/common.php')->begin = array('DbBackup_Plugin', 'backup');

嗯。是准备考虑备份的。前后台都有。正在尝试。如果并未按照我预想的情况运行的话,可能只考虑前台触发了。

加了三个参数:

        $rate = new Typecho_Widget_Helper_Form_Element_Text('rate', NULL, '1', _t('备份频率'),_t('备份数据的频率(最小单位为天,请使用整数)'));
        $form->addInput($rate->addRule('isInteger',_t('请输入整数')));
        $email = new Typecho_Widget_Helper_Form_Element_Text('email', NULL, '', _t('备份发送到'),_t('发送邮件地址。'));
        $form->addInput($email->addRule('email',_t('请输入正确的邮箱地址')));
        $lastbackup = new Typecho_Widget_Helper_Form_Element_Text('lastbackup', NULL, '', _t('上次备份时间'),_t('无需设置,由程序自动生成'));
        $form->addInput($lastbackup);

但是isInteger,这个验证方法是验证is_numeric,其实我是希望是一个正整数。现在,先将就一下下喽。离完成还早,顺便附上两个昨天写的垃圾插件,敬请测试(主要是官方论坛我注册后收不到邮件,所以无法登录。过会我再换个邮箱试试)

文章分页:已经删除,请移步typecho 插件:内容分页SplitArchivePage 进行下载 【演示地址

高亮搜索引擎来源关键字:highlightsearchkeywords.rar 【这个,在这现在这个博客上测试成功,但是在typecho上没有办法测试,因为没有数据,google搜索不到。。。】

Tags: typecho, 笔记, 插件

了解Typecho页面中可以被注入对象的地方

关于插件这个问题,可以查看这篇JianHua Zhang的Typecho阅读笔记三:插件机制,我想说的就是链接文章里的最后一句。
在Typecho_Plugin的__call魔术方法里把当前设置到的component全部打印在页面上,对于插件开发人员来说是一件非常好的事情,因为这样,你可以了解到,有哪些地方是你可以注入你的插件对象的。

大小: 156.17 K
尺寸: 407 x 376
浏览: 1927 次
点击打开新窗口浏览全图

看左上角(看不清的话,请点击看大图)。

Widget_Archive:select
Widget_Archive:handleInit

象这两个,代表了你在插件中就可以写上以下代码来进行注入。

Typecho_Plugin::factory("Widget_Archive")->select = array("插件类名","该类中的方法");

是不是很方便 ?打开每一个页面,你都可以看到类似的代码,有logo,有content,contentEx之类的。了解了这些,在相应的位置上写上你想要的效果,是不是很爽?

顺便,你需要查看一下http://docs.typecho.org/develop/widget。也可以了解一些代码是如何被调用(文中有一点点错误,在看的时候Typecho::widget,应该是Typecho_Widget::widget("xxx"))

Tags: typecho, 笔记, 插件注入

JianHua Zhang的Typecho阅读笔记三:插件机制

文章来自:http://blog.csdn.net/jh_zzz/archive/2010/01/11/5173876.aspx
由于我也正在看 typecho这个玩意所以,就记录下来。虽然我一天下来,也看了不少代码,但毕竟没有深读过。对于流程啥的,还没有开始关心,只是为了写而写。

第三篇:插件机制

index.php 为例:

/** 初始化组件 */

Typecho_Widget:: widget('Widget_Init' );

 

Init execute 中会初始化 Typecho_Plugin ,这里 $options -> plugins 是从数据库读出来后反序列化的:

Typecho_Plugin:: init($options -> plugins);

init 中分别将 plugins 中的 activated handles

PHP代码
  1. $component  =  $this -> _handle .  ':'  .  $component ;  
  2. $last = count($args );  
  3. $args [$last ] = $last > 0 ? $args [0 ] : false ;   
  4.   
  5. if (isset (self:: $_plugins ['handles' ][$component ])) {  
  6.     $args [$last ] = NULL ;  
  7.     $this -> _signal = true ;  
  8.     foreach (self:: $_plugins ['handles' ][$component ] as $callback ) {  
  9.         $args [$last ] = call_user_func_array($callback , $args );  
  10.     }  
  11. }   

__call 查找对应 index.php:begin Typecho_Plugin ,如果找到的话,就会调用相应的方法。例如如果找到的是 HelloWorld_Plugin ,则 HelloWorld_Plugin.render() 会被执行。

  (

  [0] => HelloWorld_Plugin

  [1] => render

)

 

简单说一下 Plugin 是如何加载的,在 config.inc.php 中首先设置了包含路径,插件路径也在其中:

/** 设置包含路径 */

@ set_include_path(get_include_path() . PATH_SEPARATOR .

__TYPECHO_ROOT_DIR__ . '/var' . PATH_SEPARATOR .

__TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__ );

 

HelloWorld_Plugin 此时尚未被加载,所以当执行到 HelloWorld_Plugin.render() Typecho_Common::__autoLoad 函数被执行,这里会自动加载指定的插件文件:

@ include_once str_replace('_' , '/' , $className ) . '.php' ;

例如对于 HelloWorld_Plugin ,文件就是 HelloWorld\Plugin.php ,因为 usr/plugin 目录已经在包含的路径中,所以这个文件可以正常加 载。

 

当初我学习 php 的时候还是 php3 ,现在一些新特性我都不知道,这一段我看了半天才搞 清楚,这次读这些代码了解了不少 php 的新特性:)

---EOF---

至此,JianHua Zhang的三篇博客都已经转载完毕,但是对于最后这个插件,我是建议在开发的时候,Typecho_Plugin类的__call方法里加上一行:

echo $component . '<br>';

这样可以在显示页面的时候让你了解你每块区域加载了哪些插件,也就是说,这些插件位置,是可以被你注入代码的。OK。了解了这一点,你可以根据你想要的效果为各个地方加上你的代码。

 


Tags: typecho, 笔记

JianHua Zhang的Typecho阅读笔记二:数据库访问

文章来自:http://blog.csdn.net/jh_zzz/archive/2010/01/11/5173851.aspx,由于我也正在看 typecho这个玩意所以,就记录下来。虽然我一天下来,也看了不少代码,但毕竟没有深读过。对于流程啥的,还没有开始关心,只是为了写而写。

第二篇:数据库访问

这一块比较复杂,我还没有完全理解为什么要把 SQL 语句的组装搞这么复杂。

从一个普通皮肤页面开始 themes\default\index.php ,代码如下:

PHP代码
  1. <?php  while ($this -> next()):  ?>  
  2.     < div class ="post">  
  3.        < h2 class ="entry_title">< a href ="<?php $this -> permalink() ?>"><?php $this -> title() ?></ a ></ h2 >  
  4.        < p class ="entry_data">  
  5.            < span ><?php _e(' 作者: ' ); ?><?php $this -> author(); ?></ span >  
  6.            < span ><?php _e(' 发布时间: ' ); ?><?php $this -> date('F j, Y' ); ?></ span >  
  7.            < span ><?php _e(' 分类: ' ); ?><?php $this -> category(',' ); ?></ span >  
  8.            < a href ="<?php $this -> permalink() ?>#comments"><?php $this -> commentsNum('No Comments' , '1 Comment' , '%d Comments' ); ?></ a >  
  9.        </ p >  
  10.        <?php $this -> content(' 阅读剩余部分 ...' ); ?>  
  11.     </ div >   
  12. <?php endwhile ; ?>   

从上面我们知道这个文件是在 Widget_Archive 执行时被 包含进来的,所以在这里 $this 就是 Widget_Archive next() 函数具体实现在 Typecho_Widget 中,他只是从 $stack 中取出一行数据返回,然后移向下一行, $stack 中的数据是如何生成的呢?

 

Widget_Archive execute 函数中,有这几行:

$select = $this -> select()-> where ('table.contents.status = ?' , 'publish' )

-> where('table.contents.created < ?' , $this -> options-> gmtTime);

中间代码略过

$select -> order('table.contents.created' , Typecho_Db:: SORT_DESC)

-> page($this -> _currentPage, $this -> parameter-> pageSize);

$this -> db-> fetchAll ($select , array ($this , 'push' ));

 

下面是 Widget_Abstract_Contents:: select()

PHP代码
  1. public  function  fetchAll($query , array  $filter  =  NULL )  
  2. {  
  3.     // 执行查询  
  4.     $resource = $this -> query ($query , self:: READ);  
  5.     $result = array ();    
  6.   
  7.     /** 取出过滤器 */  
  8.     if (! emptyempty ($filter )) {  
  9.         list ($object , $method ) = $filter ;  
  10.     }  
  11.   
  12.     // 取出每一行  
  13.     while ($rows = $this -> _adapter-> fetch ($resource )) {  
  14.         // 判断是否有过滤器  
  15.         $result [] = $filter ? call_user_func (array (& $object , $method ), $rows ) : $rows ;  
  16.     }  
  17.     return $result ;  
  18. }   

首先执行 query() query() 函数会执行:

$resource = $this -> _adapter-> query($query , $handle , $op , $action );

然后将查询的结果返回,根据上面 提到的 config.inc.php ,这里的 _adapter Typecho_Db_Adapter_Mysql ,他其实就是执行了一个 mysql 查询:

if ($resource = @ mysql_query($query instanceof Typecho_Db_Query ? $query -> __toString() : $query , $handle )) {

    return $resource ;

}

这里的 $query->__toString() 会返回经过 Typecho_Db_Query 处理后的 最终用来执行的 SQL 语句。

得到查询结果后,上面的 fetchAll 函数就循环调用回调函数将数据回调出去,前面的代码中 Widget_Archive 在调用时指定的是 push ,在 push 函数中返回的每一行数据都被压入 $stack ,这样 $stack 中就有了一行行的数据了。

 

 

Tags: typecho, 笔记

JianHua Zhang的Typecho阅读笔记一:页面渲染及路由机制

文章来自:http://blog.csdn.net/jh_zzz/archive/2010/01/11/5173806.aspx,由于我也正在看typecho这个玩意所以,就记录下来。虽然我一天下来,也看了不少代码,但毕竟没有深读过。对于流程啥的,还没有开始关心,只是为了写而写。

第一篇:页面渲染及路由机制

index.php 开始看,

 

/** 初始化组件 */

Typecho_Widget:: widget('Widget_Init' );

 

Typecho_Widget:: widget 函数,查找 Widget\Init.php Widget 下的文件都是从 Typecho_Widget 派生的,这里创建该对象实例,并将相关的 Request Response 对象作为参数传递过去,然后调用该对象的 execute 方法。

 

看一下 Init 中的 execute ,首先会初始化一些参数,重点看看 MVC 架构的路由:

Typecho_Router:: setPathInfo($this -> request-> getPathInfo());

Typecho_Router:: setRoutes($options -> routingTable);

首先设置路径,然后初始化路由, $options -> routingTable 默认值是在安装时写在数据库中的,运行时再读出来, Typecho_Router setRoutes 函数调用了 Typecho_Router_Parser parse 函数, parse 函数遍历整个 routingTable 数组,将处理后的路由数组返回给 Typecho_Router ,保存在 $_routingTable

PHP代码
  1. if  (! $validated  &&  ! emptyempty ($this -> _archiveSlug)) {  
  2.     $themeFile = $this -> _archiveType . '/' . $this -> _archiveSlug . '.php' ;  
  3.     if (file_exists($themeDir . $themeFile )) {  
  4.         $this -> _themeFile = $themeFile ;  
  5.         $validated = true ;  
  6.     }  
  7. }   

 

这里需要看一下 _archiveType _archiveSlug 是怎么来的:

Widget_Archived execute 函数中会根据 $this -> parameter-> type 执行相应的 handler

PHP代码
  1. if  (isset ($handles [$this -> parameter-> type])) {  
  2.     $handle = $handles [$this -> parameter-> type];  
  3.     $this -> {$handle }($select , $hasPushed );  
  4. else {  
  5.     $hasPushed = $this -> pluginHandle()-> handle($this -> parameter-> type, $this , $select );  
  6. }   

 

$this -> parameter-> type 这个变量是在构造函数中赋值的 :

$this -> parameter-> type = Typecho_Router:: $current ;

Typecho_Router:: $current 根据路由表可以查到对应于 index.php 就是 index

 

所以对于上面标黄的代码对应于 index.php 最终执行的是的是 $handles [‘index’] 对应的 handle ,就是 indexHandle 。可以看到对于其他的 Handle 一般都会设置 _archiveType _archiveSlug 变量, indexHandle 没有,因为 _archiveType 默认就是 index ,所以在 index.php _archiveType 等于 index _archiveSlug 为空。

 

所以根据前面 render 函数中的代码,最终是找到对应于 $themeDir 下的 $this -> _archiveType . '/' . $this -> _archiveSlug . '.php' 文件,然后直接包含进来,我们看到的就是这个文件的输出了。

 

/** 注册一个结束插件 */

Typecho_Plugin:: factory('index.php' )-> end();

Tags: typecho, 笔记