Project-Flyer-13-Thumbnails

跟随 Jeffrey Way 的视频学习,脑子不好,一些细节容易忘记,这里记录下来。相关视频在 laracasts.com
课程名称:Build “ProjectFlyer” With Me(13)

本节实现图片更友好的显示。
用到的插件:intervention image
Github 项目页:https://github.com/Intervention/image
Google intervention image 第一个就是它的官方网站。

下面我们先安装这个插件:

composer require intervention/image

在 ingervention image 的官方帮助里可以看到关于 laravel 的配置方法,打开 config/app.php,在:

App\Providers\RouteServiceProvider::class,

下面添加:

Intervention\Image\ImageServiceProvider::class,

在:

'View'      => Illuminate\Support\Facades\View::class,

下面添加:

'Image'     => 'Intervention\Image\Facades\Image',

打开 FlyerController 控制器,修改构造函数:__construct为:

function __construct() {
    $this->middleware('auth', ['except' => ['show']]);
}

修改 addPhoto 方法:

$photo = Photo::fromForm($request->file('photo'));

为:

$photo = Photo::fromForm($request->file('photo'))->store();

我们上传图片的过程中同时要把缩略图放到某个位置,为此,原先的方法可以改造下,会重复利用的,我们把它抽象出来。

这里可以把Photo::fromForm($request->file('photo'))->store();抽象出来,新建方法:

public function makePhoto(UploadedFile $file)
{
    return Photo::fromForm($file)->store($file);
}

替换:

$photo = Photo::fromForm($request->file('photo'))->store();

为:

$photo = $this->makePhoto($request->file('photo'));

注意到 Photo.php 里还不存在入库方法 store(),我们创建它:

public function store(UploadedFile $file)
{
    $file->move($photo->baseDir, $name);
}

修改 fromForm 方法为:

public static function fromForm(UploadedFile $file)
{
    $photo = new static;
    $photo->saveAs($file->getClientOriginalName());
    $name = time() . $file->getClientOriginalName();
    $photo->path = $photo->baseDir . '/' . $name;
    return $photo;
}

好吧,saveAs 也不存在,我们也创建它:

public function saveAs($name)
{
    // $this->name
    // $this->path
    // $this->thumbnail_path
}

我们的缩略图和原图的文件路径和名称应该是不一样的,所以原表的字段缺少了缩略图路径的字段。
修改 migrations下的 create_flyer_photos_table 文件,添加新字段,修改 up 方法为:

public function up()
{
    Schema::create('flyer_photos', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('flyer_id')->unsigned();
        $table->foreign('flyer_id')->references('id')->on('flyers')->onDelete('cascade');
        $table->string('name');
        $table->string('path');
        $table->string('thumbnail_path');
        $table->timestamps();
    });
}

然后去 Homestead 虚拟主机网站根目录下运行:php artisan migrate:refresh 来重建数据表。

正如我们在 saveAs 方法中注释的那样,现在我们的类对象需要用到的参数是三个:name,path,thumbnail_path,所以,我们需要修改 Photo.php 类的成员变量 $fileable 为:

protected $fillable = ['path', 'name', 'thumbnail_path'];

修改 saveAs 为:

public function saveAs($name)
{
    $this->name = sprintf("%s-%s", time(), $name);
    $this->path = sprintf("%s/%s", $this->baseDir, $this->name);
    $this->thumbnail_path = sprintf("%s/tn-%s", $this->baseDir, $this->name);
    return $this;
}

修改 fromForm 方法为:

public static function fromForm(UploadedFile $file)
{
    $photo = new static;
    return $photo->saveAs($file->getClientOriginalName());
}

进一步精简下 fromForm 方法:

public static function fromForm(UploadedFile $file)
{
    return (new static)->saveAs($file->getClientOriginalName());
}

修改 makePhoto 方法为:

public function makePhoto(UploadedFile $file)
{
    return Photo::named($file->getClientOriginalName())
    ->move($file);
}

打开 Photo.php,重命名 fromForm 方法名称为 named,并修改它为:

/**
 * Build a new photo instance from a file upload.
 * @param  string $name 
 * @return self       
 */
public static function named($name)
{
    return (new static)->saveAs($name);
}

为 Photo 添加引用:

use Image;

重命名 Photo.php 里的 store 方法为 move,并修改为:

public function move(UploadedFile $file)
{
    $file->move($this->baseDir, $this->name);

    Image::make($this->path)
        ->fit(200)
        ->save($this->thumbnail_path);

    return $this;
}

我们把 Image::make 的调用抽象成单独的方法 makeThumbnail 新建这个方法为:

public function makeThumbnail()
{
    Image::make($this->path)
        ->fit(200)
        ->save($this->thumbnail_path);        
}

修改 move 方法为:

public function move(UploadedFile $file)
{
    $file->move($this->baseDir, $this->name);
    $this->makeThumbnail();
    return $this;
}

修改 Flyer.php 文件的 addPhoto 方法为:

public function addPhoto(Photo $photo)
{
    return $this->photos()->save($photo);
}

修改 locatedAt 方法为:

public static function locatedAt($zip, $street)
{
    $street = str_replace('-', ' ', $street);
    return static::where(compact('zip', 'street'))->firstOrFail();
}

此时测试,我遇到了一个问题,上传图片失效了,问题出在 FlyerController 控制器里缺少引用:

use Symfony\Component\HttpFoundation\File\UploadedFile;

看插件官方有一行命令用于 push configuration in Laravel 5:

php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravel5"

我执行了。

上传成了,但是没有出现视频里的小图片的样子,应该是 show.blade.php 模板的问题吧,看了看,果然是,将

<img src="/{{ $photo->path }}" alt="">

修改为:

<img src="/{{ $photo->thumbnail_path }}" alt="">

看看效果。应可以看到缩略图了。

现在修改下这些缩略图的样式,修改 show.blade.php 里的内容部分为:

<div class="row">
<div class="col-md-4">
<h1>{{ $flyer->street }}</h1>
<h2>{!! $flyer->price !!}</h2>

<hr>

<div>{!! nl2br($flyer->description) !!}</div>
</div>

<div class="col-md-8 gallery">
@foreach ($flyer->photos->chunk(4) as $set)
<div class="row">
@foreach ($set as $photo)
<div class="col-md-3 gallery__image">
<img src="/{{ $photo->thumbnail_path }}" alt="">
</div>
@endforeach
</div>
@endforeach
</div>

</div>

修改 app.scss,添加下面行:

.gallery__image{
    margin-bottom:1em;
}

然后运行gulp

ok,本节完毕!

pause at 12:19 of the video…

0%