六、创建照片库系统

在本章中,我们将使用 Laravel 编写一个简单的照片库系统。我们还将介绍 Laravel 的内置文件验证、文件上传,以及有许多数据库关系机制。我们将使用validation类来验证数据和文件。此外,我们将介绍用于处理文件的文件类。本章涵盖以下主题:

  • 创建相册模型
  • 创建图像模型
  • 创建相册
  • 创建照片上传表单
  • 在相册之间移动照片

创建表格并迁移相册

我们假设您已经在位于app/config/database.php文件中定义了数据库凭证。为了建立一个照片库系统,我们需要一个有两个表的数据库:albumsimages。要创建新数据库,只需运行以下 SQL 命令:

CREATE DATABASE laravel_photogallery

为应用成功创建数据库后,我们首先需要创建albums表并将其安装在数据库中。为此,请打开您的终端,浏览项目文件夹,并运行以下命令:

php artisan migrate:make create_albums_table --table=albums --create

前面的命令将在app/database/migrations下生成一个迁移文件,以在我们的laravel_photogallery数据库中生成一个名为posts的新 MySQL 表。

要定义我们的表列,我们需要编辑迁移文件。编辑后,文件应具有以下代码:

<?php

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

class CreateAlbumsTable extends Migration {

  /**
  * Run the migrations.
  *
  * @return void
  */
  public function up()
    {
      Schema::create('albums', function(Blueprint $table)
      {
        $table->increments('id')->unsigned();
        $table->string('name');
        $table->text('description');
        $table->string('cover_image');
        $table->timestamps();
      });
    }

  /**
  * Reverse the migrations.
  *
  * @return void
  */
  public function down()
  {
    Schema::drop('albums');
  }
}

在保存文件后,我们需要再次使用一个简单的 artisan 命令来执行迁移:

php artisan migrate

如果没有出现错误,请查看albums表及其列的laravel_photogallery数据库。

让我们检查以下列表中的列:

  • id:此栏用于存储相册的 ID
  • name:此栏用于存储相册名称
  • description:此栏用于存储相册的描述
  • cover_image:此栏用于存储相册封面图片

我们已经成功创建了我们的albums表,因此我们需要对我们的专辑模型进行编码。

创建相册模型

正如你所知,对于任何与 Laravel 上的数据库操作相关的事情,使用模型是最好的做法。我们将受益于使用雄辩的 ORM。

将以下代码保存为app/models/目录中的Album.php:

<?php
class Album extends Eloquent {

  protected $table = 'albums';

  protected $fillable = array('name','description','cover_image');

  public function Photos(){

    return $this->has_many('images');
  }
}

我们已经使用protected $table变量设置了数据库表名;我们还使用protected $fillable变量设置了可编辑的列,我们在前面的章节中已经看到并使用了这个变量。模型中定义的变量足以使用 Laravel 的雄辩 ORM。我们将在本章的为相册分配照片部分介绍public Photos ()功能。

我们的专辑模型准备好了;现在我们需要一个图像模型和一个数据库来给相册分配照片。让我们创造它们。

用迁移类创建图像数据库

要为图像创建我们的迁移文件,请打开您的终端,浏览您的项目文件夹,并运行以下命令:

php artisan migrate:make create_images_table --table=images --create

如您所知,该命令将在app/database/migrations中生成一个迁移文件。让我们编辑迁移文件;最终代码应该如下:

<?php

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

class CreateImagesTable extends Migration {

  /**
  * Run the migrations.
  *
  * @return void
  */
  public function up()
  {
    Schema::create('images', function(Blueprint $table)
    {
      $table->increments('id')->unsigned();
      $table->integer('album_id')->unsigned();
      $table->string('image');
      $table->string('description');
      $table->foreign('album_id')->references('id')->on('albums')->onDelete('CASCADE')->onUpdate('CASCADE');
      $table->timestamps();
    });
  }

  /**
  * Reverse the migrations.
  *
  * @return void
  */
  public function down()
  {
    Schema::drop('images');
  }
}

编辑迁移文件后,运行以下迁移命令:

php artisan migrate

如您所知,该命令创建images表及其列。如果没有出现错误,请检查users表和列的laravel_photogallery数据库。

让我们检查以下列表中的列:

  • id:此列用于存储图像的 id
  • album_id:此列用于存储图片相册的 id
  • description:此栏用于存储图像的描述
  • image:此列用于存储图像的路径

我们需要为这个迁移文件再解释一件事。在迁移代码中可以看到,有一个foreign键。当我们需要链接两个表时,我们使用foreign键。我们有一张albums桌子,每张专辑都有图片。如果相册从数据库中删除,您希望它的所有图像也被删除。

创建图像模型

我们已经创建了images表。所以,如你所知,我们需要一个模型来操作 Laravel 上的数据库表。要创建它,请将以下代码保存为app/models/目录中的 Image.php:

class Images extends Eloquent {

  protected $table = 'images';

  protected $fillable = array('album_id','description','image');

}

我们的影像模型准备好了;现在我们需要一个控制器来创建数据库中的相册。让我们创造它。

创建相册

正如你从本书前面几章所知道的, Laravel 有一个很棒的 RESTful 控制器机制。在开发过程中,我们将继续使用它来保持代码的简单和简短。在接下来的章节中,我们将介绍另一个名为 资源控制器的优秀控制器/路由方法。

要列出、创建和删除相册,我们需要控制器中的一些功能。要创建它们,请将以下代码保存为app/controllers/目录中的AlbumsController.php:

<?php

class AlbumsController extends BaseController{

  public function getList()
  {
    $albums = Album::with('Photos')->get();
    return View::make('index')
    ->with('albums',$albums);
  }
  public function getAlbum($id)
  {
    $album = Album::with('Photos')->find($id);
    return View::make('album')
    ->with('album',$album);
  }
  public function getForm()
  {
    return View::make('createalbum');
  }
  public function postCreate()
  {
    $rules = array(

      'name' => 'required',
      'cover_image'=>'required|image'

    );

    $validator = Validator::make(Input::all(), $rules);
    if($validator->fails()){

      return Redirect::route('create_album_form')
      ->withErrors($validator)
      ->withInput();
    }

    $file = Input::file('cover_image');
    $random_name = str_random(8);
    $destinationPath = 'albums/';
    $extension = $file->getClientOriginalExtension();
    $filename=$random_name.'_cover.'.$extension;
    $uploadSuccess = Input::file('cover_image')
    ->move($destinationPath, $filename);
    $album = Album::create(array(
      'name' => Input::get('name'),
      'description' => Input::get('description'),
      'cover_image' => $filename,
    ));

    return Redirect::route('show_album',array('id'=>$album->id));
  }

  public function getDelete($id)
  {
    $album = Album::find($id);

    $album->delete();

    return Redirect::route('index');
  }
}

postCreate()功能首先验证表单的发布数据。接下来我们将讨论验证。如果数据验证成功,我们将重命名封面图像并用新文件名上传,因为代码会覆盖同名文件。

getDelete()功能是从数据库中删除相册以及分配的图像(存储在images表中)。请记住以下迁移文件代码:

$table->foreign('album_id')->references('id')->on('albums')->onDelete('CASCADE')->onUpdate('CASCADE');

在创建模板之前,我们需要定义路线。因此,打开app文件夹中的routes.php文件,并用以下代码替换该代码:

<?php
Route::get('/', array('as' => 'index','uses' => 'AlbumsController@getList'));
Route::get('/createalbum', array('as' => 'create_album_form','uses' => 'AlbumsController@getForm'));
Route::post('/createalbum', array('as' => 'create_album','uses' => 'AlbumsController@postCreate'));
Route::get('/deletealbum/{id}', array('as' => 'delete_album','uses' => 'AlbumsController@getDelete'));
Route::get('/album/{id}', array('as' => 'show_album','uses' => 'AlbumsController@getAlbum'));

现在,我们需要一些模板文件来显示、创建和列出相册。首先,我们应该创建索引模板。要创建它,请将以下代码保存为app/views/目录中的index.blade.php:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Awesome Albums</title>
    <!-- Latest compiled and minified CSS -->
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css" rel="stylesheet">

    <!-- Latest compiled and minified JavaScript -->
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script>
    <style>
      body {
        padding-top: 50px;
      }
      .starter-template {
        padding: 40px 15px;
      text-align: center;
      }
    </style>
  </head>
  <body>
    <div class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
      <button type="button" class="navbar-toggle"data-toggle="collapse" data-target=".nav-collapse">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="/">Awesome Albums</a>
      <div class="nav-collapse collapse">
        <ul class="nav navbar-nav">
          <li><a href="{{URL::route('create_album_form')}}">Create New Album</a></li>
        </ul>
      </div><!--/.nav-collapse -->
    </div>
    </div>

      <div class="container">

        <div class="starter-template">

        <div class="row">
          @foreach($albums as $album)
            <div class="col-lg-3">
              <div class="thumbnail" style="min-height: 514px;">
                <img alt="{{$album->name}}" src="/albums/{{$album->cover_image}}">
                <div class="caption">
                  <h3>{{$album->name}}</h3>
                  <p>{{$album->description}}</p>
                  <p>{{count($album->Photos)}} image(s).</p>
                  <p>Created date:  {{ date("d F Y",strtotime($album->created_at)) }} at {{date("g:ha",strtotime($album->created_at)) }}</p>
                  <p><a href="{{URL::route('show_album', array('id'=>$album->id))}}" class="btn btn-big btn-default">Show Gallery</a></p>
                </div>
              </div>
            </div>
          @endforeach
        </div>

      </div><!-- /.container -->
    </div>

  </body>
</html>

添加创建相册的模板

正如您在下面的代码中看到的,我们更喜欢使用 Twitter 的 bootstrap CSS 框架。这个框架允许你快速创建有用的、有响应的和多浏览器支持的界面。接下来,我们需要创建一个创建相册的模板。要创建它,请将以下代码保存为app/views/目录中的createalbum.blade.php:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Create an Album</title>
    <!-- Latest compiled and minified CSS -->
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css" rel="stylesheet">

    <!-- Latest compiled and minified JavaScript -->
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script>
  </head>
  <body>
    <div class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <button type="button" class="navbar-toggle"data-toggle="collapse" data-target=".nav-collapse">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span lclass="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="/">Awesome Albums</a>
        <div class="nav-collapse collapse">
          <ul class="nav navbar-nav">
            <li class="active"><ahref="{{URL::route('create_album_form')}}">CreateNew Album</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </div>
    <div class="container" style="text-align: center;">
      <div class="span4" style="display: inline-block;margin-top:100px;">

        @if($errors->has())
          <div class="alert alert-block alert-error fade in"id="error-block">
             <?php
             $messages = $errors->all('<li>:message</li>');
            ?>
            <button type="button" class="close"data-dismiss="alert">×</button>

            <h4>Warning!</h4>
            <ul>
              @foreach($messages as $message)
                {{$message}}
              @endforeach

            </ul>
          </div>
        @endif

        <form name="createnewalbum" method="POST"action="{{URL::route('create_album')}}"enctype="multipart/form-data">
          <fieldset>
            <legend>Create an Album</legend>
            <div class="form-group">
              <label for="name">Album Name</label>
              <input name="name" type="text" class="form-control"placeholder="Album Name"value="{{Input::old('name')}}">
            </div>
            <div class="form-group">
              <label for="description">Album Description</label>
              <textarea name="description" type="text"class="form-control" placeholder="Albumdescription">{{Input::old('descrption')}}</textarea>
            </div>
            <div class="form-group">
              <label for="cover_image">Select a Cover Image</label>
              {{Form::file('cover_image')}}
            </div>
            <button type="submit" class="btnbtn-default">Create!</button>
          </fieldset>
        </form>
      </div>
    </div> <!-- /container -->
  </body>
</html>

该模板创建一个基本的上传表单,并显示从控制器端传来的验证错误。我们只需要一个模板文件来列出相册图像。因此,要创建它,请将以下代码保存为app/views/目录中的album.blade.php:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>{{$album->name}}</title>
    <!-- Latest compiled and minified CSS -->
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css" rel="stylesheet">

    <!-- Latest compiled and minified JavaScript -->
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script>
    <style>
      body {
        padding-top: 50px;
      }
      .starter-template {
        padding: 40px 15px;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <div class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <button type="button" class="navbar-toggle"data-toggle="collapse" data-target=".nav-collapse">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="/">Awesome Albums</a>
        <div class="nav-collapse collapse">
          <ul class="nav navbar-nav">
            <li><a href="{{URL::route('create_album_form')}}">Create New Album</a></li>
          </ul>
        </div><!--/.nav-collapse -->
     </div>
    </div>
    <div class="container">

      <div class="starter-template">
        <div class="media">
          <img class="media-object pull-left"alt="{{$album->name}}" src="/albums/{{$album->cover_image}}" width="350px">
          <div class="media-body">
            <h2 class="media-heading" style="font-size: 26px;">Album Name:</h2>
            <p>{{$album->name}}</p>
          <div class="media">
          <h2 class="media-heading" style="font-size: 26px;">AlbumDescription :</h2>
          <p>{{$album->description}}<p>
          <a href="{{URL::route('add_image',array('id'=>$album->id))}}"><button type="button"class="btn btn-primary btn-large">Add New Image to Album</button></a>
          <a href="{{URL::route('delete_album',array('id'=>$album->id))}}" onclick="return confirm('Are yousure?')"><button type="button"class="btn btn-danger btn-large">Delete Album</button></a>
        </div>
      </div>
    </div>
    </div>
      <div class="row">
        @foreach($album->Photos as $photo)
          <div class="col-lg-3">
            <div class="thumbnail" style="max-height: 350px;min-height: 350px;">
              <img alt="{{$album->name}}" src="/albums/{{$photo->image}}">
              <div class="caption">
                <p>{{$photo->description}}</p>
                <p><p>Created date:  {{ date("d F Y",strtotime($photo->created_at)) }} at {{ date("g:ha",strtotime($photo->created_at)) }}</p></p>
                <a href="{{URL::route('delete_image',array('id'=>$photo->id))}}" onclick="return confirm('Are you sure?')"><button type="button" class="btnbtn-danger btn-small">Delete Image </button></a>
              </div>
            </div>
          </div>
        @endforeach
      </div>
    </div>

  </body>
</html>

大家可能还记得,我们在模型方面使用了hasMany()雄辩法。在控制器端,我们使用如下函数:

$albums = Album::with('Photos')->get();

代码获取属于相册的数组中的整个图像数据。因此,我们在下面的模板中使用foreach循环:

@foreach($album->Photos as $photo)
  <div class="col-lg-3">
    <div class="thumbnail" style="max-height: 350px;min-height: 350px;">
    <img alt="{{$album->name}}" src="/albums/{{$photo->image}}">
      <div class="caption">
        <p>{{$photo->description}}</p>
        <p><p>Created date:  {{ date("d F Y",strtotime($photo->created_at)) }} at {{ date("g:ha",strtotime($photo->created_at)) }}</p></p>
        <a href="{{URL::route('delete_image',array('id'=>$photo->id))}}" onclick="return confirm('Are yousure?')"><button type="button" class="btnbtn-danger btn-small">Delete Image</button></a>
      </div>
    </div>
  </div>
@endforeach

创建照片上传表单

现在我们需要创建一个照片上传表单。我们将上传照片并将其分配到相册中。我们先定路线;打开app文件夹中的routes.php文件,并添加以下代码:

Route::get('/addimage/{id}', array('as' => 'add_image','uses' => 'ImagesController@getForm'));
Route::post('/addimage', array('as' => 'add_image_to_album','uses' => 'ImagesController@postAdd'));
Route::get('/deleteimage/{id}', array('as' => 'delete_image','uses' => 'ImagesController@getDelete'));

我们需要一个照片上传表单的模板。要创建它,请将以下代码保存为app/views/目录中的addimage.blade.php:

<!doctype html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>Laravel PHP Framework</title>
    <!-- Latest compiled and minified CSS -->
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css" rel="stylesheet">

    <!-- Latest compiled and minified JavaScript -->
    <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script>
  </head>
  <body>

    <div class="container" style="text-align: center;">
      <div class="span4" style="display: inline-block;margin-top:100px;">
        @if($errors->has())
          <div class="alert alert-block alert-error fade in"id="error-block">
            <?php
            $messages = $errors->all('<li>:message</li>');
            ?>
            <button type="button" class="close"data-dismiss="alert">×</button>

            <h4>Warning!</h4>
            <ul>
              @foreach($messages as $message)
                {{$message}}
              @endforeach

            </ul>
          </div>
        @endif
        <form name="addimagetoalbum" method="POST"action="{{URL::route('add_image_to_album')}}"enctype="multipart/form-data">
          <input type="hidden" name="album_id"value="{{$album->id}}" />
          <fieldset>
            <legend>Add an Image to {{$album->name}}</legend>
            <div class="form-group">
              <label for="description">Image Description</label>
              <textarea name="description" type="text"class="form-control" placeholder="Imagedescription"></textarea>
            </div>
            <div class="form-group">
              <label for="image">Select an Image</label>
              {{Form::file('image')}}
            </div>
            <button type="submit" class="btnbtn-default">Add Image!</button>
          </fieldset>
        </form>
      </div>
    </div> <!-- /container -->
  </body>
</html>

在创建模板之前,我们需要对我们的控制器进行编码。因此,将以下代码保存为app/controllers/目录中的ImageController.php:

<?php
class ImagesController extends BaseController{

  public function getForm($id)
  {
    $album = Album::find($id);
    return View::make('addimage')
    ->with('album',$album);
  }

  public function postAdd()
  {
    $rules = array(

      'album_id' => 'required|numeric|exists:albums,id',
      'image'=>'required|image'

    );

    $validator = Validator::make(Input::all(), $rules);
    if($validator->fails()){

      return Redirect::route('add_image',array('id' =>Input::get('album_id')))
      ->withErrors($validator)
      ->withInput();
    }

    $file = Input::file('image');
    $random_name = str_random(8);
    $destinationPath = 'albums/';
    $extension = $file->getClientOriginalExtension();
    $filename=$random_name.'_album_image.'.$extension;
    $uploadSuccess = Input::file('image')->move($destinationPath, $filename);
    Image::create(array(
      'description' => Input::get('description'),
      'image' => $filename,
      'album_id'=> Input::get('album_id')
    ));

    return Redirect::route('show_album',array('id'=>Input::get('album_id')));
  }
  public function getDelete($id)
  {
    $image = Image::find($id);
    $image->delete();
    return Redirect::route('show_album',array('id'=>$image->album_id));
  }
}

控制器有三个功能;第一个是getForm()功能。这个功能基本上展示了我们的照片上传表单。第二个验证并将数据插入数据库。我们将在下一节解释验证和插入函数。第三个是getDelete()功能。这个函数基本上从数据库中删除图像记录。

验证照片

Laravel 有一个强大的验证库,这在本书中已经多次提到。我们验证控制器中的数据如下:

$rules = array(

  'album_id' => 'required|numeric|exists:albums,id',
  'image'=>'required|image'

);

$validator = Validator::make(Input::all(), $rules);
if($validator->fails()){

  return Redirect::route('add_image',array('id' =>Input::get('album_id')))
  ->withErrors($validator)
  ->withInput();
}

让我们检查一下代码。我们在array中定义了一些规则。我们在rules数组中有两个验证规则。第一条规则如下:

'album_id' => 'required|numeric|exists:albums,id'

前面的规则意味着album_id字段是必需的(必须在表单中发布),它必须是一个数值,并且必须存在于albums表的id列中,因为我们想要将图像分配给albums。第二条规则如下:

'image'=>'required|image'

前面的规则意味着image字段是必需的(必须在表单中发布),其内容必须是图像。然后,我们使用以下代码检查发布的表单数据:

$validator = Validator::make(Input::all(), $rules);

验证函数需要两个变量。第一个是我们需要验证的数据。在这种情况下,我们使用Input::all()方法进行设置,这意味着我们需要验证发布的表单数据。第二个是rules变量。rules变量必须设置为数组,如下代码所示:

$rules = array(

  'album_id' => 'required|numeric|exists:albums,id',
  'image'=>'required|image'

);

Laravel 的验证类带有许多预定义的规则。您可以在http://laravel . com/docs/validation # available-validation-rules上看到所有可用验证规则的更新列表。

有时候,我们只需要验证特定的 MIME 类型,比如JPEG, BMP, ORG, and PNG。您可以轻松地为这种验证设置验证规则,如以下代码所示:

'image' =>'required|mimes:jpeg,bmp,png'

然后,我们使用以下代码检查验证过程:

if($validator->fails()){

  return Redirect::route('add_image',array('id' =>Input::get('album_id')))
  ->withErrors($validator)
  ->withInput();
}

如果验证失败,我们将浏览器重定向到图像上传表单。然后,我们使用以下代码显示模板文件中的规则:

@if($errors->has())
  <div class="alert alert-block alert-error fade in"id="error-block">
    <?php
    $messages = $errors->all('<li>:message</li>');
    ?>
    <button type="button" class="close"data-dismiss="alert">×</button>

    <h4>Warning!</h4>
    <ul>
      @foreach($messages as $message)
        {{$message}}
      @endforeach

    </ul>
  </div>
@endif

为相册分配照片

postAdd( )功能用于处理在数据库中创建新图像记录的请求。我们使用前面提到的方法获得作者的身份:

Auth::user()->id

使用下面的方法,我们将博客文章分配给当前用户。我们在查询中有一个新方法,如下面的代码所示:

Posts::with('Author')->…

我们在相册模型中使用以下代码定义了一个public Photos ()函数:

public function Photos(){

  return $this->hasMany('images','album_id');
}

hasMany()方法是一个在表之间创建关系的功能。基本上,函数有一个required变量和一个可选变量。第一个变量(required)用于定义目标模型。第二个变量是可选变量,用于定义当前模型表的源列。在这种情况下,我们将相册的标识存储在images表的album_id列中。正因为如此,我们需要在函数中将第二个变量定义为album_id。第二个参数只有在你的身份证不符合惯例的情况下才需要。使用这种方法,我们可以将相册的信息和分配的图像数据同时传递给模板。

第四章建立个人博客中可以记得,我们可以列出foreach循环中的关系数据。让我们快速查看一下模板文件中代码的图像列表部分,它位于app/views/ album.blade.php:

@foreach($album->Photos as $photo)

  <div class="col-lg-3">
    <div class="thumbnail" style="max-height: 350px;min-height: 350px;">
    <img alt="{{$album->name}}" src="/albums/{{$photo->image}}">
      <div class="caption">
        <p>{{$photo->description}}</p>
        <p><p>Created date:  {{ date("d F Y",strtotime($photo->created_at)) }} at {{ date("g:ha",strtotime($photo->created_at)) }}</p></p>
        <a href="{{URL::route('delete_image',array('id'=>$photo->id))}}" onclick="return confirm('Are yousure?')"><button type="button" class="btnbtn-danger btn-small">Delete Image</button></a>
      </div>
    </div>
  </div>

@endforeach

在相册之间移动照片

在相册之间移动照片是管理相册图像的一大特色。许多照片库系统都带有这个功能。所以,我们可以很容易地用 Laravel 进行编码。我们需要一个表单和控制器功能来添加这个功能到我们的照片库系统。让我们先对控制器功能进行编码。打开位于app/controllers/ImagesController.php文件,并在其中添加以下代码:

public function postMove()
{
  $rules = array(

    'new_album' => 'required|numeric|exists:albums,id',
    'photo'=>'required|numeric|exists:images,id'

  );

  $validator = Validator::make(Input::all(), $rules);
  if($validator->fails()){

    return Redirect::route('index');
  }
  $image = Image::find(Input::get('photo'));
  $image->album_id = Input::get('new_album');
  $image->save();
  return Redirect::route('show_album',array('id'=>Input::get('new_album')));
}

正如您在前面的代码中看到的,我们再次使用了Validation类。让我们检查一下规则。第一条规则如下:

'new_album' => 'required|numeric|exists:albums,id'

前面的规则意味着new_album字段是required(必须以表格形式发布),必须是数值,并且存在于albums表的id列中。我们想给相册分配图片,所以图片必须存在。第二条规则如下:

'photo'=>'required|numeric|exists:images,id'

前面的规则意味着photo字段是required(必须以表格形式发布),必须是数值,并且存在于images表的id列中。

验证成功后,我们更新photos字段的album_id列,并使用以下代码重定向浏览器以显示新的相册:

$image = Image::find(Input::get('photo'));
$image->album_id = Input::get('new_album');
$image->save();
return Redirect::route('show_album',array('id'=>Input::get('new_album')));

Images控制器的最终代码如下:

<?php

class ImagesController extends BaseController{

  public function getForm($id)
  {
    $album = Album::find($id);

    return View::make('addimage')
    ->with('album',$album);
  }

  public function postAdd()
  {
    $rules = array(

      'album_id' => 'required|numeric|exists:albums,id',
      'image'=>'required|image'

    );

    $validator = Validator::make(Input::all(), $rules);
    if($validator->fails()){

      return Redirect::route('add_image',array('id' =>Input::get('album_id')))
      ->withErrors($validator)
      ->withInput();
    }

    $file = Input::file('image');
    $random_name = str_random(8);
    $destinationPath = 'albums/';
    $extension = $file->getClientOriginalExtension();
    $filename=$random_name.'_album_image.'.$extension;
    $uploadSuccess = Input::file('image')->move($destinationPath, $filename);
    Image::create(array(
      'description' => Input::get('description'),
      'image' => $filename,
      'album_id'=> Input::get('album_id')
    ));

    return Redirect::route('show_album',array('id'=>Input::get('album_id')));
  }
  public function getDelete($id)
  {
    $image = Image::find($id);

    $image->delete();

    return Redirect::route('show_album',array('id'=>$image->album_id));
  }
  public function postMove()
  {
    $rules = array(
      'new_album' => 'required|numeric|exists:albums,id',
      'photo'=>'required|numeric|exists:images,id'
    );
    $validator = Validator::make(Input::all(), $rules);
    if($validator->fails()){

      return Redirect::route('index');
    }
    $image = Image::find(Input::get('photo'));
    $image->album_id = Input::get('new_album');
    $image->save();
    return Redirect::route('show_album',array('id'=>Input::get('new_album')));
  }
}

我们的控制器已经准备好了,所以我们需要在app/routes.php中设置更新表单的路线。打开文件并添加以下代码:

Route::post('/moveimage', array('as' => 'move_image', 'uses' => 'ImagesController@postMove'));

位于app/routes.php的最终代码应该如下所示:

<?php
Route::get('/', array('as' => 'index', 'uses' =>
  'AlbumsController@getList'));
Route::get('/createalbum', array('as' => 'create_album_form',
  'uses' => 'AlbumsController@getForm'));
Route::post('/createalbum', array('as' => 'create_album',
  'uses' => 'AlbumsController@postCreate'));
Route::get('/deletealbum/{id}', array('as' => 'delete_album',
  'uses' => 'AlbumsController@getDelete'));
Route::get('/album/{id}', array('as' => 'show_album', 'uses' =>
  'AlbumsController@getAlbum'));
Route::get('/addimage/{id}', array('as' => 'add_image', 'uses' =>
  'ImagesController@getForm'));
Route::post('/addimage', array('as' => 'add_image_to_album',
  'uses' => 'ImagesController@postAdd'));
Route::get('/deleteimage/{id}', array('as' => 'delete_image',
'uses' => 'ImagesController@getDelete'));
Route::post('/moveimage', array('as' => 'move_image',
'uses' => 'ImagesController@postMove'));

创建更新表单

现在我们需要在我们的模板文件中创建我们的更新表单。打开位于app/views/ album.blade.php的模板文件,如下改变foreach循环:

@foreach($album->Photos as $photo)
  <div class="col-lg-3">
    <div class="thumbnail" style="max-height: 350px;min-height: 350px;">
      <img alt="{{$album->name}}" src="/albums/{{$photo->image}}">
      <div class="caption">
        <p>{{$photo->description}}</p>
        <p>Created date:  {{ date("d F Y",strtotime($photo->created_at)) }}at {{ date("g:ha",strtotime($photo->created_at)) }}</p>
        <a href="{{URL::route('delete_image',array('id'=>$photo->id))}}" onclick="returnconfirm('Are you sure?')"><button type="button"class="btn btn-danger btn-small">Delete Image</button></a>
        <p>Move image to another Album :</p>
        <form name="movephoto" method="POST"action="{{URL::route('move_image')}}">
          <select name="new_album">
            @foreach($albums as $others)
              <option value="{{$others->id}}">{{$others->name}}</option>
            @endforeach
          </select>
          <input type="hidden" name="photo"value="{{$photo->id}}" />
          <button type="submit" class="btn btn-smallbtn-info" onclick="return confirm('Are you sure?')">Move Image</button>
        </form>
      </div>
    </div>
  </div>
@endforeach

总结

在这一章中,我们创建了一个简单的照片库系统,其中包含了 Laravel 的内置功能和雄辩的数据库驱动程序。我们已经学习了如何验证数据,以及在名为 Hasmooth 的雄辩中强大的数据关系方法。在接下来的章节中,我们将学习如何处理更复杂的表、关系数据和关系类型。