laravel源码分析e(laravel源码分析)
本文目录一览:
- 1、如何高效地学习 Laravel 框架
- 2、为什么 Laravel 会成为最成功最流行的 PHP 框架
- 3、laravel 怎么检测队列是否执行
- 4、为什么 Laravel 会成为最成功的 PHP 框架
- 5、大神们,看laravel框架的源码吗
- 6、Laravel源码里面为什么要用:class语法
如何高效地学习 Laravel 框架
推荐学习路径
1. 框架的使用知识学习
基于以上的思想,我创建了 《Laravel 实战课程》,计划中有三本(也有可能更多),分别是:
第一本 —— 《Laravel 入门教程 - 从零到部署上线》
第二本 —— 《Laravel 进阶课程 - 从零开始构建论坛系统》
第三本 —— 《Laravel 高级课程 - 构架 API 服务器》
第一本书教授如何使用 Laravel 一步一步构建一个类似新浪微博的应用,书中很多技术话题会被一带而过,这是有意而为之的,我们希望让读者保持对编码线索的专注,不被篇幅悠长的名词解释分心。通过阅读本教程,你将学到如 HTML、CSS、JavaScript、PHP 和 Laravel 等 Web 开发相关的基础知识。不仅如此,本书还会对这些基础知识点进行延伸扩展,为你讲解一些在 Web 开发中更为专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流、Bootstrap 框架基本使用等。这些知识将为你未来的编程开发奠定下坚实的基础。
第二本以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。编码规范遵循 Laravel 项目开发规范 ,应用程序架构思路贴近 Laravel 框架的设计哲学。在论坛系统的构建中,我们将学到多角色用户权限系统、管理员后台、注册验证码、图片上传、图片裁剪,XSS 防御、自定义命令行、自定义中间件、任务调度、队列系统的使用、应用缓存、Redis、模型事件监控、表单验证、消息通知、邮件通知、模型修改器等知识。在本课程的学习中,你不仅能学到使用 Laravel 开发一个论坛项目,还能学到安全优先、高扩展性的大型项目架构经验。
第三本将以构建 API 服务器为目标,来展开。目前本课程正在紧张撰写中,敬请期待。
2. 框架的底层实现学习
学完了以上三本书,你将拥有一定的项目开发经验,对框架的功能使用也会有一个比较全面的系统性理解。这时候,会是学习『底层实现』的好时机。
底层实现的知识学习,可以从文档开始,打开 Laravel 的文档中心 —— d.laravel-china.org ,找到最新版本的 Laravel 文档,然后仔细阅读 2、3 遍。因为有了上面的项目经验,此时的文档阅读啃起来会轻松多了。
阅读文档后,可以尝试看下 Laravel 底层的源码,看看这些框架的功能都是怎么实现的。
学习过程中可以适当做笔记,例如:
zhangbao 同学的 Laravel 文档阅读笔记
leoyang 同学的 Laravel 源码分析笔记
错误的学习方法
一上来就开始啃文档 d.laravel-china.org 。
如果你是新手,有太多的新概念你需要学习,你会发现学习起来非常艰难,甚至怀疑文档是不是写的太烂了(社区里经常出现这种抱怨)。
事实上,不是文档写的太烂,而是你把文档用错了。文档的『目的』是快速查阅,一份优秀文档的标准是语言简练,释义,这个 Laravel 的文档做的很棒。但是,文档并不适合做入门学习使用,上面我们已经讲过,原因是信息量太大。
寻找网络上零散的课程进行学习。
如果你想学习单个概念,这些零散的小课程会很方便。但是,如果是想以阅读大量课程来达到系统性学习的目的,你将会很失望。很多时候你会感觉 —— 你好像学了很多,学了很久,以为自己学会了,但是心里还是没底气。
你需要的是通过项目,完整的项目,将所有的知识串起来去记忆。你的作品,清清楚楚摆在面前,看着你一步步构建出来的一套系统,自信心也会有所增加。
一开始就学习高级话题,如 服务容器、服务提供器、Facades、Contracts、Repository 等
很多时候你会发现这些话题晦涩难懂,很难学习。并且即使你毅力比较好,死记硬背,很快也会忘记,学习效率非常低下。然后最重要的,学会这些概念,并无法使你掌握构建一个完整项目的能力。
为什么 Laravel 会成为最成功最流行的 PHP 框架
Laravel是一个有着美好前景的年轻框架,它的社区充满着活力,同时提供了完整而清晰的文档,而且为快速、安全地开发现代应用提供了必要的功能。
2011年,Taylor Otwell首次将Laravel带给这个世界,彼时,Laravel就是一个全新且现代的框架。Laravel基于MVC架构,可以满足诸如事件处理、用户身份验证等各种需求,同时通过包管理实现模块化和可扩展的代码,并且对数据库管理有着健壮的支持。
不管是专家还是新手,一旦接触到Laravel,都会有相见恨晚之感——这正是你在为PHP项目寻找的框架。本文我们将讨论为什么Laravel会成为最成功最流行的PHP框架。
模块化可扩展性
Laravel是模块化和可扩展的,你可以在包含超过5500个程序包的Packalyst中找到你想要添加的任何代码。
微服务API
Lumen是一个由Laravel衍生的专注于性能的微框架。使用Lumen提供的高性能API你可以更加简单快速地开发微型项目。Lumen使用最小的配置集成了Laravel的所有重要特性,你可以通过将代码复制到Laravel项目来实现框架的完整迁移。
?php
$app-get('/', function() {
return view('lumen');
});
$app-post('framework/{id}', function($framework) {
$this-dispatch(new Energy($framework));
});
HTTP路由
Laravel拥有类似于Ruby on Rails的快速高效的路由系统。它可以让用户通过在浏览器上输入路径的方式让应用程序的各部分相关联。
Route::get('/', function () {
return 'Hello World';
});
HTTP中间件
Route::get('/', function () {
return 'Hello World';
});
Laravel可以通过中间件对应用进行保护——中间件会处理分析和过滤到达服务器的HTTP请求。你可以使用中间件来验证注册用户、避免跨站脚本攻击(XSS)以及其它安全问题。
?php
namespace App\Http\Middleware;
use Closure;
class OldMiddleware {
public function handle($request, Closure $next) {
if ($request-input('age') = 200) {
return redirect('home');
}
return $next($request);
}
}
缓存
Laravel提供了健壮的缓存系统,使用缓存可以让应用加载地更加快速,从而带来更好的用户体验。
Cache::extend('mongo', function($app) {
return Cache::repository(new MongoStore);
});
身份验证
安全是至关重要的。Laravel自带对本地用户的身份验证,并可以使用“remember” 选项来记住用户。此外你还可以引入一些额外参数,例如是否是活跃用户。
if (Auth::attempt(['email' = $email, 'password' = $password, 'active' = 1 ], $remember)) {
// The user is being remembered...
}
集成Stripe
Laravel Cashier可以满足你开发支付系统过程中所需要的任何需求。除此之外,它还同步并集成了用户身份验证系统。所以,你不再需要担心如何将计费系统集成到开发中了。
$user = User::find(1);
$user-subscription('monthly')-create($creditCardToken);
任务自动化
Elixir是一个让我们可以使用Gulp定义任务的Laravel API,我们可以使用Elixir定义预处理器来压缩CSS 和JavaScript。
elixir(function(mix) {
mix.browserify('main.js');
});
加密
一个安全的应用应该做到可以对数据进行加密。在Laravel中,可以使用OpenSSL和AES-256-CBC加密算法来满足你所有的加密需求。此外,所有的加密值都通过认证码进行签名以避免加密信息被篡改。
use Illuminate\Contracts\Encryption\DecryptException;
try {
$decrypted = Crypt::decrypt($encryptedValue);
} catch (DecryptException $e) {
//
}
事件处理
Laravel应用中对事件的定义、记录和监听都非常便捷。服务提供者EventServiceProvider中的listen属性包含了应用中的所有事件列表。
protected $listen = [
'App\Events\PodcastWasPurchased' = [
'App\Listeners\EmailPurchaseConfirmation',
],
];
分页
在Laravel中分页非常简单,因为它能够根据用户在浏览器中的当前页生成一系列分页链接。
?php
namespace App\Http\Controllers;
use DB;
use App\Http\Controllers\Controller;
class UserController extends Controller {
public function index() {
$users = DB::table('users')-paginate(15);
return view('user.index', ['users' = $users]);
}
}
对象关系映射(ORM)
Laravel包含了一个数据库处理层,其中的对象关系映射被称作Eloquent。另外这个对象关系映射也适用于PostgreSQL。
$users = User::where('votes', '', 100)-take(10)-get();
foreach ($users as $user) {
var_dump($user-name);
}
单元测试
单元测试的开发是一个耗费大量时间的任务,但是它却保证了我们的应用能够正常工作,不出问题。Laravel使用PHPUnit进行单元测试。
?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase {
public function testBasicExample() {
$this-visit('/')-see('Laravel 5')-dontSee('Rails');
}
}
待办事项清单(Queue)
Laravel提供了在后台使用待办事项清单(to do list)处理复杂、漫长流程的选择,好吧,其实就是队列,队列可以让我们异步处理某些流程而不需要用户在加载页面时长时间的等待。
Queue::push ( new SendEmail ( $ message ));
laravel 怎么检测队列是否执行
队列Service
laravel把队列相关的服务全封装在一个Service里面,通过Queue Service Provider 注册到IOC中.在Queue Serivce里提供了多种服务,关于它做了什么请看以下代码中的注释(代码有点多,就不全部贴出来了)
public function register()
{
// 注册Manager, 而Manager为队列服务的统一入口
$this-registerManager();
// 注册队列的各种命令
$this-registerWorker();
$this-registerListener();
// 注册任务执行失败后的记录
$this-registerFailedJobServices();
// 未知
$this-registerQueueClosure();
}
讲配置文件
在Queue Service注入到IOC后,我们就可以使用队列了。
一个队列服务最基本的就是把任务写入队列,再将其拿出来执行, 很简单.所以队列服务最基本的要素有四点:任务,进队列,出队列,执行.在这里,我们就跟着这四个要素的步伐,看看它们在laravel中是如何实现的.这里,先以官方的示例来分析,有了一个具体概念之后再举一反三,学会它的本质。
任务
队列服务就是围绕着任务进行的.在手册上,通过它的实例SendReminderEmail,我们可以很清楚地知道,laravel可以对一个任务做很多事,比如:可设置重新执行的次数,说明该任务(若失败)可以被执多次(针对的是单个Job);可设置是否可以延迟执行;对该Job设置处理的队列名称,等等.这些功能都是\Illuminate\Bus\Queueable提供的,当然,实例中还有一个\Illuminate\Queue\InteractsWithQueue,而它则是针对Job所用(稍后再说).一个任务建立完成后,就需要使其进入队列了。当然了,除了以上几个特点,还有任务的执行逻辑等等,要全面地了解任务,就需要清楚它的数据结构,其在队列中的数据结构会在进入队列中讲到.
任务进队列
示例中,在定义了任务之后,就将其用Controller中的方法使其进入了队列,那么这一点是如何实现的?
代码在:\Illuminate\Foundation\Bus\DispatchesJobs
protected function dispatch($job)
{
return app(Dispatcher::class)-dispatch($job);
}
/**
* Dispatch a command to its appropriate handler in the current process.
*
* @param mixed $job
* @return mixed
*/
public function dispatchNow($job)
{
return app(Dispatcher::class)-dispatchNow($job);
}
这段代码的意图得了解app(Dispather::class), 这个则在\Illuminate\Bus\BusServiceProvider中表现的很明确了(为什么是这里就不分析了),app(Dispather::class)就是\Illuminate\Bus\Dispatcher.现在,上面代码中的dispatch与 dispatchNow方法就会逐渐清晰起来.简言之,该Dispatcher类做了两件事,执行该任务或把该任务放入队列,也就是将队列任务分为了两种执行方式,立即执行或以消息队列执行,与队列相关的代码如下:
/**
* 把任务分发到队列中
* @param string $command 任务类
*/
public function dispatchToQueue($command)
{
$connection = isset($command-connection) ? $command-connection : null;
// laravel里内置了多种队列服务,这里则解析出来
$queue = call_user_func($this-queueResolver, $connection);
// 队列服务解析不成功则抛出异常
if (! $queue instanceof Queue) {
throw new RuntimeException('Queue resolver did not return a Queue implementation.');
}
// 在任务类中可自定义queue方法进入队列
if (method_exists($command, 'queue')) {
return $command-queue($queue, $command);
} else {
// 系统提供的一种进入队列方式
return $this-pushCommandToQueue($queue, $command);
}
}
/**
* 根据不同的任务属性选择不同的进入队列方式
* 这里所提到的方式在手册中有提到
* @param Queue $queue 队列服务
* @param $command 任务类
*/
protected function pushCommandToQueue($queue, $command)
{
// 该推任务设置了延迟,且设置队列名称
if (isset($command-queue, $command-delay)) {
return $queue-laterOn($command-queue, $command-delay, $command);
}
//设置队列名称
if (isset($command-queue)) {
return $queue-pushOn($command-queue, $command);
}
//设置延迟
if (isset($command-delay)) {
return $queue-later($command-delay, $command);
}
// default
return $queue-push($command);
}
到现在为止,Controller已经展示了一种进入队列的方法,很明显它是经过封装提供的接口,虽然很好用,但有些操作是我们所不必须的,比如:是否立即执行,进入队列就需设置不同的任务参数等等,需要更好的为我们所用,就再深入一点,找出它进入队列的关键点(与Redis交互的地方).上面已经提到call_user_func($this-queueResolver, $connection);会得到一个队列服务,那么$this-queueResolver是什么?在\Illuminate\Bus\BusServiceProvider:23就可以看到:
// 理解这个回调,则需要了解Illuminate\Contracts\Queue\Factory
// 在vendor/laravel/framework/src/Illuminate/Foundation/Application.php:1051 可以看到它与Illuminate\Queue\QueueManager的关系了
$this-app-singleton('Illuminate\Bus\Dispatcher', function ($app) {
return new Dispatcher($app, function ($connection = null) use ($app) {
return $app['Illuminate\Contracts\Queue\Factory']-connection($connection);
});
});
QueueManager
在laravel中,Service对外的统一接口都是其Manager,其中与所需服务交互的基本上是通过__call 方法提供,这种方式有两个优点,一,提供统一的接口,二,分层明确(将实际的处理由__call转发,与配置相关的则由manager自己解决).
现在为了使任务进入队列的过程更清晰,一步一步找到了QueueManager,这个类设置了很多事件接口,和其他连接相关方法.其中connection方法就展示了一个队列服务是如何解析出来的了.
其实这段解析的代码唯一的难点中于:
protected function getConnector($driver)
{
if (isset($this-connectors[$driver])) {
return call_user_func($this-connectors[$driver]);
}
throw new InvalidArgumentException("No connector for [$driver]");
}
为什么这么一段简单的代码就能解析队列服务?查看QueueServiceProvider就一目了然了.其中就注册了很多队列服务.redis的队列服务处理则是\Illuminate\Queue\RedisQueue.
QueueManager的功能现在很清晰了.1,解析队列服务 2,转发(__call)处理到相应的队列服务中 3,提供队列相关接口 .既然QueueManager有这么多队列相关的功能,那么我们完全可以把它作为一个队列处理的入口(直接获取队列服务再进行操作是并不是明智的选择),巧的是laravel也是这么做的.所以现在有两种方式进入队列,1,使用\Illuminate\Foundation\Bus\DispatchesJobs间接与队列服务通信 2,使用QueueManager间接与队列服务通信.当然这些方法都是在\Illuminate\Queue\RedisQueue(队列服务的接口)上扩展的.所以掌握该类,就能明白队列的各种行为了.
RedisQueue
队列服务在lavavel中提供了多种,这里只对以Redis队列服务进行分析学习.所以有关队列的处理都集中在\Illuminate\Queue\RedisQueue.上面也说到了,有两种方式进入队列, 分别使用,看它们产生的任务数据结构有什么区别?(数据结构便于分析,在后面会提到)
在Controller使用 $this-dispatch((new SendReminderEmail()));即以任务类进入
{
"job": "Illuminate\\Queue\\CallQueuedHandler@call",
"data": {
"command": "O:26:\"App\\Jobs\\SendReminderEmail\":4:{s:5:\"queue\";s:5:\"email\";s:10:\"connection\";N;s:5:\"delay \";N;s:6:\"\u0000*\u0000job\";N;}"
},
"id": "7u00jImd8CAns0fQO8jedqkQmnbQsfsr",
"attempts": 1
}
直接使用 Queue::push(SendReminderEmail::class , ['email'='123456789@qq.com'],'email');
{
"job": "App\\Jobs\\SendReminderEmail",
"data": {
"email": "123456789@qq.com"
},
"id": "I0OeBIQjJjisQrZ7STX3zexrBLF7Uilx",
"attempts": 1
}
上面讲到,构成消息队列需要两个进程,所以上面的进入队列是一个进程,现在的出队列及执行任务则在另一个进程中执行。lavarel提供了两个命令来启动该进程,quque:work ,queue:litsen 当然,再理解了如何完成这些操作后完全可以自己写一个命令,现在看看它是如何出队列和如何执行任务?
任务出队列
在手册中,对于一个任务可以指定多种属性,比如,延迟,失败次数,队列名称等等,当然,所有可执行操作或功能都得依赖数据结构,数据结构的制定也是为了实现相应的行为.所以,RedisQueue的代码对应上面的数据结构来理解就比较容易了。
RedisQueue是所有队列服务(Redis)的基础接口,所以任务出队列的操作也能在这找到。假设现在已经对RedisQueue的代码已经有点熟悉了,不难发现,有一个稍复杂的pop方法(出队列)。那么,问题出现了,出队列是如何实现的?解决了这个问题,任务出队列就可算是完成了.
队列应有的功能
查看php artisan queue:work --help命令的使用方法,整理有关队列所需的功能或服务:
指定队列名称
任务的执行逻辑
任务执行延迟
任务中失败的最大次数
当然还有其他关于该命令的功能,比如:是否以守护进程执行,是否强制执行,限制进程执行的memory,无任务时的等待时间.这些与命令相关的因不同的命令而异,与队列任务无关.这样,在理清队列任务需要的功能后,我们就可以分析它的数据结构,理解代码了.
队列数据结构
数据结构都是依据行为而建立.所以在查看pop方法时,可考虑以上几个点.上面的数据结构中,已经可以看到队列的执行逻辑,所需参数,失败次数,这些一目了然,就不啰嗦了.在整个pop方法中,有这么几个队列,queue:delayed,queue:reserved,queue.本来取出一个任务用lpop就可完成,为什么要多用两个集合(注意,是有序集合不是队列)来完成pop操作呢?因为要实现任务延迟和失败处理.
其执行过程如图:
过程解析:
(1). 取任务,因为要实现延迟的功能,所以在有序集合里的score是过期时间,过期时间的含义则是在此时间之前不执行,也就达到了延迟执行的效果.延迟的含义在这里指的并不是在多少秒后执行,而是在多少秒内不执行.对于过期的任务,就将其rpush到队列中,直到lpop操作将其拿走.
(1).为什么在存在queue:reserved集合并且把lpop的任务zadd进支?因为只要lpop了job就可以将其记录下来,若此时任务还未开始执行进程就非正常终止了,该任务就不会丢失,再次执行时,依据上面的步骤就可以将其取出,防止意外使job丢失.
(2).队列的执行都是依据json中的类来完成,这部分较简单,略.
(3).当任务执行成功时,要手动删除queue:reserved中的任务;当任务执行失败,删除queue:reserved中的任务,再将其记录下来,记录方式是zadd queue:delayed, 并且将该任务的执行次数加一,这个过程RedisQueue已经封装(RedisQueue::release)好了.
这一系列的过程就完成了让队列任务延迟的功能.所以这么复杂的操作都是为了实现延迟的功能,当然,有更好的点子可以考虑自己实现.
执行任务
到此,任务的执行在json数据结构中表现的很明确,整个处理过程也很清晰了.需要注意的是当任务执行成功后要删除任务.对于如何执行出队列,以及如何执行队列任务,可以详细看看queue:work命令(\Illuminate\Queue\Console\WorkCommand::fire), 它是最好的示例;
队列处理命令的自定义
在使用queue:work之后,会发现它并不有处理所有的情况.所以在本文中一直提到过,自写一个处理命令是可行的.当面临queue:work所不能解决的问题时,可以好好考虑下自己编写.在实际开发中,任务的种类繁多,对于不同的任务应该有不同的处理方案.所以,有以下几个问题是经常遇到的:
比如:
调用服务发生错误且由服务提供方造成,需另作记录,而这样的错误不算作job的执行错误
营销短信只能在9:00到20:00之间发送, 所以在该时间段内没有执行的必要
与数据库交互时,数据库连接是有时间限制的,而以守护进程的方式执行则无时间限制,这样就会报错
所以,面临laravel所提供命令的局限性,有自定义处理命令的能力是很有必要的.
为什么 Laravel 会成为最成功的 PHP 框架
模块化和可扩展性
Laravel注重代码的模块化和可扩展性。你可以在包含超过5500个程序包的Packalyst目录中找到你想要添加的任何文件。Laravel的目标是让你能够找到任何想要的文件。
微服务和程序接口
Lumen 是一个由laravel衍生的专注于精简的微框架。它高性能的程序接口可让你更加简单快速的开发微型项目。Lumen使用最小的配置集成了所有laravel的重要特性,你可以通过将代码复制到laravel项目的方式将完整的框架迁移过来。
?php $app-get('/', function() { return view('lumen'); }); $app-post('framework/{id}', function($framework) { $this-dispatch(new Energy($framework)); }); HTTP路径
Laravel拥有类似于Ruby on Rails的,快速、高效的路由系统。它可以让用户通过在浏览器上输入路径的方式让应用程序的各部分相关联。
Route::get('/', function () { return 'Hello World'; }); HTTP中间件
应用程序可受到中间件的保护——中间件会处理分析和过滤服务器上的HTTP请求。你可以安装中间件,用于验证注册用户,并避免如跨站脚本(XSS)或其它的安全状况的问题。
?php namespace App\Http\Middleware; use Closure; class OldMiddleware { public function handle($request, Closure $next) { if ($request-input('age') = 200) { return redirect('home'); } return $next($request); } } 缓存
你的应用程序可得到一个健壮的缓存系统,通过对其进行调整,可以让应用程序的加载更加快速,这可以给你的用户提供最好的使用体验。
Cache::extend('mongo', function($app) { return Cache::repository(new MongoStore); }); 身份验证
安全是至关重要的。Laravel自带对本地用户的身份验证,并可以使用“remember” 选项来记住用户。它还可以让你例如一些额外参数,例如显示是否为活跃的用户。
if (Auth::attempt(['email' = $email, 'password' = $password, 'active' = 1 ], $remember)) { // The user is being remembered... } 种类集成
Laravel Cashier可以满足你要开发支付系统所需要的一切需求。除此之外,它还同步并集成了用户身份验证系统。所以,你不再需要担心如何将计费系统集成到开发当中了。
$user = User::find(1); $user-subion('monthly')-create($creditCardToken); 任务自动化
Elixir是一个可让我们使用 Gulp 定义任务的Laravel程序接口,我们可以使用Elixir定义可精简CSS 和Java的预处理器。
elixir(function(mix) { mix.browserify('main.js'); }); 加密
一个安全的应用程序应该做到可把数据进行加密。使用Laravel,可以启用OpenSSL安全加密算法AES-256-CBC来满足你所有的需求。另外,所有的加密值都是由检测加密信息是否被改变的验证码所签署的。
use Illuminate\Contracts\Encryption\DecryptException; try { $decrypted = Crypt::decrypt($encryptedValue); } catch (DecryptException $e) { // } 事件处理
应用程序中事件的定义、记录和聆听都非常迅速。 EventServiceProvider事件中的listen包含记录在你应用程序上所有事件的列表。
protected $listen = [ 'App\Events\PodcastWasPurchased' = [ 'App\Listeners\EmailPurchaseConfirmation', ], ]; 分页
在Laravel中分页是非常容易的因为它能够根据用户的浏览器当前页面生成一系列链接。
?php namespace App\Http\Controllers; use DB; use App\Http\Controllers\Controller; class UserController extends Controller { public function index() { $users = DB::table('users')-paginate(15); return view('user.index', ['users' = $users]); } } 对象关系图(ORM)
Laravel包含一个处理数据库的层,它的对象关系图被称为 Eloquent 。另外这个对象关系图也适用于 PostgreSQL 。
$users = User::where('votes', '', 100)-take(10)-get(); foreach ($users as $user) { var_dump($user-name); } 单元测试
单元测试的开发是一个耗费大量时间的任务,但是它却是保证我们的应用程序保持正常工作的关键。Laravel中可使用 PHPUnit执行单元测试。
php use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Foundation\Testing\DatabaseTransactions; class ExampleTest extends TestCase { public function testBasicExample() { $this-visit('/') -see('Laravel 5') -dontSee('Rails'); } } 待办事项清单
Laravel提供在后台使用待办事项清单(to do list)处理复杂、漫长流程的选择。它可以让我们异步处理某些流程而不需要用户的持续导航。
大神们,看laravel框架的源码吗
安装composer。安装之前要确保目录:wamp\bin\php\php5.4.3下的php.ini文件中的php_openssl.dll扩展库是开启的,否则,composer在安装过程中会出现错误提示。(注意:wamp安装文件下会有两个php.ini文件,我们要修改的是php目录下的php.ini文件)。
下载最新Laravel框架(),解压到服务器根目录www下。
Laravel 4 的安装。打开cmd命了窗口,使用cd命令将目录切换到服务器根目录下。执行命令composer install ,等待下载完成。
访问项目主页。因为在Laravel框架中,没有index.php文件,而是用server.php文件来替代的,所以我们需要修改Apache的http.conf文件,在IfModule dir_module下面添加server.php即可。具体修改如下图所示:
配置成功后,直接访问,即可出现以下界面,则安装成功!
Laravel源码里面为什么要用:class语法
自 PHP 5.5 起,关键词 class 也可用于类名的解析。使用 ClassName::class 你可以获取一个字符串,包含了类 ClassName 的完全限定名称。这对使用了 命名空间 的类尤其有用。
[php] view plain copy
$app-singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
$app-singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
$app-singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
这段bootstrap/app.php代码中既然已经写了类的完全限定名,为什么还要用::class语法?
解释:
因为 ::class 表示是字符串。此处代码等同于:
[php] view plain copy
$app-singleton(
'Illuminate\Contracts\Http\Kernel',
'App\Http\Kernel'
);
$app-singleton(
'Illuminate\Contracts\Console\Kernel',
'App\Console\Kernel'
);
$app-singleton(
'Illuminate\Contracts\Debug\ExceptionHandler',
'App\Exceptions\Handler'
);
用 ::class 的好处在于 IDE 里面可以直接改名一个 class,然后 IDE 自动处理相关引用。
同时,php 执行相关代码时,是不会先加载相关 class 的。
同理,代码自动化检查 inspect 也可以正确识别 class。