Laravel 5.1自定义500错误页面的例子
编辑PHP文件app/Exceptions/Handler.php内容如下:
代码如下 | 复制代码 |
public function render($request, Exception $e) if ($e instanceof ModelNotFoundException) { if($e instanceof \Symfony\Component\Debug\Exception\FatalErrorException return parent::render($request, $e); |
然后编辑自定义错误页面对应视图文件errors.default.blade.php。
验证码(Captcha)开源软件了,我们可以利用它结合Laravel 5生成验证码了,并且它在不断的更新算法比较难破解了,下面来看一篇Captcha为Laravel 5 应用生成验证码例子具体如下。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;
});
显示效果如下:
如果要返回原生图片,可以调用这个函数:
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')
以防止恶意攻击。
公众号菜单添加删除如果是单号可以直接登录后台操作了,但如果我们开了开发接口那么这个菜单的操作也必须通过接口来实现了,下面我们来看一篇关于php版微信实现公众号菜单添加删除操作例子。为了以最快方式调试新菜单功能,就用Debug方式去生成新菜单。请参数微信教程2的 wechat-json类。导入该文件后,我们用Debug方式生成一个新菜单:
if (isset($argc) && $argc >= 1 && $argv[0] == __FILE__) {
$client = new WechatJSON(array(
WechatJSON::APP_ID => 'wx78acfe8023sfsd4d51',
WechatJSON::APP_SECRET => '9ba3476db1ffsfsf512e0b22f630fa',
));
$res = $client->call('/menu/create',array (
'button' => array(
array (
'name' => '扫码',
'sub_button' => array(
array(
'name' => '扫码不提示',
'type' => 'scancode_push',
'key' => 'rselfmenu_0_0',
'sub_button' =>array ()
),
array(
'name' => '扫码带提示',
'type' => 'scancode_waitmsg',
'key' => 'rselfmenu_0_1',
'sub_button' =>array ()
),
),
),
array(
'name' => '发图',
'sub_button' => array(
array(
'name' => '系统拍照发图',
'type' => 'pic_sysphoto',
'key' => 'rselfmenu_1_0',
'sub_button' => array()
),
array(
'name' => '拍照或者相册发图',
'type' => 'pic_photo_or_album',
'key' => 'rselfmenu_1_1',
'sub_button' => array()
),
array(
'name' => '微信相册发图',
'type' => 'pic_weixin',
'key' => 'rselfmenu_1_2',
'sub_button' => array()
),
)
),
array(
'name' => '发送位置',
'type' => 'location_select',
'key' => 'rselfmenu_2_0'
)
)
)
, WechatJSON::JSON);
if (!$res) {
var_dump($client->_error);
}
var_export($res);
}
执行后,取消关注再关注,让新菜单生效!
效果图:
测试结果如下:
scancode_push事件:
array (
'tousername' => 'gh_e2a2b3bd35ff',
'fromusername' => 'on0eVjnYStxkCSaaCamYCpMZDmwA',
'createtime' => '1411629272',
'msgtype' => 'event',
'event' => 'scancode_push',
'eventkey' => '6',
'scancodeinfo' =>
SimpleXMLElement::__set_state(array(
'ScanType' => 'qrcode',
'ScanResult' => 'http://www.baidu.com/',
)),
array (
'tousername' => 'gh_e2a2b3bd35ff',
'fromusername' => 'on0eVjnYStxkCSaaCamYCpMZDmwA',
'createtime' => '1411629475',
'msgtype' => 'event',
'event' => 'scancode_push',
'eventkey' => '6',
'scancodeinfo' =>
SimpleXMLElement::__set_state(array(
'ScanType' => 'qrcode/EAN_13',
'ScanResult' => '6925082946487',
'EventKey' =>
SimpleXMLElement::__set_state(array(
)),
)),
)
上面是在菜单上点击《扫码不提示》后的log,有两种情况出现,第一种是如果你扫的是二维码是URL,它就会跳转到网页(注包括服务号生成的二维码),第二种是如果你扫的是条形码,就会跳转到搜索到该商品的详细信息,也就是大家常用的查价格。
scancode_waitmsg事件:
array (
'tousername' => 'gh_e2a2b3bd35ff',
'fromusername' => 'on0eVjnYStxkCSaaCamYCpMZDmwA',
'createtime' => '1411629302',
'msgtype' => 'event',
'event' => 'scancode_waitmsg',
'eventkey' => '6',
'scancodeinfo' =>
SimpleXMLElement::__set_state(array(
'ScanType' => 'qrcode',
'ScanResult' => 'http://www.111cn.net/',
)),
上面是点击菜单《扫码提示》后的log,推送XML跟scancode_push时差不多,但它不会跳转到网址或者商品信息。博主认为,这有利于后台取得scancodeinfo的信息来进一步处理!打个比方,自己自定义二维码信息,然后截取处理。类似于原服务号的参数二维码。
注意,以上两个菜单扫描事件和微信APP的扫一扫,是有区别的。具体你看事件就能看出来,scan事件!
pic_sysphoto事件、pic_photo_or_album事件和pic_weixin事件
array (
'tousername' => 'gh_e2a2b3bd35ff',
'fromusername' => 'on0eVjnYStxkCSaaCamYCpMZDmwA',
'createtime' => '1411627313',
'msgtype' => 'image',
'picurl' => 'http://mmbiz.qpic.cn/mmbiz/L8zbjcLqNFvEZ4dne4MGQQGR8xuHk4KhEk3icghU6a4bFTXnP2oeicr5VaBVJa10w4MYOOEia4udqicT5fdtAADHYg/0',
'msgid' => '6062893143676022221',
'mediaid' => 'i7hYOlSXbUCaC7Z9Elx4WpBqQq37-hR0El5w-frPfD5WCdBC7x46DPO6HL7zMfgd',
)
上面是点《发图》后,三个子菜单选择或者拍好,发图后的log信息,从图中我们看到事件是推过来了image,其他信息,相信大家都知道是什么,不解释。
location_select事件:
array (
'tousername' => 'gh_e2a2b3bd35ff',
'fromusername' => 'on0eVjnYStxkCSaaCamYCpMZDmwA',
'createtime' => '1411627424',
'msgtype' => 'event',
'event' => 'location_select',
'eventkey' => '6',
'sendlocationinfo' =>
SimpleXMLElement::__set_state(array(
'Location_X' => '23',
'Location_Y' => '113',
'Scale' => '15',
'Label' =>
SimpleXMLElement::__set_state(array(
)),
'Poiname' =>
SimpleXMLElement::__set_state(array(
)),
)),
)
上面是点击菜单《发送位置》后的log,我们可以看出事件是location_select,不像发图那样变成image,最有价值的信息是我们要取的sendlocationinfo里的
用户授权也是高级接口那部分内容,只是把它独立出来,这样让整个微信框架条理清晰些,但我们用它首先要在微信后台设置OA2的URL,这里的URL和教程一的有所不同。它是不带http://开头的域名。
首先登陆你的微信后台找到《开发者中心》:
点击修改填入我们的域名如下格式:
好了,最基本要点的OA2要求搞好,下面我们用个WechatAuth类生成一个OA2的URL格式,然后再从服务号里,以链接或者菜单又或者图文,跳到微信内置的WEB里就实现了我们取openid或者授权取用户消息!
例子代码生成snsapi_base或者snsapi_userinfo:
$auth = new WechatAuth(array(
WechatAuth::APP_ID => 'wx32259fc5sd5aac12B',
WechatAuth::APP_SECRET => '7ef73d3c56fcd0d984862ff217d2c648',
));
$url = $auth->getLoginUrl(array(
'redirect_uri' => 'http://www.demo.com/wp/ken',
'scope' => 'snsapi_userinfo' //snsapi_base
));
echo $url;
执行后,我们会得到如下OA2的URL:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx32259fc5d5aac13d&redirect_uri=http%3A%2F%2Fwww.demo.com%2Fwp%2Fken&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirects
然后我们在服务号里以刚才说到的菜单好,链接好 点击转到微信内置的浏览器里,如果你的scope方式为snsapi_userinfo时会弹出授权界面,base时不会弹默认执行后会返回openid:
好了,OA2无非就是让我们生成特定格式的URL,让我们点过去取openid或者用户信息(无论是否关注了你的服务号,只要确认授权),可以运用本站微信的实例有相关OA2的运用或者留言给我!
WechatAuth类:
<?php
/**
* 微信 OAuth2.0授权接口
* Class WechatAuth
*/
class WechatAuth {
const
JSON = 'json',
POST = 'post',
GET = 'get',
APP_ID = 'appid',
APP_SECRET = 'secret',
API_URL_PREFIX = 'https://api.weixin.qq.com/sns';
public
$_error_number = 0,
$_error,
$_APPID,
$_APPSECRET;
protected
$_cache = array(),
$_options,
$_openid,
$_access_token,
$_refresh_token,
$_timeout = 30;
static protected
$_instance;
/**
* 单例模式
* @param array $options
* @return WechatAuth
*/
static public function getInstance(array $options = array()) {
if (empty(self::$_instance)) {
self::$_instance = new WechatAuth($options);
}
return self::$_instance;
}
/**
* @param array $options {WechatAuth::APP_ID:"", WechatAuth::APP_SECRET:""}
*/
public function __construct(array $options = array()) {
$this->_options = array(
'timeout' => $this->_timeout,
);
$_options = array_merge($this->_options, $options);
$this->_APPID = $_options['appid'];
$this->_APPSECRET = $_options['secret'];
$this->_timeout = $_options['timeout'];
}
/**
* 提交请求
* @param $url
* @param array $params
* @param string $type Webchat_API::POST|Webchat_API::GET
* @return bool|mixed
*/
public function request($url, $params = array(), $type = self::POST) {
$ch = curl_init();
if ($type == self::GET) {
$url = $url.'?'.http_build_query($params);
}
curl_setopt_array($ch, array(
CURLOPT_URL => $url,
CURLOPT_TIMEOUT => $this->_timeout,
CURLOPT_USERAGENT => 'wordpress_wechat_client/0.1.'.rand(1,6),
CURLOPT_HEADER => 0,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSLVERSION => 3,
// CURLOPT_VERBOSE => 1,
));
if ($type == self::POST) {
curl_setopt($ch, CURLOPT_PORT, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
}
if ($type == self::JSON) {
//微信的破接口竟然不支持unicode转义符,违反JSON协定,只能把JSON字符中的unicode转回来
$data = preg_replace('/\\\\u([a-f0-9]{4})/e', "json_decode('\"$0\"', 1)", json_encode($params));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
}
$res = curl_exec($ch);
$this->_error_number = curl_errno($ch);
$this->_error = curl_error($ch);
curl_close($ch);
if ($this->_error_number) {
return false;
}
return $this->parseResult($res);
}
/**
* 处理返回结果
* @param $res
* @return bool|mixed
*/
protected function parseResult($res) {
$res = json_decode($res, true);
if (!empty($res)) {
if (isset($res['errcode']) && $res['errcode']) {
$this->_error_number = $res['errcode'];
$this->_error = $res['errmsg'];
return false;
}
return $res;
}
return false;
}
/**
* 获取当前URL
* @return string
*/
static public function getCurrentUrl() {
$pageURL = 'http';
if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") {
$pageURL .= "s";
}
$pageURL .= "://";
if (isset($_SERVER['SERVER_PORT']) && $_SERVER["SERVER_PORT"] != "80") {
$pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
} else {
if(isset($_SERVER["SERVER_NAME"]) && isset($_SERVER["REQUEST_URI"]))
$pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
}
return $pageURL;
}
/**
* 获取访问token
* @param bool $refresh 是否强制刷新
* @return bool|mixed
*/
public function getAuthAccessToken($refresh = false) {
$code = isset($_GET['code']) ? $_GET['code'] : '';
$state = isset($_GET['state']) ? $_GET['state'] : '';
$cache = $this->cache('auth_access_token');
if ($cache && ! $refresh) {
return array('access_token' => $cache, 'code' => $code, 'state' => $state);
}
$res = $this->request(self::API_URL_PREFIX.'/oauth2/access_token', array(
self::APP_ID => $this->_APPID,
self::APP_SECRET => $this->_APPSECRET,
'code' => $code,
'grant_type' => 'authorization_code',
), self::GET);
if ($res) {
$this->cache('auth_access_token', $res['access_token']);
$this->cache('auth_refresh_token', $res['refresh_token']);
$this->cache('auth_openid', $res['openid']);
} else {
if ($this->_error_number == 42001) {
return $this->refreshAccessToken();
}
}
return array('access_token' => $res['access_token'], 'code' => $code, 'state' => $state);
}
/**
* 刷新访问token
* @return mixed
*/
public function refreshAccessToken() {
$code = isset($_GET['code']) ? $_GET['code'] : '';
$state = isset($_GET['state']) ? $_GET['state'] : '';
$cache = $this->cache('auth_refresh_token');
if ($cache) {
$this->_refresh_token = $cache;
}
$res = $this->request(self::API_URL_PREFIX.'/oauth2/refresh_token', array(
self::APP_ID => $this->_APPID,
'refresh_token' => $this->_refresh_token,
'grant_type' => 'refresh_token',
), self::GET);
if ($res) {
$this->cache('auth_access_token', $res['access_token']);
$this->cache('auth_refresh_token', $res['refresh_token']);
$this->cache('auth_openid', $res['openid']);
}
return array('access_token' => $res['access_token'], 'code' => $code, 'state' => $state);
}
/**
* 获取用户信息
* @param bool $refresh 是否强制刷新
* @return bool|mixed
*/
public function getUserInfo($refresh = false) {
$this->_access_token = $this->getAuthAccessToken($refresh);
$cache = $this->cache('auth_openid');
if ($cache) {
$this->_openid = $cache;
}
$res = $this->request(self::API_URL_PREFIX.'/userinfo', array(
'access_token' => $this->_access_token,
'openid' => $this->_openid,
), self::GET);
if ($res) {
return $res;
}
return false;
}
/**
* 获取用户授权地址
* @param array $options
* @return string
*/
public function getLoginUrl($options = array()) {
$_options = array(
self::APP_ID => $this->_APPID,
'redirect_uri' => self::getCurrentUrl(),
'response_type' => 'code',
'scope' => 'snsapi_base', //snsapi_base | snsapi_userinfo
'state' => 'STATE',
);
$params = array_merge($_options, $options);
return 'https://open.weixin.qq.com/connect/oauth2/authorize?'.http_build_query($params).'#wechat_redirects';
}
/**
* 缓存接口Session实现
* @param $key 缓存索引key
* @param null $value 缓存值
* @return bool|mixed
*/
public function cache($key, $value = null) {
if (!session_id()) {
session_start();
}
if (empty($value)) {
if (isset($_SESSION[$key])) {
return $_SESSION[$key];
}
return false;
}
$_SESSION[$key] = $value;
return false;
}
}
相关文章
- 这篇文章主要给大家介绍了关于C#创建自定义控件及添加自定义属性和事件使用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2020-06-25
- 本文实例讲述了JS实现自定义简单网页软键盘效果。分享给大家供大家参考,具体如下:这是一款自定义的简单点的网页软键盘,没有使用任何控件,仅是为了练习JavaScript编写水平,安全性方面没有过多考虑,有顾虑的可以不用,目的是学...2015-11-08
- 为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
- 下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02
- 自定义一个jquery模态窗口插件,将它集成到现有平台框架中时,它只能在mainFrame窗口中显示,无法在顶层窗口显示. 解决这个问题的办法: 通过以下代码就可能实现在顶层窗口弹窗 复制代码 代码如下: $(window.top.documen...2014-05-31
- 这篇文章主要介绍了自定义feignClient的常见坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-20
- 今天小编就为大家分享一篇pytorch 自定义卷积核进行卷积操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-05-06
PHP YII框架开发小技巧之模型(models)中rules自定义验证规则
YII的models中的rules部分是一些表单的验证规则,对于表单验证十分有用,在相应的视图(views)里面添加了表单,在表单被提交之前程序都会自动先来这里面的规则里验证,只有通过对其有效的限制规则后才能被提交,可以很有效地保证...2015-11-24- 这篇文章主要介绍了jquery自定义插件开发之window的实现过程的相关资料,需要的朋友可以参考下...2016-05-09
- 这篇文章主要介绍了C#自定义事件监听实现方法,涉及C#事件监听的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 这篇文章主要介绍了使用BindingResult 自定义错误信息,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-23
- 这篇文章主要介绍了在Vue中获取自定义属性方法:data-id的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-09
- 这篇文章主要介绍了Vue 组件复用多次自定义参数操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27
- 今天小编就为大家分享一篇pytorch 自定义参数不更新方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-29
- 下面小编就为大家带来一篇thinkphp自定义权限管理之名称判断方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2017-04-03
- Nginx日志主要分为两种:访问日志和错误日志。访问日志主要记录客户端访问Nginx的每一个请求,格式可以自定义。下面这篇文章主要给大家介绍了Nginx自定义访问日志的配置方式,需要的朋友可以参考学习,下面来一起看看吧。...2017-07-06
- 404页面就是一个告诉搜索引擎这个页面不存在了,同时也提示用户可以选择其它的操作了,下面我来给没有apache操作权限朋友介绍php中自定义404页面的操作方法。 方法一...2016-11-25
- implicit 关键字用于声明隐式的用户定义类型转换运算符。如果转换过程可以确保不会造成数据丢失,则可使用该关键字在用户定义类型和其他类型之间进行隐式转换,这篇文章就给大家详细介绍implicit关键字做自定义类型隐式转换的方法,需要的朋友可以参考下...2020-06-25
浅谈Java自定义类加载器及JVM自带的类加载器之间的交互关系
这篇文章主要介绍了浅谈Java自定义类加载器及JVM自带的类加载器之间的交互关系,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-22- 这篇文章主要介绍了微信小程序 Toast自定义实例详解的相关资料,需要的朋友可以参考下...2017-01-23