用sphinx给PHP加个给力的搜索功能

28 Dec 2018 Category: php

最近工作上需要实现搜索功能,尝试了几种方案。虽然最终线上部署的还是最low的方案,但是中间的过程还是比较有意思的。业务上根据关键字查找内容。关键字的出处多来源于标题,文章描述等。主要实现方式有一些几种,各个方式各有利弊,需要权衡。

like模糊查询标题和描述,使用或条件查询

like查询估计是最常用的方式了,也是最容易实现的方式。业务代码少,逻辑清晰,准确率也高。不用其他额外操作(比如分词)。但是有个非常致命的问题,那就是效率。效率非常低,特别是在数据量大的情况。测试过程中,在224256行数据中,对3749个字进行like查询,执行总时间长达4003秒。相当于每个查询需要花费1.06秒的查询时间。

查看更多

如何给PHP添加多个错误处理函数

18 Dec 2018 Category: php

一些常规的PHP框架都会对PHP的错误、异常进行异常处理封装,方便框架日志记录,开发的时候方便处理。我们先看看几个框架错误处理:

Laravel

Laravel在app初始化的时候注册了错误处理函数,异常处理函数,异常退出处理函数,最终将错误转化成异常抛出,统一通过异常处理函数进行处理。

    public function bootstrap(Application $app)
    {
        $this->app = $app;
        error_reporting(-1);
        set_error_handler([$this, 'handleError']);
        set_exception_handler([$this, 'handleException']);
        register_shutdown_function([$this, 'handleShutdown']);
        if (! $app->environment('testing')) {
            ini_set('display_errors', 'Off');
        }
    }
    public function handleError($level, $message, $file = '', $line = 0, $context = [])
    {
        if (error_reporting() & $level) {
            throw new ErrorException($message, 0, $level, $file, $line);
        }
    }
    public function handleShutdown()
    {
        if (! is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
            $this->handleException($this->fatalExceptionFromError($error, 0));
        }
    }

查看更多

ThinkCMF thinkphp5.1 个人修改版本

05 Dec 2018 Category: php

上一个项目在api上使用了thinkphp5.1,但是后台还是使用thinkcmf5.0,tp版本是5.0 .当时就想统一thinkphp版本。最近得空有时间修改,因此在ThinkCMF 5.0.180901基础上将thinkphp版本改成5.1.29 。修改后,已经对本地测试的不兼容进行修改。

ThinkCMF修改基础版本

ThinkCMF 5.0.180901 正式版

ThinkPHP版本

thinkphp5.1.29

目录结构改动

  • vendor目录移动到根目录

修改原因: \think\Loader 中注册vendor目录是写死的,没办法动态修改,除非重写Loader self::$composerPath = $rootPath . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR;

查看更多

PHP神奇又有用的Trait

20 Nov 2018 Category: php

php和java,c++一样都是单继承模式。但是像python,是支持多继承(即Mixin模式)。那么如何在php中实现多继承模式?这就需要使用trait。

Trait使用方式:

trait Arrayabletrait{
	public function toArray(){

	}
}

class Model{
	use Arrayabletrait;
}


$model = new Model();
$model->toArray();

Trait使用场景

  • 有些功能不需要类的方法属性,但是在不同的类都有使用需求。例如上面的对象转数组方法。 这种情况可以使用一个基类定义toArray方法,则需要将这类基础方法定义在尽可能顶层的基类当中,保证所有的类都能够调用这个方法。

  • 类因为某些需求,已经继承了第三方类对象。例如第三方orm模型类。这种情况如果要给类附加一些公共的功能,除了创建一个继承于orm模型的基类,复制一套公共功能的代码之外,就可以使用trait。

查看更多

如何快速高效的将数组转换成树形结构

13 Nov 2018 Category: php

任何无限极分类都会涉及到创建一个树状层级数组。从顶级分类递归查找子分类,最终构建一个树状数组。如果分类数据是一个数组配置文件,且子类父类id没有明确的大小关系。那么我们如何高效的从一个二维数组中构建我们所需要的树状结构呢。

假设数据源如下:


return [
	['id'=>1,'name'=>'文章','parent_id'=>0],
	['id'=>2,'name'=>'页面','parent_id'=>0],
	['id'=>3,'name'=>'娱乐','parent_id'=>1],
	['id'=>4,'name'=>'国内','parent_id'=>1],
	['id'=>5,'name'=>'海外','parent_id'=>1],
	['id'=>6,'name'=>'北京','parent_id'=>4],
	['id'=>7,'name'=>'上海','parent_id'=>4]
];

查看更多

Design Patten On Php

18 Oct 2018 Category:


layout: post title: 设计模式(一),创建模式(如何创建,谁创建,什么时候创建) category: 算法 comments: true description: 设计模式(一),创建模式(如何创建,谁创建,什么时候创建) keywords: 设计模式,工厂模式,单例模式,建造者模式 —

1、工厂模式 通过工厂类,创建不同的对象。工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。

以日志操作类为例

abstract class BaseApp{
	protected $input;
	protected $response;
	protected $route;
	public function start(){
		return $this->handlerRequest();
	}
	public function setInput($input){
		$this->input = $input;
	}
	public function setResponse($response){
		$this->response = $response;
	}
	public function setRoute($route){
		$this->route = $route;
	}
	abstract public function handlerRequest();
}

class CliApp extends BaseApp{
	protected $args;
    public function handlerRequest(){
        //write to file
    }
}

class WebApp extends BaseApp{
	protected $urlparams;
	protected $requestMethod;
	protected $remoteIp;


    public function handlerRequest(){
        //write to db
    }
}

查看更多

Yii2和thinkphp5中一个微小的差异造成bug的根源

16 Oct 2018 Category: php

考虑一个场景,一个函数需对相同表进行多次查询,多次查询中有部分查询条件相同。对于这种情况,Yii2和thinkphp5的实现方式要格外小心。在Yii2中,可以直接使用clone 复用共同的查询条件,但是thinkphp5的话,必须把相同条件再重复写一次。

例如,需要查询总有效文章数,以及今日发布有效文章数。

Yii2 版本


$query = Post::find();
$query->where(['status'=>1,'is_delete'=>0]);
$todayquery = clone $query;
$todayquery->andFilterWhere(['between','create_at',$start_date, $end_date])
$totalcount = $query->count();
$todaycount = $todayquery->count();

查看更多

高性能MySQL(第3版)阅读笔记

15 Oct 2018 Category: sql

  • char(5) 和varchar(200) 存储’hello’的空间开销相同,使用短列有什么优势?

  • mysql会分配固定大小内存块保存内部值,尤其使用内存表临时表进行排序,操作时。因此最好只分配需要的存储空间。

  • 数据类型越短越好,尽量避免NULL(NULL索引,统计,比较更复杂,可为NULL的列需要的存储空间更多)

  • 整数(tinyint 8位,smallint 16位,mediumint 24位,int 32位,bigint 64位储储空间)mysql 可为整数指定列宽,但是列宽只是为图像化界面显示字符个数

  • decimal 可指定小数点前后允许的最大位数,消耗存储空间,mysql 将数字打包在二进制字符串中,每4个字节存储9个数字,小数点战一个字节

  • float 在存储相同范围的数据,占用存储空间比decimal小,float 使用4个字节存储,double占用8个字节

  • varchar 存储变成字符串,需要1位或2位保存长度。长度小于255使用1位。由于变长,更新操作更费时间(更新使得行数据长度变化,myisam 将数据猜成不同存储片段,innodb则需要分裂页,将数据放进页内)。mysql5 在存储varchar 的时候,空格会保留??

  • 以下情况适合使用varchar[高性能MySQL(第3版)p115]: 字符串最大长度比平均长度大很多,列的更新少(不会产生碎片);使用类似UTF8字符集,每个字符使用不同字节数存储

  • char ,mysql会根据定义的长度分配固定空间,当存储cahr类型数据,mysql会去除末尾空格。char适合存储固定长度,或长度相近的数据。对于经常变更的数据,char比varchar好,因为不会产生碎片

  • binary,varbinary 固定长度二进制,变长二进制字符串,采用”\0”结束

  • blob,text blob以二进制方式存储,没有排序规则;text存储字符串,有字符集排序规则。mysql 对blob,text排序是对列前面max_sort_length排序,而不是整个字符串排序。

  • enum 类型。枚举类型将列表值压缩到一个或两个字节中,内部保存的是整数,并在.frm保存字符串,整数映射关系。枚举类型排序是按内部整数排序,而非字符排序。枚举列,字符串列表是固定的,每次添加修改都需要使用alter table。将char,varchar 和枚举类型关联时,会比直接cahr,varchar关联慢。

查看更多