Laravel memcached缓存对文章增删改查进行优化例子

 更新时间:2016年11月25日 16:16  点击:1945
本文章来为各位介绍一篇关于Laravel memcached缓存对文章增删改查进行优化例子,希望这篇文章能够帮助到各位。

本节我们将以文章的增删改查作为实例系统讲述缓存的使用,这个实例是对之前创建RESTFul风格控制器实现文章增删改查这篇教程的改造和升级,我们将在其基础上融合进Eloquent ORM和模型事件,将应用的场景直接拉到生成环境。

1、准备工作

路由及控制器

路由的定义和控制器的创建保持和创建RESTFul风格控制器实现文章增删改查中一样。

创建数据表

关于文章对应数据表我们在数据库部分使用查询构建器实现对数据库的高级查询已有提及,这里我们使用之前创建的数据表即可。

创建文章模型

关于文章模型Post的创建也和之前Eloquent ORM部分讲ORM概述、模型定义及基本查询中创建的一致。

2、修改控制器

在之前我们是通过缓存实现对文章的增删改查操作,这里我们将其修改为通过数据库实现增删改查操作:

<?php

    namespace App\Http\Controllers;

    use Illuminate\Http\Request;

    use Cache;
    use App\Models\Post;

    use App\Http\Requests;
    use App\Http\Controllers\Controller;

    class PostController extends Controller
    {
        /**
         * 显示文章列表.
         *
         * @return Response
         */
        public function index()
        {
            //使用all获取所有数据,如果数据量大采用分页获取
            $posts = Post::all();
            if(!$posts)
                exit('还没有发布任何文章!');

            $html = '<ul>';

            foreach ($posts as $post) {
                $html .= '<li><a href='.route('post.show',['post'=>$post]).'>'.$post->title.'</li>';
            }

            $html .= '</ul>';

            return $html;
        }

        /**
         * 创建新文章表单页面
         *
         * @return Response
         */
        public function create()
        {
            $postUrl = route('post.store');
            $csrf_field = csrf_field();
            $html = <<<CREATE
                <form action="$postUrl" method="POST">
                    $csrf_field
                    <input type="text" name="title"><br/><br/>
                    <textarea name="content" cols="50" rows="5"></textarea><br/><br/>
                    <input type="submit" value="提交"/>
                </form>
CREATE;
            return $html;
}

        /**
         * 将新创建的文章存储到存储器
         *
         * @param Request $request
         * @return Response
         */
        public function store(Request $request)
        {
            $title = $request->input('title');
            $content = $request->input('content');

            $post = new Post;
            $post->title = $title;
            $post->content = $content;
            $post->save();

            return redirect()->route('post.show',['post'=>$post]);
        }

        /**
         * 显示指定文章
         *
         * @param int $id
         * @return Response
         */
        public function show($id)
        {

            $post = Cache::get('post_'.$id);
            if(!$post){
                $post = Post::find($id);
                if(!$post)
                    exit('指定文章不存在!');
                Cache::put('post_'.$id,$post,60*24*7);
            }

            if(!Cache::get('post_views_'.$id))
                Cache::forever('post_views_'.$id,0);
            $views = Cache::increment('post_views_'.$id);
            Cache::forever('post_views_'.$id,$views);

            $editUrl = route('post.edit',['post'=>$post]);
            $deleteUrl = route('post.destroy',['post'=>$post]);
            $html = <<<POST
                <h3>{$post->title}</h3>
                <p>{$post->content}</p>
                <i>已有{$views}人阅读</i>
                <p>
                    <a href="{$editUrl}">编辑</a>
                </p>
POST;

            return $html;
        }

        /**
         * 显示编辑指定文章的表单页面
         *
         * @param int $id
         * @return Response
         */
        public function edit($id)
        {
            $post = Post::find($id);

            if(!$post)
                exit('指定文章不存在!');

            $postUrl = route('post.update',['post'=>$post]);
            $csrf_field = csrf_field();
            $html = <<<CREATE
                <form action="$postUrl" method="POST">
                    $csrf_field
                    <input type="hidden" name="_method" value="PUT"/>
                    <input type="text" name="title" value="{$post->title}"><br/><br/>
                    <textarea name="content" cols="50" rows="5">{$post->content}</textarea><br/><br/>
                    <input type="submit" value="提交"/>
                </form>
CREATE;
            return $html;

        }

        /**
         * 在存储器中更新指定文章
         *
         * @param Request $request
         * @param int $id
         * @return Response
         */
        public function update(Request $request, $id)
        {
            $post = Post::find($id);
            if(!$post)
                exit('指定文章不存在!');

            $title = $request->input('title');
            $content = $request->input('content');

            $post->title = $title;
            $post->content = $content;

            $post->save();

            return redirect()->route('post.show',['post'=>$post]);
        }

        /**
         * 从存储器中移除指定文章
         *
         * @param int $id
         * @return Response
         */
        public function destroy($id)
        {
            $post = Post::find($id);
            if(!$post)
                exit('指定被删除文章不存在!');

            if($post->delete()){
                redirect()->route('post.index');
            }else{
                exit('删除文章失败!');
            }
        }
    }

需要注意的是在show方法中,我们首先从缓存中取文章数据,缓存中不存在才会去数据库取,同时将数据回写到缓存中,由于对数据库的操作大部分都是读操作,所以这一点小小的改进对性能却有很大提升,尤其是在海量数据时。此外我们还将访问量持久化到缓存中以提升性能。

3、在模型事件中使用缓存

我们还可以通过模型事件在文章进行增删改的时候触发相应事件将修改保存到缓存中,这里我们简单讲模型事件注册到AppServiceProvider的boot方法中:

//保存之后更新缓存数据
Post::saved(function($post){
    $cacheKey = 'post_'.$post->id;
    $cacheData = Cache::get($cacheKey);
    if(!$cacheData){
        Cache::add($cacheKey,$post,60*24*7);
    }else{
        Cache::put($cacheKey,$post,60*24*7);
    }
});

//删除之后清除缓存数据
Post::deleted(function($post){
    $cacheKey = 'post_'.$post->id;
    $cacheData = Cache::get($cacheKey);
    if($cacheData){
        Cache::forget($cacheKey);
    }
    if(Cache::get('post_views_'.$post->id))
        Cache::forget('post_views_'.$post->id);
});

我们将缓存有效期设置为一周。这样在文章创建或更新时会将数据保存到缓存,而删除文章时也会从缓存中移除数据,从而保证被删除后的文章查看详情时也不能浏览。

Memcached缓存配置在任何php环境下我们都可以配置使用来提升WEB的性能了,下面我们来看一篇Laravel Memcached缓存驱动的配置应用实例,具体的细节如下所示。

对于大型网站(数据多,访问量大)而言,缓存系统是必备组件,其为减轻数据库负载、提高页面访问速度、提升系统性能立下汗马功劳。Laravel作为一个功能完善且强大的PHP框架,自然为缓存系统提供了支持。目前Laravle支持的缓存驱动包括文件、数组、数据库、APC、Memcached和Redis,并且为这些驱动提供了统一的存取接口,这样做的好处显而易见:我们可以根据业务需求随时切换缓存驱动而不用对业务逻辑代码做任何修改。

Laravel缓存驱动配置位于config/cache.php,该配置数组中第一个配置项default用于指定默认缓存驱动:

'default' => env('CACHE_DRIVER', 'file'),

这里默认缓存驱动为文件缓存。第二配置项stores是重头戏,用于配置Laravel支持的6种缓存驱动:

'stores' => [

    'apc' => [
        'driver' => 'apc',
    ],

    'array' => [
        'driver' => 'array',
    ],

    'database' => [
        'driver' => 'database',
        'table' => 'cache',
        'connection' => null,
    ],

    'file' => [
        'driver' => 'file',
        'path' => storage_path('framework/cache'),
    ],

    'memcached' => [
        'driver' => 'memcached',
        'servers' => [
            [
                'host' => '127.0.0.1',
                'port' => 11211,
                'weight' => 100,
            ],
        ],
    ],

    'redis' => [
        'driver' => 'redis',
        'connection' => 'default',
    ],

],

其中apc表示APC缓存,APC是PHP的一个扩展,其目标是为缓存和优化PHP中间码(opcode)提供一个免费、开源、健壮的框架。更多详情可参考PHP官方文档:http://php.net/manual/zh/book.apc.php,APC缓存和Memcached一样都是基于内存的缓存系统,性能相当,但局限是只能用于单机缓存,不支持分布式,而实际生产环境往往并不止一台web服务器,所以相对而言,大型网站更多选择使用Memcached。

数组缓存驱动(array)往往仅仅用于测试,好处是不会持久化,只会在一次PHP脚本执行的生命周期内有效。

文件缓存驱动(file)往往只用于本地开发测试,因为文件缓存将缓存存储到文件中,读取时从硬盘读取,性能自然不及基于内存的缓存系统如APC或Memcached以及Redis。

数据库缓存驱动(database)将缓存数据存储到数据库中,使用之前需要在数据库中新建一张表用于存放缓存项,该表表结构可定义如下:

Schema::create('cache', function($table) {
    $table->string('key')->unique();
    $table->text('value');
    $table->integer('expiration');
});

缓存本来就是将数据库中的数据读取后存放到缓存系统,虽然数据库缓存在一定程度上提升了系统性能,但对于大型系统而言自然不是最佳选择。

memcached缓存驱动基于Memcached,使用之前需要先在系统中安装Memcached,当然如果你使用的是Homestead虚拟机的话,已经为你安装好了,并且开机自动启动,我们可以使用如下指令查看其状态及启动端口:

ps -ef | grep memcached

正如我们前面提到的,Memcached是基于内存的分布式缓存系统,在实际生产环境中有着广泛使用。

Redis是近几年才出现的缓存系统,相比Memcached的键值对而言支持更多的数据结构,包括字符串、哈希、列表、集合和有序集合等,正因如此,又被称作数据结构服务器,Redis也是基于内存的,但是可以持久化到硬盘。除了作为缓存系统外,还可以用作NoSQL数据库、消息队列等。总而言之,功能很强大。关于Redis我们后续会单独讲,所以缓存实例这一块我们将以Memcached作为缓存驱动为例,系统的讲讲Laravel中如何使用缓存。

从配置文件说起,memcached配置项中的driver指定使用的缓存驱动类型为memcached。servers表示使用的安装Memcached的服务器,host代表主机名,port代表Memcached监听的端口号,默认为11211,weight代表权重,因为很多时候我们配置了多台Memcached服务器,权重表示存取的优先级。

作为测试,这里我们就使用默认配置好了。

开始之前我们要将默认缓存驱动改成memcached:

'default' => env('CACHE_DRIVER', 'memcached'),

此外,config/cache.php配置文件中还有最后一个配置项prefix,用于配置缓存键的前缀,对于基于内存的缓存系统而言,缓存项可能被同一主机上的多个应用使用,所以加上前缀以示区别还是很有必要的。这里我们使用laravelacademy作为前缀好了:

'prefix' => 'laravelacademy',

Laravel 5.1中500错误是程序错误,程序错误一定是系统自带的500错误,如果我们想自定义的话可以和小编来看看如何做。

500错误页面

编辑PHP文件app/Exceptions/Handler.php内容如下:

 代码如下 复制代码

public function render($request, Exception $e)
{

    if ($e instanceof ModelNotFoundException) {
        $e = new NotFoundHttpException($e->getMessage(), $e);
    }

    if($e instanceof \Symfony\Component\Debug\Exception\FatalErrorException
        && !config('app.debug')) {
        return response()->view('errors.default', [], 500);
    }

    return parent::render($request, $e);
}

然后编辑自定义错误页面对应视图文件errors.default.blade.php。

验证码(Captcha)开源软件了,我们可以利用它结合Laravel 5生成验证码了,并且它在不断的更新算法比较难破解了,下面来看一篇Captcha为Laravel 5 应用生成验证码例子具体如下。

Laravel Captcha

1、安装

我们通过 Composer 安装 Captcha 扩展包:

composer require mews/captcha

注:Windows中使用该扩展包还需要安装 GD2 扩展(在php.ini中取消php_gd2.dll前面的注释)。

2、配置

使用Captcha服务提供者之前还需要在config/app.php中注册服务提供者:

'providers' => [
    // ...
    Mews\Captcha\CaptchaServiceProvider::class,
]

同时注册下相应门面:

'aliases' => [
    // ...
    'Captcha' => Mews\Captcha\Facades\Captcha::class,
]

如果要使用自定义的配置,还可以发布配置文件到config目录:

$ php artisan vendor:publish

编辑新生成的captcha.php:

return [
    'default' => [
        'length' => 5,
        'width' => 120,
        'height' => 36,
        'quality' => 90,
    ],
    // ...
];

3、使用示例

// app/Http/routes.php

Route::any('captcha-test', function()
{
    if (Request::getMethod() == 'POST')
    {
        $rules = ['captcha' => 'required|captcha'];
        $validator = Validator::make(Input::all(), $rules);
        if ($validator->fails())
        {
            echo '<p style="color: #ff0000;">Incorrect!</p>';
        }
        else
        {
            echo '<p style="color: #00ff30;">Matched :)</p>';
        }
    }

    $form = '<form method="post" action="captcha-test">';
    $form .= '<input type="hidden" name="_token" value="' . csrf_token() . '">';
    $form .= '<p>' . captcha_img() . '</p>';
    $form .= '<p><input type="text" name="captcha"></p>';
    $form .= '<p><button type="submit" name="check">Check</button></p>';
    $form .= '</form>';
    return $form;
});


显示效果如下:

Laravel Captcha

如果要返回原生图片,可以调用这个函数:

captcha();
或者

Captcha::create();
如果要返回URL:

captcha_src();
或者

Captcha::src();
如果要返回HTML:

captcha_img();
我们这个示例中使用的就是这个函数,或者调用Captcha门面上的方法:

Captcha::img();
要使用配置文件captcha.php中不同的配置项,可以这样调用:

captcha_img('flat');
Captcha::img('inverse');

注意:

在laravel 5.2中这个包会出现验证码怎么也无法验证成功的问题,因为5.2采用了middleware分组,并没有使用全局中间件导致这个包没有启用session导致上述问题。解决办法:在

vendor/mews/captcha/src/CaptchaServiceProvider.php
29行的

this->app['router']->get('captcha/{config?}', '\Mews\Captcha\CaptchaController@getCaptcha')
后面添加

->middleware('web');

确认你的web中间件分组内有StartSession中间件。另外你也可以添加5.2新特性频率限制到后面

->middleware('throttle:60,1')

以防止恶意攻击。

[!--infotagslink--]

相关文章

  • Yii2.0高级框架数据库增删改查的一些操作

    yii2.0框架是PHP开发的一个比较高效率的框架,集合了作者的大量心血,下面通过用户为例给大家详解yii2使用中的一些基本的增删改查操作。 User::find()->all(); //返回所有用户数据; User::findOne($id); //返回 主键...2015-11-24
  • vue实现在进行增删改操作后刷新页面

    这篇文章主要介绍了vue实现在进行增删改操作后刷新页面,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-05
  • Jquery easyui开启行编辑模式增删改操作

    jquery easyui框架提供了创建网页所需要的一切,可以帮助大家建立站点,接下来,通过本文给大家介绍Jquery easyui开启行编辑模式增删改操作,感兴趣的朋友一起学习...2016-01-15
  • Django开发RESTful API实现增删改查(入门级)

    这篇文章主要介绍了Django开发RESTful API实现增删改查(入门级),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-10
  • SQLite 入门教程四  增删改查 有讲究

    增删改查操作,其中增删改操作被称为数据操作语言 DML,相对来说简单一点。 查操作相对来说复杂一点,涉及到很多子句,所以这篇先讲增删改操作,以例子为主,后面再讲查操作...2020-07-11
  • php SQLite增删改减实现代码

    db.execsql(sql); 或者db.insert()、db.delete()、db.update(),并且包括数据表的创建和删除等等也可以通过execsql实现 //创建表 代码如下 复制代码 ...2016-11-25
  • 搭建MyBatis-Plus框架并进行数据库增删改查功能

    这篇文章主要介绍了搭建MyBatis-Plus框架并进行数据库增删改查,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-12
  • php memcache和php memcached比较以及问题

    php memcache和php memcached是php的memcache分布式的高速缓存系统的两个客户端,php memcache是老客户端,php memcached是功能更加完善的新的代替php memcached的。...2016-11-25
  • PHP中加速、缓存扩展的区别和作用详解(eAccelerator、memcached、xcache、APC )

    这篇文章主要介绍了PHP中eAccelerator、memcached、xcache、APC 4个加速、缓存扩展的区别的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下...2016-07-25
  • Mybatis实现动态增删改查功能的示例代码

    这篇文章主要介绍了Mybatis实现动态增删改查功能的示例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-02
  • php memcache和memcached模块安装应用

    memcache的官方主页:php教程.net/package/memcache">http://pecl.php.net/package/memcache memcached的官方主页:http://pecl.php.net/package/memcached 以下是我安装...2016-11-25
  • Mybatis基于xml配置实现单表的增删改查功能

    这篇文章主要介绍了Mybatis基于xml配置实现单表的增删改查,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-12
  • Memcached 入门代码实例

    代码如下 复制代码 <?php教程 class mycache { private $cache; function __construct() { $this->cache = new memcache();...2016-11-25
  • PHP MemCached 缓存应用

     Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱...2016-11-25
  • memcached的安装、配置等基本命令

    memcached是一个超高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载了,现在我们就来看看如何配置memcached吧,希望能帮助到大家。 memcached的基本...2016-11-25
  • Laravel查询构建器对数据库增删改查的例子

    本文章来为各位介绍一篇Laravel对数据库增删改查的例子了,这个是基于查询构建器来实现了,具体的如下所示。 获取查询构建器很简单,还是要依赖DB门面,我们使用DB门面的...2016-11-25
  • Yii针对添加行的增删改查操作示例

    这篇文章主要介绍了Yii针对添加行的增删改查操作,涉及Yii结合jQuery针对页面元素的动态操作及数据库增删改查等操作相关实现技巧,需要的朋友可以参考下...2016-10-20
  • Memcached 应用与分析(1/9)

    ◎Memcached是什么 在阐述这个问题之前,我们首先要清楚它“不是什么”。很多人把它当作和SharedMemory那种形式的存储载体来使用,虽然memcached 使用了同样的&...2016-11-25
  • C#访问SQLServer增删改查代码实例

    这篇文章主要为大家详细介绍了C#访问SQLServer增删改查代码实例,感兴趣的小伙伴们可以参考一下...2020-06-25
  • 微信小程序本地缓存数据增删改查实例详解

    这篇文章主要介绍了微信小程序本地缓存数据增删改查实例详解的相关资料,需要的朋友可以参考下...2017-05-27