Laravel 学习心得
来源:互联网 发布:电脑的记事软件 编辑:程序博客网 时间:2024/06/07 03:11
搭建Laravel
工欲善其事必先利其器,我们先搭建laravel,看看它的结构。
Laravel的核心设计模式
控制反转(IoC):由内部依赖转化为外部依赖,调用者不在自身内部创建被调用者的实例,改为在外部创建。一般通过“接口(interface)”去约束外部依赖,让它满足我们的依赖条件。这个过程我们成为依赖注入(DI)。
//普通内部依赖class robot { private $abilities = []; public function __construct($a){ $abilities = $a ; } public function doSomething() { foreach($abilities as $ability){ echo $ability; } }}//=======分割线===========//外部依赖实现的接口interface abilityInterface { public function work(){}}//接口的具体实现class swimRobot implements abilityInterface { public funtion work(){ echo 'swim'; }}class answerRobot implements abilityInterface { public funtion work(){ echo 'answer'; }}//外部依赖(构造函数)class robot { private $ability; public function __construct(abilityInterface $ability){ $this->ability = $ability; } public function doSomething(){ $this->ability->work(); }}$robot_swim = new robot(new swimRobot());$robot_answer = new robot(new answerRobot());
通过控制反转,我们可以根据业务需求去制造不同功能的类,只需要在类外部修改代码就可以,这个类实现我们约定的接口就可以。
laravel的核心是一个IoC容器。所谓的容器就是一个可以动态添加依赖的类。
//简单的“IoC容器“”class IocContainer { private $classes_dependencies = []; public function bind($class, $dependency){ $this->classes_dependencies[$class] = $dependency; } public function initialize($class, $parameters = []){ if(isset($this->classes_dependencies[$class])){ return call_user_func_array($this->classes_dependencies[$class], $parameters); } }}
服务提供者(Service Provider): 我们了解了IoC容器的概念之后,知道要声明服务类(一个提供服务的类,我们称为服务类),那必须在IoC容器中注册,在控制器中就可以直接找到该类并使用。我们不能把注册行为分散到每个类中,所以使用服务提供者来帮我们实现这个注册的动作。同时也便于管理。Laravel中使用配置文件去配置服务提供者,然后使用服务提供者去向IoC容器去注册服务类。
<?php//为了示例声明了服务类的契约。namespace App\Contracts;interface MessageContract{ public function send($m);}
<?php//定义一个提供服务的类namespace App\Services;use App\Contracts\MessageContract;class MessageService implements MessageContract { public function send($m){ echo "send message: ".$m; }}
定义完这个消息类之后,我们需要将它注册。需要一个对应的服务提供者。可以使用下面的命令:
php artisan make:provider MessageServiceProvider
<?php//这是生成的服务提供者。namespace App\Providers;use Illuminate\Support\ServiceProvider;use App\Services\MessageService ; //我们刚刚定义的服务类class MessageServiceProvider extends ServiceProvider{ /** * Bootstrap the application services. * * @return void */ public function boot() { // } /** * Register the application services. * * @return void * @author LaravelAcademy.org */ public function register() { //使用singleton绑定单例 $this->app->singleton('MyMessage',function(){ return new MessageService(); }); //或者使用bind绑定实例到接口以便依赖注入 /* $this->app->bind('App\Contracts\MessageContract',function(){ return new MessageService(); }); */ }}
可以看到一个服务提供者有两个方法,boot跟register。当我们确定没有使用其他尚未加载的服务类时,我们写在register方法中,并且只绑定事物到服务容器,不做其他事情。当我们使用到了尚未加载的服务类时,我们写在boot中,该方法是在所有服务提供者被注册以后才会被调用。例如:
public function boot() { //这里使用了其他未被加载的服务类 view()->composer('view', function () { // }); }
如果我们确定当前服务只需要一个实例,我们可以使用 singleton 去注册,我们使用到该服务的时候都是取这一个实例,如果我们需要动态修改(依赖注入)这个服务类,我们使用bind方法。两者取一。底层的框架singleton的实现代码:
...public function singleton($abstract, $concrete = null){ $this->bind($abstract, $concrete, true);}...
我们需要去向容器注册我们的服务提供者,追加该类到配置文件config/app.php的providers数组中即可:
'providers' => [ //其他服务提供者 App\Providers\MessageServiceProvider::class,],
创建一个test控制器:
php artisan make:controller Test/TestController
简单设置路由(app\Http\routes.php):
Route::resource('test','Test\TestController');
<?phpnamespace App\Http\Controllers\Test;use Illuminate\Http\Request;use App\Http\Requests;use App\Http\Controllers\Controller;class TestController extends Controller{ /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { //直接使用容器调用 app('MyMessage')->send('testing'); } ...//其他控制器动作}
访问你本地的路由就可以看到结果(public作为根目录)。我们回顾一下声明服务的过程,首先声明一个提供服务的类(可以选择使用契约),声明一个对应的服务提供者,将它注册到IoC容器,接着注册一下该服务提供者。在IoC容器看来,就是先获取了服务提供者数组,然后注册他们提供的服务类。如果我们需要修改这个服务类,只需要修改它本身就可以,删除就取消注册对应的服务提供者,控制器中的代码不用去关心这个服务类。
门面模式 (Facade):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。门面模式又称为外观模式,它是一种对象结构型模式。
门面模式的概念看起来挺复杂,我们结合生活中的例子来阐述。
场景:下班回家,你首先要开门,开灯,然后开煮水器,开热水器,开空调。我们抽象你的家为一个系统,那么你(用户)跟这个系统的交互是很繁杂的。门面模式为你提供一个家用机器人,只需要告诉这个机器人我要回家了,它会帮你把上面的动作都做好,你(用户)根本感觉不到家里的电器是怎么开的。在这个例子中,机器人就相当于系统的“门面”或者“外观”。
在 Laravel 应用中,该机制原理由 Facade 类实现。Laravel 自带的门面,以及我们创建的自定义门面,都会继承自 Illuminate\Support\Facades\Facade 基类。门面类只需要实现一个方法:getFacadeAccessor。正是 getFacadeAccessor 方法定义了从容器中解析什么,然后Facade 基类使用魔术方法 __callStatic() 从你的门面中调用解析对象。下面是实例:
创建一个出租屋类:
<?phpnamespace App\Facades;class RentHouse{ public function comeHome() { echo "turn on the lights <br>"; echo "turn on the TV <br>"; echo "shower <br>"; }}
创建一个出租屋的机器人(门面):
<?phpnamespace App\Facades;use Illuminate\Support\Facades\Facade;class RentHouseRobot extends Facade{ protected static function getFacadeAccessor() { //相当于告诉容器 该类是哪个类的门面 return 'RentHouse'; }}
接下来我们要在服务提供者中绑定Test类到服务容器,新建一个provider:
<?phpnamespace App\Providers;use Illuminate\Support\ServiceProvider;use App\Facades\RentHouse;class RentHouseProvider extends ServiceProvider{ /** * Bootstrap the application services. * * @return void */ public function boot() { } /** * Register the application services. * * @return void */ public function register() { $this->app->singleton('RentHouse',function(){ return new RentHouse(); }); }}
再然后需要到配置文件config/app.php中注册门面类别名以及RentHouseProvider:
'providers' => [ //其他服务提供者 App\Providers\RentHouseProvider::class,],'aliases' => [ ...//其他门面类别名映射 'RentHouseRobot' => App\Facades\RentHouseRobot::class,],
最后控制器再调用:
<?phpnamespace App\Http\Controllers\Test;use Illuminate\Http\Request;use App\Http\Requests;//这里需要引入这个门面use RentHouseRobot;use App\Http\Controllers\Controller;class TestController extends Controller{ /** * Display a listing of the resource. * * @return Response */ public function index() { //app('MyMessage')->send('testing'); RentHouseRobot::comeHome(); } ...//其他方法}
同上访问你的路由就可以看到结果了。
仓储模式(repository):Repository 是一个独立的层,介于领域层与数据映射层(数据访问层)之间。它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接口提供给领域层进行领域对象的访问。Repository 是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。
又是文绉绉的定义。让我们举这样一个例子,有一个有钱人,他有农场,牧场,渔场。这几个仓库的类型都是不一样的,我们(领域层)去操作不同的仓库是痛苦的,所以需要一个仓库管理员,他负责帮我们存储,取出,扔掉,只要他会这些技能他就能做我们的仓库管理员。同时我们定义一个类别的货物成对象,比如渔场的产品,有名字,鱼类,生产日期等,我们跟仓库管理员打交道只需要获取这个对象去处理就可以了,其他的我们不用管。实例如下:
我们先定义我们货物的类,假设货物具有产地,ID,生成日期,过期时间,名称等属性。
<?phpnamespace App\Repositories\Farm;//在仓储模式中,我们定义货物的类只需要属性跟getter,setter。class Product{ private $id; private $name; private $created; private $source; private $expired; public function setId($id) { $this->id = $id; } public function getId() { return $this->id; } public function setName($name) { $this->name = $name; } public function getName() { return $this->name; } public function setCreated($created) { $this->created = $created; } public function getCreated() { return $this->created; } public function setSource($source) { $this->source = $source; } public function getSource() { return $this->source; } public function setExpired($expired) { $this->expired = $expired; } public function getExpired() { return $this->expired; }}
接下来我们定义一个仓库应该具有的方法(数据访问层):
<?phpnamespace App\Repositories\Farm;interface Storage{ //制定一些规则 public function persist($data); public function retrieve($id); public function delete($id);}
通过实现上面的接口,我们可以定义一个或几个仓库管理员。在实际应用中,我们或许会对货物划分不同的规则,但是货物类本身是不会改变的,规则就交给仓库管理员接口去管理。
<?phpnamespace App\Repositories\Farm;use App\Repositories\Farm\Storage;//一个仓库管理员的实现class FarmStorage implements Storage { private $data; private $lastId; public function __construct() { $this->data = array(); $this->lastId = 0; } public function persist($data) { $this->data[++$this->lastId] = $data; return $this->lastId; } public function retrieve($id) { return isset($this->data[$id]) ? $this->data[$id] : null; } public function delete($id) { if (!isset($this->data[$id])) { return false; } $this->data[$id] = null; unset($this->data[$id]); return true; }}
- Laravel 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- 学习心得
- mongodb 索引基础
- Android上如何实现矩形区域截屏
- 阿里巴巴图标
- [BZOJ]1922 [SDOI2010] 大陆争霸 最短路 + 堆优化
- 软件外包交易平台排行
- Laravel 学习心得
- MapReduce简介
- 怪异模式与标准模式
- Java修行之路
- mongodb基础命令
- maven创建的工程css文件不生效问题
- 西南交通大学第十三届ACM决赛-重现赛-H(BFS+DP)
- linux下内核对打开的文件结构的表示
- Dubbo各种协议