laravel_slide



laravel_slide

6 15


laravel_slide

A html presentation about laravel

On Github lifesign / laravel_slide

LARAVEL与框架二三事

高锋

2014-12-20 @ 四脚猫

  • 常用ID: 云袭/lifesign
  • 混迹各大技术社区
  • lifesign.me

PHPhub 社区

Laravel-china.org

laravel 现状

2014年php开发框架流行度排名

Github Star

First Commit

Author: Taylor Otwell

发布里程

  • 2011年6月 1.0.0 Beta
  • 2011年11月 2.0发布
  • 2013年5月 3.2发布
  • 2013年12月 4.0发布
  • 到目前为止最新版本是4.2.11

....

2015年1月 laravel5

「Laravel特点」

“Laravel是一个简单优雅的PHP Web开发框架,可以将开发者从意大利面条式的代码中解放出来,通过简单、高雅、表达式语法开发出很棒的Web应用,Laravel拥有更富有表现力的语法、高质量的文档、丰富的扩展包,被称为“巨匠级PHP开发框架”。”

特色简介

  • 强大的路由系统
  • 合理的 ORM model 层, Eloquent ORM
  • Blade 模板引擎
  • migration 数据库版本系统 和 seeding
  • artisan命令行工具, 高度自动化
  • 使用包管理器 Composer 扩展
  • 强调测试驱动, 高质量代码

Route System

  • Routing for basic static pages
  • Passing parameters to functions
  • Using named routes to make URLs easier to use
  • Filtering routes for Auth or anything else
  • Group routing
  • Routing to Controller
  • Resource Route

先来一个最基本的路由

// app/routes.php
Route::get('/', function(){
    return View::make('hello');
})

其他请求呢?

Route::post('foo/bar', function(){
    return 'Post Request';
})

Route::any('foo', function(){
    return 'Any Request';
});

路由参数

很多时候往往路由不是静态的地址, 而是带有动态的参数. 比如blog/{$category}

Route::get('blog/{category}', function($category){
    return "Finding Post in {$category}";
});

可选参数

Route::get('blog/{category?}', function($category = null){
    if ($category)
        //fetch blogs in this category
    else 
        //fetch all blogs

    return View::make('blog', /* $blogs */);
});

命名路由

顾名思义是给路由进行命名, 有什么好处呢?

Route::get('user/{id}', ['as' => 'user.detail', function($id){
   // 
}]);
  • 生成重定向跳转 Redirect::route('user.detail', $id);
  • 生成 url route('user.detail', $id) -> "http://domain/user/$id"

路由过滤

//define filter
Route::filter('login', function()
{
    // Some Logic check if the current user is login
});

在特定的路由前进行过滤 使用 before 关键字

Route::get('money', ['before' => 'login', function(){
    // see user's money
}]);

群组路由

如果不想为每个路由定义相同的过滤器, 我们可以采用群组路由的方式

Route::group(['before' => 'csrf'], function(){

    Route::post('login', function(){});

    Route::post('user/profile', function(){});
});

控制器路由

Route::get('user/{id}', 'UserController@showProfile');

控制器

class UserController extends BaseController {

    /**
     * Show the profile for the given user.
     */
    public function showProfile($id)
    {
        $user = User::find($id);

        return View::make('user.profile', ['user' => $user]);
    }

}

资源控制器

Route::resource('photo', 'PhotoController');

Eloquent ORM

Laravel 的 Eloquent ORM 提供了漂亮、简洁的 ActiveRecord 实现来和数据库的互动。 每个数据库表会和一个对应的「模型」互动。

Eloquent ORM ——CRUD Example

// 获取所有任务记录
$tasks = Task::all();

// 获取ID为1的任务
$task = Task::find(1);

// 更新ID为1的task
$task = Task::find(1);
$task->title = 'Finish Homework';
$task->save();

// 创建一条任务
Task::create([
    'title' => 'Write article'
]);

// 删除任务
Task::find(1)->delete();

Eloquent ORM

Relationship

  • 一对一
  • 一对多
  • 多对多

One To One Example

class User extends Eloquent {

    public function phone()
    {
        return $this->hasOne('Phone');
    }

}

$phone = User::find(1)->phone;

SQL执行

select * from users where id = 1

select * from phones where user_id = 1

One To Many Example

class Task extends Eloquent {

    public function user()
    {
        return $this->belongsTo('User');
    }

}
class User extends Eloquent {

    public function tasks()
    {
        return $this->hasMany('Task');
    }

}
// Get all tasks by the author with an id of 1
$tasks = User::find(1)->tasks;

// Get the author of a task
$author = Task::find(5)->user()->username;

// Insert a new task by author
$task = new Task([ title: 'Go to store.' ]);
User::find(1)->tasks()->insert($task);

Eloquent ORM ——Mass-assignment

//需要手动指定一堆的键值 为的是预防多余字段插入
News::create([
    'title' => Input::get('title'),
    'slug' => Input::get('slug'),
    'content' => Input::get('content'),
    'published_at' => Input::get('published_at'),
])

一个常见的场景

有没有更简单直观的做法呢?

通过定义fillable属性 - "白名单"

class News extends Eloquent {

    protected $fillable = array('title', 'slug', 'content', 'published_at');

}

定义Guarded属性 - "黑名单"

class News extends Eloquent {

    protected $guarded = array('id');

}

Finally:

News::create(Input::get());

Model Events

  • Eloquent 模型中定义了很多的事件, 使得我们可以在模型操作的生命周期的不同时间点, 通过以下方法绑定事件creating 、 created 、 updating 、 updated 、 saving 、 saved、 deleting 、 deleted 、 restoring 、 restored 。
  • 当一个对象被创建时, creating 和 created 事件会被触发。如果是更新对象, updating / updated 事件会被触发。而两者的 saving / saved 事件都会触发。

Model Events Example

Eloquent_Model_Name::Event_Name(callback)

//创建或者修改post模型的时候自动加入编辑的人的id

Post::creating(function($post)
{
    $post->created_by = Auth::user()->id;
    $post->updated_by = Auth::user()->id;
});

Post::updating(function($post)
{
    $post->updated_by = Auth::user()->id;
});

//删除图片
Image::deleting(function($image)
{
    if (count($image->galleries)) return false;
});

Model Observer Example

如果我们对一个模型注册了很多的事件, 可以为这个模型单独注册一个模型的观察者。

class UserObserver {
    public function creating($model) {}
    public function updating($model) {}
    public function saved($model)    {}
}

使用 observe 方法注册一个观察者的实例 User::observe(new UserObserver)

Setter And Getter

允许动态的对模型进行获取和修改

Getter

class User extends Eloquent {

    public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }

}

echo User::find(1)->firstName; // jack->Jack

Setter

class User extends Eloquent {

    public function setPasswordAttribute()
    {
        return md5( $this->password );
    }
}

更多用法

官方文档

Blade模板引擎

"Laravel 所提供的一个简单却又非常强大的模板引擎。Blade 是使用 模板继承(template inheritance) 及 区块(sections) 来创建出视图。所有的 Blade 模板的后缀名都要命名为 .blade.php。"

一个简单的layout

<!-- Stored in app/views/layouts/master.blade.php -->

<html>
    <body>
        @include('layouts.partial.nav')

        @section('sidebar')
            This is the master sidebar.
        @show

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>

继承布局

@extends('layouts.master')

@section('sidebar')
    <!-- 如果需要调用父类的section 用@parent关键字 -->
    @parent

    <p>This is appended to the master sidebar.</p>
@stop

@section('content')
    <!-- {{}} 输出变量  {{{}}}过滤内容中的 HTML 字符串实体 -->
    Hello, {{ $name }}. {{{age}}}
    <p>This is my body content.</p>
@stop

其他控制语法

@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    No Records.
@endif


@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach

@while (true)
    <p>looping forever.</p>
@endwhile

Migrations & Seeds

  • Migrations: 数据库的版本控制
  • Seeds: 数据导入

来个栗子

php artisan migrate:make create_users_table --table=users --create

<!-- store in app/database/migrations/2014_12_19_095403_create_users_table -->
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration {


    public function up()
    {
        Schema::create('users', function($table)
        {
            $table->increments('id');
            $table->string('name');
            $table->integer('age');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::drop('users');
    }

}

执行操作 php artisan migrate

执行回滚 php artisan rollback

重置操作 php artisan reset

Seed Example

//入口
class DatabaseSeeder extends Seeder {

    public function run()
    {
        //调用UserTableSeeder的run方法 一个表一个seeder
        $this->call('UserTableSeeder');
        // $this->call('OtherTableSeeder');

        $this->command->info('User table seeded!');
    }

}

//使用faker作为假数据生成器
use Faker\Factory as Faker;

class UserTableSeeder extends Seeder {

    public function run()
    {   
        $faker = Faker::create();

        foreach(range(1, 50) as $index)
        {
            User::create([
                'github_id'        => $index,
                'github_url'       => $faker->url(),
                'city'             => $faker->city(),
                'name'             => $faker->userName(),
                'introduction'     => $faker->sentence(),
                'email'            => $faker->email(),
            ]);
        }
    }

}

执行: php artisan db:seed

Artisan 命令行工具

查看当前路由

php artisan route

Other Useful Command

  • php artisan down 进入维护模式 (php artisan up 可恢复)
  • php artisan tinker 内置的repl模式 可以直接进行数据库操作
  • php artisan serve 开启内置server
  • php artisan tail 实时查看laravel的log

使用Composer扩展

是 PHP 用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件。

关于安装

php >= 5.3.2 openssl √ (win下使用php套件的同学注意多个php.ini问题)

$ curl -sS https://getcomposer.org/installer | php
$ mv composer.phar /usr/local/bin/composer
$ composer

 / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version d79f2b0fd33ee9b89f3d9f1969f43dc3d570a33a 2014-09-10 15:11:05

Usage:
  [options] command [arguments]
...

简明三步教程

在项目目录中创建 composer.json 文件, 比如 Monnolog

{
    "require": {
        "monolog/monolog": "1.2.*"
    }
}

安装依赖

在项目目录中执行 composer install

引入自动加载

在代码初始化的部分引入下面的代码:

require 'vendor/autoload.php'

Other Thing

packagist.orgComposer 的官方仓库, 一些知名的PHP库都能在其中找到, 也可以提交自己的类库。 被墙可以考虑使用Composer国内镜像 公司内部可使用Satis 使用Toran自建镜像

What Else?

What's New in laravel5

  • Elixir
  • Event Scheduling
  • Event Annotations
  • Form Request
  • FileSystem - Flysystem
  • Method Injection
  • Route Cache
  • Route Annotations
  • Socilate

关于学习框架的一些建议

  • 关注web开发领域
  • 标准化
  • 从最熟悉的开始
  • 善用工具
  • 阅读经典书籍

自我定位

建议1. 关注web开发领域

不局限在PHP层面 多关注框架以外的共有的东西 借鉴、改良、优化

建议2. 标准化

  • PSR
  • Composer
  • Vagrant

标准化之PSR

PSR 是由 FIG制定的php规范, 简称PSR。

为什么要制定规范?

本组织旨在通过讨论我们代码项目的共同点以找出一个协作编程的方法。

目前发布的规范如下

  • PSR-0 自动加载(类名中的_会自动转换成目录分隔符)
  • PSR-1 基本代码规范(命名、字符编码等)
  • PSR-2 代码风格(缩进、括号、关键字位置等)
  • PSR-3 日志接口(日志等级)
  • PSR-4 自动加载(指定文件路径来自动加载)

标准化之composer

  • 使用composer作为项目的依赖管理工具, 只需要维护 composer.json / composer.lock
  • 使用优秀的,遵循标准的类库
  • 发布自己的类库, 为开源贡献力量

标准化之vagrant

Vagrant 是一款用来构建虚拟开发环境的工具, 非常适合来做 web 开发。

我们可以通过 Vagrant 封装一个 Linux的开发环境, 分发给团队成员。成员可以在自己喜欢的桌面系统(Mac/Windows/Linux)上开发程序, 代码却能统一在封装好的环境里运行, 而不用担心由于所在系统环境造成的未知bug。

Vagrant Quick Start

安装 virtualbox 安装 vagrantup 执行命令
$ vagrant init hashicorp/precise32
$ vagrant up

Laravel Way --Homestead

Laravel 官方定制的 vagrant 包, 包含常用一套完整的开发环境

  • Ubuntu 14.04
  • PHP 5.5
  • Nginx
  • MySQL
  • Postgres
  • Node (With Bower, Grunt, and Gulp)
  • Redis
  • Memcached
  • Beanstalkd
  • Laravel Envoy
  • Fabric + HipChat Extension

安装

  • vagrant box add laravel/homestead
  • composer global require "laravel/homestead=~2.0" 配置SSH-key
  • homestead up
  • homestead ssh
  • homestead halt

建议3. 从最熟悉的开始

了解框架的分类

  • 传统mvc: [Thinkphp], [CI]
  • 全栈式: [Laravel], [Phalcon]
  • 组件式: [Symfony], [Aura]
  • 微框架:[Slim],[Silex]

找到适合自己的方法

  • 找一个自己喜欢的 熟悉的钻研源码
  • 了解框架生命流程、某个组件的实现
  • 尝试自己写一个框架

建议4. 善用工具

  • IDE: PHPstorm/Netbeans/Zend Studio
  • Editor: Sublime Text/Atom
  • Debug: Whoops/Socketlog

建议5. 阅读经典书籍

总结

Thanks