2

JustWriting是一个用PHP,基于CI框架的极简主义博客系统,在这里,你甚至不需要数据库,直接用Markdown写博客就可以了,就像我此刻一样,直接用Mou来写这篇博客分享一样,So easy.Enjoy!

当初发现这个博客系统的时候真是眼前一亮:这就是我要的博客系统啊!不仅可以个人写作分享,还可以一个团队进行团队的博客协作。详细说明和教程请参考JustWriting作者的Demo,

在下还是很佩服像这样能写出一些确确实实好用的东西的人,恰好本人也是一个PHP的入门者,用了一段时间,难免会有一种看其(源码)究竟的感觉,于是,我打开Sublime,一行一行的尝试解读代码,JustWriting的核心部分其实就是理解Hjue这位大神写的applications\libraries\blog_lib.php这个文件就足以。关于CI框架和一些第三方的库比如applications\third_party\Michelf这个Markdown解析库可以自行开撸,OK,上代码吧:

<?php
     date_default_timezone_set("Asia/Chongqing");    
     $file_ext='.md';
     $posts_path = "posts/";
     $handle = opendir($posts_path);
     //var_dump($handle);
     while (false !== ($entry = readdir($handle))) {
     //$entry 得到了所有的文件名,包括. 还有..
     if(substr(strrchr($entry,'.'),1)==ltrim($file_ext, '.')) {
    //这里的判断条件是将. 和 ..的文件去掉了,得到所有想要的Markdown文件
        $fcontents = file($posts_path.$entry);
        //$fcontents array() 得到了所有的文件内容,
        $hi=0;
        $pattern = '/^\s*(title|date|position|description|      intro|status|toc|url|feature|tags)\s*:(.*?)$/im';
        $post_title='';
        $post_intro='';
        $post_date='';
        $post_status='public'; 
        $post_tags=array();
        while(!trim($fcontents[$hi])){
          $hi++;
          continue;
        }
        while(trim($fcontents[$hi])){
            //$fcentents[$hi] 得到了全部的 Date,Title,intro 
        
          preg_match($pattern, $fcontents[$hi], $matches);
          //$matches array() 长度为三的数组 $matchs[0] $matches[1] $matches[2]
          //$matches[0]:得到一个Date,Title,intro字符串的全部,比如 Date: 2014-08-22
          //$matches[1]:得到一个Date,Title,intro字符串冒号的前半部分,比如 Date
          //$matches[2]:得到一个Date,Title,intro字符串冒号的前半部分,比如 2014-08-22
            
          $hi++;
          if(empty($matches)) break;
          else{
            switch (trim(strtolower($matches[1]))) {
                //有了上面的 $matches array(),这里的switch就很好理解了
              case 'title':
                $post_title = $matches[2];
                break;
              case 'date':
                $post_date = trim($matches[2]);
                break;    
                case 'feature':
                  $post_feature = trim($matches[2]);
                 //这个是我自己加的哈,提供一个了feature images的功能
                  break;

              case 'tags':
                $tags = trim($matches[2]);
                if(substr($tags,0,1)=='[') $tags = substr($tags,1);
                if(substr($tags,-1,1)==']') $tags = substr($tags,0,-1);
                //这里的substr是将[ ]去掉了
                $post_tags = preg_split('#[,\s]#',$tags, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
                //$post_tags 得到每篇的tags 数组 }
            
             if(empty($post_date))
                {
                  $post_date = filemtime($posts_path.$entry);
                  //$post_date为空,则使用文件的创建时间(这种情况通常是作者忘了写
                  //Date: 2014-08-24)其实也是可以不写的
                }else{
                  $post_date = strtotime($post_date);
                  //$post_date 转为时间
                   
                }
          }                
        }
        
    }
    }

```
/*************************************************************************************************
这里是分割线,不知道SF对代码块的Markdown转译是怎么样的,这里的第一个函数竟然会跟上面的一堆代码在一起了,这不科学,所以我要华丽的分割线:
**************************************************************************************************/

`###说说其中用到的PHP函数:`

[resource opendir ( string $path [, resource $context ] )](http://php.net/manual/zh/function.opendir.php)

打开一个目录句柄,可用于之后的 closedir(),readdir() 和 rewinddir() 调用中,看下面的例子

```
<?php
$dir = "/etc/php5/";

//官方的经典使用方法,其实掌握官方的经典实用方法已经很OK
if (is_dir($dir)) {
    if ($dh = opendir($dir)) {
        while (($file = readdir($dh)) !== false) {
            echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
        }
        closedir($dh);
    }
}
?>

第二个就是 : string readdir ([ resource $dir_handle ] )

返回目录中下一个文件的文件名。文件名以在文件系统中的排序返回。这个在这里显得很有用哇,简直这函数突然感觉就神了!上面已经给出这个函数的最佳使用方式,

    /* 这是正确地遍历目录方法 */
    while (false !== ($file = readdir($handle))) {
        echo "$file\n";
    }

array file ( string $filename [, int $flags = 0 [, resource $context ]] )

将一个文件读入数组中,这可能就是Hjue使用file()的原因,当初我在想为啥不用file_get_contents(),This is the reason .

其实要看解决这个Blog的一些问题,关键还是得在正则上花点心思,所以来观摩一下大神的用法:

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

这个函数的注意的是matches这个参数:

matches 如果提供了参数matches,它将被填充为搜索结果。 $matches[0]将包含完整模式匹配到的文本,$matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。

看一个经典的用法,取得一个url 的域名:

<?php
//从URL中获取主机名称
preg_match('@^(?:http://)?([^/]+)@i',
    "http://www.php.net/index.html", $matches);
$host = $matches[1];

//获取主机名称的后面两部分
preg_match('/[^.]+\.[^.]+$/', $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>

最后来看看这个处理标签$post_tags的函数,当时我真是眼前一亮啊,果然得仔细看文档啊

array preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] )

官方给的定义是:通过一个正则表达式分隔给定字符串.

值得关注的是这个函数的返回值:

返回一个使用 pattern 边界分隔 subject 后得到 的子串组成的数组

简直爽歪歪,这种函数真是应该放在大脑的内存区域的~~~

<?php
//使用逗号或空格(包含" ", \r, \t, \n, \f)分隔短语
$keywords = preg_split("/[\s,]+/", "hypertext language, programming");
print_r($keywords);
?>

/*  返回这个数组,神奇吧!
    Array
    (
        [0] => hypertext
        [1] => language
        [2] => programming
    )
 */

写了这么多(老实的搬运工),先睡了。其实主要是是记录一下自己的笔录,不过还是强烈推荐大家上手JustWriting,从此写博客就不是什么难事了。详细教程请参考 作者的Demo教程网站 : http://justwriting.sinaapp.com/
如果你在部署过程中有啥问题,也可以直接找我哈!留下你的评论吧

最后留个彩蛋吧: [http://justwriting.com/](http://justwriting.com/)

原文链接 : http://www.jellybool.com/post/justwriting-source-code


JellyBool
16.2k 声望2k 粉丝

给学网 GeiXue.com 创始人:让每一个热爱编程的人都学有所成的精品课程。