Laravel 开发笔记
2017-03-03 15:33
113 查看
Laravel 4.2 鉴权使用加盐密码
刚开始接触laravel,发现laravel默认的鉴权模块密码并未加盐处理(密码由password_hash方法创建)。所以自己琢磨着对密码加盐。像下面这样校验密码(密码在最初创建时,也以md5(salt . password .salt)的形式存储)Auth::attempt(array('username'=>$user->username, 'password'=>$user->salt.Input::get('password').$user->salt))
但一直不成功,debug跟踪源码,可以看到最后,EloquentUserProvider的validateCredentials方法进一步调用BcryptHasher的check方法,,再进一步调用vendor/ircmaxell/password-compat/lib/password.php:230 password_verify方法,而不是我起初所想的直接$user->password == md5('input_password')。因此我在这里直接改写了源码,以此来实现密码加盐
![](https://images2015.cnblogs.com/blog/635249/201703/635249-20170303123250813-2136393792.png)
Laravel 4.2 响应存在多余的空行
在任意响应中多四个空行,这个问题在4.2版本中遇到,并且在配置了auth过滤器的请求中才有![](https://images2015.cnblogs.com/blog/635249/201703/635249-20170303123801204-899781046.png)
这个问题在下载请求时会有问题,比如压缩文件。在下载zip文件时,如果响应前步多几个空行,会造成文件起始多几个字节,造成这样的错误
warning [zip]: 8 extra bytes at beginning or within zipfile 。 因为代码文件里是windows 换行符 CRLF,所以四个空行是八个字符,所以响应头部多了八个字节
![](https://images2015.cnblogs.com/blog/635249/201703/635249-20170303123700501-1820976787.png)
或者提示 该文件已损坏或者需要另一个压缩分卷
Laravel 5.3 清除客户端cookie
有时需要服务端来清除cookie,以保证所有httponly属性的cookie也能被清除。laravel已经提供API来生成清除cookie的http头![](https://images2015.cnblogs.com/blog/635249/201703/635249-20170303124300282-2041968117.png)
![](https://images2015.cnblogs.com/blog/635249/201703/635249-20170303124307438-408461578.png)
Laravel 5.3 实现controller路由
laravel 5.3中移出了controller路由,只保留了resources路由,这对开发规范的项目而言是好事,而对开发不规范的项目简直是灾难,开发不得不用get或者post路由为每一个控制器的方法注册路由,这会造成路由文件routes.php(routes/web.php)文件巨大不好维护。个人比较喜欢按约定来,所以写了个函数简单实现controller路由(约定namespace/controller/method)格式,如Home/XxYyController@getMmGg 将映射到 url : home/xx-yy/mm-gg,并且是get请求/** * 驼峰字符串转蛇形字符串 * @param $str * @param string $delimiter * @return string */ function humpToSnake($str,$delimiter = '_'){ if ( ! ctype_lower($str)) { $replace = '$1'.$delimiter.'$2'; $str = strtolower(preg_replace('/([A-Za-z])([A-Z])/', $replace, $str)); } return $str; } /** * 基于controller约定路由 * 例如: $namespace = 'H5' * GET : XxYyController@getMmGg -> url : h5/xx-yy/mm-gg * POST : XxYyController@postMmGg -> url : h5/xx-yy/mm-gg * @param string $controller 控制器类名 * @param bool $namespace 相对于App\Http\Controllers的命名空间 */ function routeController($controller,$namespace = false){ if (preg_match('/([\w]+)Controller$/', $controller, $matches)) { $className = humpToSnake($matches[1],'-'); $methods = get_class_methods('App\Http\Controllers\\'.($namespace ? $namespace.'\\' : '').$controller); foreach($methods as $method){ if(strpos($method,'get') === 0){ // 注册get路由 $methodName = humpToSnake(lcfirst(substr($method,3)),'-'); Route::get($className.'/'.$methodName,$controller.'@'.$method); } else if(strpos($method,'post') === 0){ // 注册post路由 $methodName = humpToSnake(lcfirst(substr($method,4)),'-'); Route::post($className.'/'.$methodName,$controller.'@'.$method); } } } }
在php项目中独立使用Eloquent ORM框架
laravel使用的eloquent orm框架极其强大,大部分数据库层面的操作都能够在不写任何sql的情况下实现查询。所以在写其余项目时,比如爬虫,也想将此orm集成进来eloquent 是一个独立的项目 https://github.com/illuminate/database,所以完全可以单独拿出来用
通过composer在项目中安装依赖
composer require illuminate/database:~4.2
将eloquent初始化的代码独立于一个php文件(start.php)中
<?php /** * Created by PhpStorm. * User: lvyahui * Date: 2016/3/17 * Time: 17:23 */ require_once __DIR__ . '/vendor/autoload.php'; require_once 'config.php'; $localDBConf = config('db.local'); $database = array( 'driver' => 'mysql', 'host' => $localDBConf['host'], 'port' => $localDBConf['port'], 'database' => $localDBConf['name'], 'username' => $localDBConf['user'], 'password' => $localDBConf['pass'], 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', ); //use Illuminate\Container\Container; use Illuminate\Database\Capsule\Manager as Capsule; $capsule = new Capsule(); /*创建连接*/ $capsule->addConnection($database); /*设置全局访问*/ $capsule->setAsGlobal(); /*启动Eloquent*/ $capsule->bootEloquent();
定义数据库模型 BaseModel.php
<?php use Illuminate\Database\Eloquent\Model as Eloquent; /** * Created by PhpStorm. * User: samlv * Date: 2016/3/17 * Time: 17:30 */ class BaseModel extends Eloquent { protected $guarded = array('id'); public $timestamps = false; }
ApkClass.php
<?php require_once ('BaseModel.php'); /** * Created by PhpStorm. * User: lvyahui * Date: 2016/3/31 * Time: 16:35 */ class ApkClass extends BaseModel { protected $table = 'apk_class'; }
在需要进行数据库操作中引入初始化文件和模型文件即可以使用
<?php /** * Created by PhpStorm. * User: lvyahui * Date: 2016/3/31 * Time: 17:00 * 扫描tmp/zip目录,解压左右的zip包,让后进行处理。 */ require_once ('start.php'); require_once ('models/ApkClass.php'); foreach($usedApkClasss as $map_id=>$num){ ApkClass::where('map_id',$map_id)->update(array('num' => $num)); }
Laravel 基于约定进行子视图填充
laravel 另一个强大之处是其模板引擎,开发中常用的有两种,视图继承和子视图填充。这里以子视图填充为例,按约定的方式简化代码的编写基础控制器
<?php use Illuminate\Support\Facades\View; use Illuminate\Support\Facades\Redirect; use Illuminate\Support\Facades\Input; class BaseController extends Controller { protected $layout = 'layouts.site'; protected $stdName = null; protected $routeParams = false; /** * Setup the layout used by the controller. * * @return void */ protected function setupLayout() { if ( ! is_null($this->layout)) { $this->layout = View::make($this->layout); } } public function __construct() { } /** * 获取控制器名称 * 例如: * 类:admin/DataSourceController * 将返回 * dataSource * @return null|string */ public function getStdName() { if(!$this->stdName){ $className = get_class($this); if (preg_match('/([\w]+)Controller$/', $className, $matches)) { // $this->stdName = camel_case($matches[1]); $this->stdName = lcfirst($matches[1]); } else { $this->stdName = $className; } } return $this->stdName; } public function makeView($data = array(),$view = null){ if(!$view){ $routeParams = $this->getRouteParams(); $controllerName = $routeParams['c']; $methodName = $routeParams['m']; if(preg_match('/^get(.*)$/',$methodName,$matches)){ $methodName = StringUtils::humpToSnake($matches[1]); } $view = $controllerName.'.'.$methodName; } if(!is_array($data)){ $data = array(); } if(Request::ajax()){ return View::make($view,$data); }else{ $this->layout->nest('content',$view,$data); return false; } } /** * * @return array|bool */ public function getRouteParams(){ if(!$this->routeParams){ list($class,$method) = explode('@',Route::current()->getActionName()); $class = str_replace("\\",".",substr($class,0,strrpos($class,'Controller'))); // $names = explode(".",$class); // foreach ($names as & $name) { // $name = snake_case($name); // } $class = StringUtils::humpToSnake($class); // $class = implode('.',$names); $this->routeParams = array( 'c' => $class, 'm' => $method ); } return $this->routeParams; } public function getRouteParam($key){ $routePatams = $this->getRouteParams(); return $routePatams[$key]; } }
控制器方法中只需要return makeView()方法即可,makeView方法会确定视图文件位置。
<?php class UserController extends BaseController { public function getList(){ return $this->makeView(array('users'=>array())); } }
主视图(site.blade.php)写法
<!DOCTYPE html> <html lang="zh-CN"> <head> @include('layouts.head') <!-- 页面级别css --> @yield('page.level.css','') </head> <body> @include('layouts.header') <div class="container-fluid"> {{$content}} </div> @include('layouts.footer') <!-- 页面级别js文件 --> @yield('page.level.js','') <!-- 页面级别js代码片段 --> @yield('page.level.script','') </body> </html>
上面几份代码实现这样的约定是:UserController@getList方法渲染views/user/list.blade.php页面,并将其填充到view/layouts/site.blade.php视图中,也就是我认为整个站点主视图(布局,layouts/site.blade.php)基本一致,所有方法产生的内容直接填充主视图即可,那以后开发新的页面或者接口,只需要按改约定开发即可
相关文章推荐
- Laravel 开发笔记
- Ag和Laravel开发仿知乎笔记-后端
- (转载)Laravel学习笔记(一)安装配置开发环境
- Laravel学习笔记之基于PHPStorm编辑器的Laravel开发
- Laravel 开发笔记
- laravel 开发笔记之laracasts/flash
- laravel 开发笔记
- Laravel 开发笔记
- Ag和Laravel开发仿知乎笔记-前端
- 开发asp.net自定义控件(asp.net学习笔记二)
- 开发asp.net自定义控件(asp.net学习笔记三)
- 没头没尾--项目开发笔记:如何编写最外层用例?!
- SharePoint 应用的开发学习笔记(-)
- “面向状态软件开发”学习笔记一(整理LeWolf的文章)
- 没头没尾--项目开发笔记:异常处理与日志记录代码自动生成(工具能生成多少代码!?续一)
- SharePoint 应用的开发学习笔记(二)
- 没头没尾--项目开发笔记:最后的笔记
- 开发asp.net自定义控件(asp.net学习笔记四)
- 使用VC和MATCOM结合开发应用程序心得笔记
- 没头没尾--项目开发笔记:先开发UI层还是先开发BusinessRules层!!??