WinRoadのLaravel4初心者講座

次世代PHPフレームワークのLaravel4を初心者向けに解説して参ります。

Winroad徒然草の管理人がお届けします
ブログ
このエントリーをはてなブックマークに追加

ブログ一覧

ファイルをデータベースに保管する

今日は、画像ファイルやPDFファイルなどをデータベースに保管する方法をご紹介します。

  1. テーブルにバイナリデータ保管用のカラムとMIMEタイプ保管用のカラムを作成します。
  2. アップロード用のビューファイルから送信されたファイルをInput::file(‘file’)で取得します。
  3. Input::file(‘file’)->getMimeType()でMimeタイプを取得します。
  4. file_get_contents(Input::file(‘file’))で、ファイル本体を取得します。
  5. いったんデータベーステーブルに保存します。
  6. 画像ファイルを表示するために、idから取得します。
  7. バイナリデータをbase64でエンコードします。
  8. 表示用のビューファイルに、base64でエンコードした画像本体とMIMEタイプを送信します。
  9. 表示用のビューファイルのimgタグでブラウザ上に表示します。

それでは、実際に作成してみましょう。まず、最初にデータ保管用のテーブル(cabinets)を作成します。

<?php
class SetupController extends BaseController{
 public function getCabinets(){
 //cabinetsテーブルの存在確認
 if(Schema::hasTable('cabinets')){
 $data['warning']='cabinetsテーブルはあります。';
 return View::make('setup.index',$data);
 }
 //cabinetsテーブルの作成
 Schema::create('cabinets',function($table){
 $table->increments('id');
 //genbaテーブルへのリレーション用
 $table->integer('G_id')->nullable();
 //name
 $table->string('name',100)->nullable();
 //MIMEタイプの保存
 $table->string('mime',50)->nullable();
 //publicフォルダ用保存域パス
 $table->string('path',100)->nullable();
 //データ保管庫
 $table->binary('data')->nullable();
 //created_atとupdated_atの同時作成
 $table->timestamps();
 //deleted_atカラムを追加
 $table->timestamp('deleted_at')->nullable();
 });
 $data['warning']='cabinetsテーブルを作成しました。';
 return View::make('setup.index',$data);
 }
}

※データベーステーブル作成用のコントローラです。とりあえす、id,mime,dataカラムがあれば、問題ありません。

17行目:publicフォルダにファイルを保管するための保存パスの登録用カラムです。こちらに保管する方が簡単なのですが、今回は、データベースに直接フィルを保存する方法をご紹介します。

19行目:画像データやPDFファイルなどをデータベースに保管するには、データ種別をバイナリで保管します。※スキーマビルダーでは、$table->vinary()で、BLOBカラムを作成しますが、大きめのファイルも保管するのでしたら、LONGBLOBを使用した方がいいでしょう。尚、MEDIUMBLOBやLONGBLOBは、スキーマビルダーでは作成できません。

2015-02-14 22-49-13

次にモデルを作成します。モデルは特に問題はありませんが、念のために記述しておきます。

<?php
class Cabinet extends Eloquent{
 //テーブル名がcabinets(複数形)なら省略可
 protected $table='cabinets';
 //primaryKeyがidなら省略可
 protected $primaryKey='id';
 //複数代入の制限
 protected $guarded=['id','created_at','updated_at','deleted_at'];
 //ソフトデリートを使用
 protected $softDelete=true;
}

コントローラを作成します。

<?php
class CabinetController extends BaseController {
  //一覧表の表示
 public function getIndex(){
 $cabinets=Cabinet::orderBy('created_at','desc')->get();
 return View::make('cabinet.index',compact('cabinets'));
 }
 
 //アップロードデータの作成用ビュー
 public function getCreate($id=null){
 $genba=Genba::find($id);
 return View::make('cabinet.create',compact('genba'));
 }
 //ファイルのアップロード処理
 public function postCreate(){
 //ファイルのアップロード確認
 if(!Input::hasFile('file')){
 return Redirect::back()
 ->with('warning','<div class="uk-alert uk-alert-danger">ファイルがアップされていません</div>');
 }
 //アップロードファイルを取得
 $file=Input::file('file');
 //return var_dump($file);
 $name=date('YmdHis.').$file->getClientOriginalExtension();
 //新規データの作成
 $cabinet=new Cabinet;
 $cabinet->G_id=Input::get('G_id');
 $cabinet->name=Input::get('name');
 //テーブルのdataカラムにバイナリデータで保存
 $cabinet->data=file_get_contents($file);
 $cabinet->mime=$file->getMimeType();
 $cabinet->path='images/'.$name;
 $cabinet->save();
 //publicフォルダに保存
 $file->move('images/',$name);
 return Redirect::to('cabinet/view/'.$cabinet->id);
 }
 //画像ファイルをブラウザに表示する為の準備
 public function getView($id){
 //データベースに保存してあるデータを取得
 $file=Cabinet::find($id);
 //バイナリデータをbase64でエンコード
 $data['base64']=base64_encode($file->data);
 //mimeタイプを取得
 $data['mime']=$file->mime;
 return View::make('cabinet.view',$data);
 }

※31行目:file_get_contents()関数で、アップロードしたファイルを保存します。

ファイルのアップロード用ビューファイルを作成します。

@extends('uk.base')
 @section('content')
 <h3 class="menuTab">現場資料のアップデート</h3>
 {{ Session::get('warning') }}
 {{ Form::open(['files'=>'true','class'=>'uk-form uk-form-horizontal']) }}
<div class="uk-form-row">
 {{ Form::label('name','現場名',['class'=>'uk-form-label uk-form-large']) }}
 {{Form::text('name',$genba->name,['class'=>'uk-form-width-large','disabled'=>'disabled'])}}
 </div>
   <div class="uk-form-row">
 {{ Form::label('path','保存パス',['class'=>'uk-form-label']) }}
 {{Form::text('path','',['class'=>'uk-form-width-large'])}}
 </div>
 <div class="uk-form-row">
 {{ Form::label('item','ファイル種別',['class'=>'uk-form-label']) }}
 {{Form::text('item','',['class'=>'uk-form-width-large'])}}
 </div>
<div class="uk-form-row">
 {{ Form::label('file','保存ファイル',['class'=>'uk-form-label']) }}
 {{ Form::file('file') }}
 </div>
<hr>
{{ Form::hidden('name',$genba->name) }}
 {{ Form::hidden('G_id',$genba->id) }}
 {{ Form::submit('アップロード',['class'=>'uk-button uk-button-primary uk-width-1-2'] )}}
{{ Form::close() }}
 @stop

画像表示用のビューファイルです。

@extends('uk.base')
 @section('content')
 <h1>Cabinet</h1>
 <div class="uk-thumnail uk-thumnail-large">
 <img src='data:{{$mime}};base64,{{$base64}}'>
 </div>
 @stop

※<img src=”data:img/png;base64,base64_encode(バイナリデータ)”>で、データベーステーブルに保存したバイナリデータを表示します。

Laravel5(開発版)のインストール

今月中にリリース予定のLaravel5ですが、待ちきれないので、開発版をインストールして試してみたいと思います。

インストール

  1. まず、コマンドプロンプトを起動したら、下記のコマンドを入力します。
    • composer create-project laravel/laravel C:\xampp\htdocs\laravel dev-develop
    • 上記のC:\xampp\htdocs\laravelには、インストールしたいフォルダ名(場所)を指定します。
  2. laravel5は、フォルダ構成が大幅に変更になっています。
  3. ルートフォルダ(laravel直下のトップフォルダ)内には、app、bootstrap、config、database、public、resources、strage、tests、vendorがあります。
  4. appフォルダ内には、Console、Http、Providersフォルダがあります。
  5. そして、Httpフォルダの中に、Controllers、Middleware、Requestsフォルダと、kernel.phpファイルとroutes.phpファイルがあります。
    • 2014-11-06 10-24-02
  6. laravel4とは、大幅に変更されていますので、最初は戸惑います。また、リリースまでにさらに変更になる可能性もあります。※ほんの1週間前までは、routes.phpファイルすらありませんでした。

ルーティング

  1. まず、気になるのが、ルーティングですが、app/Http/routes.phpファイルでルーティングを指定します。
  2. デフォルトのroues.phpの中身を見てみましょう。
    • <?php
      $router->get('/', 'HomeController@index');
      $router->controller('auth', 'AuthController');
      $router->controller('password', 'PasswordController');
  3. デフォルトでは、3つのルーティングが指定されています。
  4. まず、トップページの指定ですが、HomeControllerのindexメソッドが指定されています。
  5. そして、AuthControllerと、PasswordControllerがレストフルコントローラとして指定されています。
  6. Laravel4では、下記のような指定になるはずですので、違いを確認して下さい。
    • <?php
      Route::get('/', 'HomeController@index');
      Route::controller('auth','AuthController');
      Route::controller('password','PasswordController');

コントローラ

  1. それでは、コントローラの中身を確認してみましょう。下記のようになっています。
    • <?php namespace App\Http\Controllers;
      class HomeController extends Controller {
      public function Index()
      {
       return view('hello');
       }
      }
  2. まず、一番の違いは、名前空間の指定です。laravel4では、コントローラは名前空間を指定する必要が無かったのですが、laravel5からは、名前空間の指定が必須になるようです。
  3. 試しに、<?php //namespace App\Http\Controllers; と、名前空間の指定箇所をコメントアウトしてみると、下記のようにエラーが表示されます。
    • 2014-11-06 10-57-50
  4. そして、ビューの指定ですが、View::make()では、なくて、view()に変更になっています。
  5. ここもView::make(‘hello’)に変更してみると、下記のようなエラーが表示されます。
    • 2014-11-06 11-03-30
  6. つまり、「Viewクラスが、App\Http\Controllersフォルダ内に見つかりません。」と表示されます。
  7. Laravel4のようにViewクラスを使うには、use演算子で指定(インポート)する必要があります。つまり、下記のように修正すれば、Viewクラスのmakeメソッドが使えるようになります。
    • <?php namespace App\Http\Controllers;
       use Illuminate\Support\Facades\View;
       class HomeController extends Controller {
       public function Index()
       {
       //return view('hello');
       return View::make('hello');
       }
       }

ビュー

  1. ビューの場所は、resourcesフォルダ内に移動になっています。resourcesフォルダ内には、assetsフォルダ、langフォルダとviewsフォルダがあります。
  2. ビューに関しては、場所が変更になった程度で他に特段明記するような変更は無いように思われます。

モデル

  1. モデルに関してですが、laravel4のようにモデルだけを格納しておくようなフォルダはなくなったようです。モデルは、好きなように好きな場所に作成して下さいと言うことでしょうか。
  2. モデルの例として、app/User.phpファイルが作成されていますので、中身を確認してみましょう。
    • <?php namespace App;
      use Illuminate\Auth\UserTrait;
      use Illuminate\Database\Eloquent\Model;
      use Illuminate\Contracts\Auth\User as UserContract;
      use Illuminate\Auth\Passwords\CanResetPasswordTrait;
      use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
      use Illuminate\Database\Eloquent\SoftDeletingTrait;
      class User extends Model implements UserContract, CanResetPasswordContract {
      use UserTrait, CanResetPasswordTrait, SoftDeletingTrait;
      /**
       * The database table used by the model.
       *
       * @var string
       */
       protected $table = 'users';
      /**
       * The attributes excluded from the model's JSON form.
       *
       * @var array
       */
       protected $hidden = ['password', 'remember_token'];
       protected $dates = ['deleted_at'];
       
      }
    • 7行目と22行目は、ソフトデリートを使用するために、私が追加しました。
  3. まず、Laravel5では、名前空間は必須ですので、namespace App;で現在のファイルのある場所を指定します。
  4. そして、このUserモデルで使用するクラスやトレイトをuse演算子で指定します。
  5. 尚、このUserモデルを試しにHomeControllerで使用してみます。HomeControllerを下記のように修正します。
    • <?php namespace App\Http\Controllers;
      use App\User;
      class HomeController extends Controller {
      public function Index()
       {
       $user=User::find(1);
       return view('hello',compact('user'));
       }
      }
    • Userモデルを使用するには、2行目のuse演算子が必要になってきます。尚、2行目のuse演算子を使用しないで、6行目を下記のように記述してもOKです。
    • $user=\App\User::find(1);
  6. そして、app/resources/views/hello.phpファイルの<h1>You have arrived.</h1>を<h2>ようこそ<?php echo $user->name;?>さん</h2>と変更したら下記のように表示されます。
    • 2014-11-06 12-04-44

まだ、さわり程度ですが、使ってみた感想は、Laravel4に比べてコードの記述量が増えています。しかし、Laravelの特徴であった記述の簡易さを多少犠牲にしてでも自由度を追求した結果でしょうか。好みの分かれるところだと思いますが、私としては歓迎しています。いまからリリースが楽しみです。

Laravel Excelでシート内の操作

Laravel Excelのシート内の操作方法を調べてみたいと思います。

行の操作

Laravel Excelで行の操作を行うには、rowメソッドを使用します。rowメソッドの第1引数には、指定行、第2引数には、行内のセルの値を配列で指定します。

//1行目のセルに値を代入
 $sheet->row(1,['test1','test2']);
//2行目のセルに値を代入
 $sheet->row(2,['test3,'test4']);

又、指定行のセルのプロパティを変更するには、第2引数にクロージャーでset+プロパティメソッドを指定します。

$sheet->row(1,function($row){
 //1行目のセルの背景色に青を指定
 $row->setBackground('#0000FF');
 //1行目のセルの文字色に白を指定
 $row->setFontColor('#FFFFFF');
 });

行の追加

行を追加するには、appendRowメソッドを使用します。第1引数に指定した行の直後に、第2引数で指定した配列の値のセルを追加します。又、第1引数に行を指定せずに、配列を直接指定すれば、最終行の後に指定した配列の値のセルを挿入します。

//2行目の後に行を追加します。
$sheet->appendRow(2,['test1','test2']);
//最終行の後に行を追加します。
$sheet->appendRow(['test3',test4']);

行の挿入

又、prependRowメソッドを使用すれば、指定した行の直前に行を挿入します。又、上記と同様に第1引数に行を指定しないで、配列を直接指定すれば、最初の行の直前に行を挿入します。

//3行目の直前に指定した値の行を挿入します。
$sheet->prependRow(3,['test1',test2']);
//最初の行の直前に行を挿入します。
$sheet->prependRow(['test3','test4']);

複数行の追加

複数行を追加するには、rowsメソッドを使用します。

$sheet->rows([
['test1',test2'],
['test3','test4']
]);

セルの操作

セルを操作するには、cellメソッドを使用します。cellメソッドの第1引数にはセルの位置、第2引数は、クロージャーを指定します。そして、複数のセルを同時に操作するにはcellsメソッドを使用します。

$sheet->cell('A1',function($cell){
 //ここにセルの操作を記述します。
 });
 #sheet->cells('A1:A5',cunftion($cell){
 //ここに複数のセルの操作を記述します。
 });

セルのプロパティを操作するには、set+プロパティ名メソッドを使用します。

  • 背景色の変更
    $cells->setBackground('#000000');
  • フォントカラーの変更
    $cells->setFontColor('#FFFFFF');
  • フォントの種類の変更
    $cells-&gt;setFontFamily('MS ゴシック');
  • フォントサイズの変更
    $cells->setFontSize(16);
  • フォントの太さの変更
    $cells->FontWeight('bold');
  • フォントの複数のプロパティを同時に変更
    $cells->Font([
     'family' => 'MS明朝',
     'size'  => '16',
     'bold' => true
     ]);
  • 罫線を上、右、下、左の順に指定
    $cells->setBorder('solid','none','none','solid');
  • 罫線の種類の指定を配列で指定
    $cells->setBorder([
     'borders' => [
     'top' => ['style' => 'solid'],
     ]
     ]);
  • セル内の横の配置を指定
    $cells->setAlignment('center');
  • セル内の縦の配置を指定
    $cells->setValignment('middle');

 シートのスタイル変更

シートのスタイルを変更するには、setStyleメソッドを使用します。

$sheet->setStyle([
 'font' => [
 'name' => 'MS明朝',
 'size' => '15',
 'bold' => true
 ]
 ]);

また、シートのフォントをまとめて変更するには、setFont()メソッドを使用し、別々に変更するには、set+プロパティ名メソッドを使用します。

//シートのフォントをまとめて変更
 $sheet->setFont([
 'family' => 'MSゴシック',
 'size' => '15',
 'bold' => true
 ]);
//シート内のフォント種類を変更
 $sheet->setFontFamily('MS明朝');
 //シート内のフォントサイズを変更
 $sheet->setFontSize(15);
 //シート内のフォントの太さを変更
 $sheet->setFontBold(true);
//シート内のすべての罫線をまとめて変更
 $sheet->setAllBorders('thin');
 //シート内のセルの罫線を指定して変更
 $sheet->setBorder('A1','thin');
 //シート内のセルの罫線の範囲を指定して変更
 $sheet->setBorder('A1:F10','thin');

シートのウインドウ枠の固定

シートのウインドウ枠を固定するには、freeze+固定位置メソッドを使用します。

//シートの最初の行を固定します。
 $sheet->freezeFirstRow();
 //シートの最初の列を固定します。
 $sheet->freezeFirstColumn();
 //シートの最初の行と列を固定します。
 $sheet->freezeFirstRowAndColumn();
 //固定位置をセルで指定します。
 $sheet->setFreeze('A2');

オートフィルター

オートフィルターを使用可能にするには、setAutoFilterメソッドを使用します。引数には、オートフィルターを使用する範囲を指定しますが、範囲の指定しない場合は、シート全体にフィルターが適用されます。

//シート全体にオートフィルターを適用する
$sheet->setAutoFilter(); 
 //範囲を指定してオートフィルターを適用する
 $sheet->setAutoFilter('A1:E10');

セルのサイズ変更

セルのサイズを変更するには、setWidth,setHeightメソッドを使用します。setWidthとsetHeightは、それぞれ一つの列や幅を変更するには、第1引数に、列(行)を指定して、第2引数でその値を指定します。また、まとめて指定するには、配列で指定します。

  • セルの幅を変更
    //一つの列の幅を変更する
     $sheet->setWidth('A5',5);
     //複数の行の幅を同時に変更する
     $sheet->setWidth([
     'A' => 5,
     'B' => 10
     ]);
  • セルの高さを変更
    //一つの行の高さを変更する
     $sheet->setHeight(1,50);
     //複数の行の高さを同時に変更する
     $sheet->setHeight([
     1 => 50,
     2 => 25
     ]);

セルのサイズ(幅、高さ)を同時に変更するには、setSizeメソッドを使用します。setSizeメソッドの第1引数には、セルの位置、第2引数には、幅、第3引数には、高さを指定します。また、配列で指定することもできます。

  • 一つのセルのサイズを変更
    $sheet->setSize('A1',500,50);
  • セルのサイズを配列で指定して変更
    $sheet->setSize([
     'A1' => [
     'width' => 50,
     'height' => 500,
     ]
     ]);

オートサイズ

エクスポートされたファイルは、自動的にサイズは設定されています。オートサイズはsetAutoSizeメソッドで、変更することができます。

//オートサイズを有効にする
 $sheet->setAutoSize(true);
 //オートサイズを無効にする
 $sheet->setAutoSize(fale);
 //指定列だけのオートサイズを無効にする
 $sheet->setAutoSize([
 'A','C'
 ]);

 セルの結合

セルを結合するには、mergeCellsメソッドや、setMergeColumnメソッドを使用します。mergeCellsメソッドは、結合するセルの範囲を指定します。

$sheet->mergeCells('A1:E1');

setMergeColumnメソッドは、結合する列や行を配列で指定します。

$sheet->setMergeColumn([
'columns' => ['A','B','C','D'],
'rows => [
[2,3],[5,11]
]
]);

列のフォーマット指定

列のフォーマットを変更するには、setColumnFormatメソッドを使用します。setColumnFormatメソッドは、フォーマット形式を配列で指定します。

//列のフォーマットを%形式に変更
$sheet->setColumnFormat([
'C' => '0%'
]);
$sheet->setColumnFormat([
'A2:K2' => '0000'
]);
$sheet->setColumnFormat([
'B' => '0',
'D' => '0.00',
'E' => '@',
'F' => 'yyyy-mm-dd',
]);

 PHPExcelのメソッド

$excelメソッドや、$sheetメソッドから、PHPExcelのメソッドも呼び出すことができます。

Laravel Excelでシートの作成

Laravel Excelでシートを作成するには、sheetメソッドを使用します。

sheet(‘シート名’,’クロージャー’)

sheetメソッドの第1引数には、シート名、第2引数にはクロージャーを指定します。

Excel::create('filename',function($excel){
 $excel->sheet('sheetname',function($sheet){
 //ここにシートを作成するためのロジックを記述します。
 });
 })->export('xlsx');

また、複数シートの指定もできます。

Excel::create('Filename',function($excel){
 //一つ目のシート
 $excel->sheet('First sheet',function($sheet){
 });
 //二つ目のシート
 $excel->sheet('Second sheet',function($sheet){
 });
 })->export('xlsx');

シートのプロパティ変更

シートのプロパティは、set+プロパティメソッドで、変更することができます。

Excel::create('Filename',function($excel){
 $excel->sheet('Sheetname',function($sheet){
 //印刷方向を横に指定します。
 $sheet->setOrientation('landscape');
 });
 ])->export('xlsx');

ページ余白の設定

シートのページ余白を指定するには、setPageMarginメソッドを使用します。余白の指定方法は、すべての余白を同じ数字にするには、数値で指定し、上下左右別々で指定するには、配列で(上、右、下、左)の順に指定します。

//ページの上、右、下、左の余白を指定します。
 $sheet->setPageMargin(array(
 0.25,0.30,0.25,0.30
 ));
//すべての余白を同じ値で指定します。
 $sheet->setPageMargin(0.25);

※上記余白の値は、インチでの指定ですので、0.25インチは、約0.635センチ、0.30インチは0.762センチになりますので注意して下さい。

尚、app/config/maatwebsite/excel/export.phpの83行の’page_margin’=>false,のfalseの箇所にデフォルトの余白の値をインチ数で指定しておくこともできます。

配列の値でシートの作成

fromArrayメソッドを使用すれば、配列の値で、シートを作成することができます。

fromArray(‘配列データ’,nullの値、セルの開始位置,0の表示の有無,見出し行の有無)

fromArrayの第1引数には、配列の値を指定します。第2引数には、空白セルの指定値?を指定します。第3引数にはセルの開始位置、そして第4引数には、*0を表示するかどうかの指定を行います。第5引数は、セルの見出し行の有無を指定します。

Excel::create('Filename',function($excel){
 $excel->sheet('Sheetname',function($sheet){
 $sheet->fromArray([
 ['data1','data2'],
 ['data3,'data4']
 ]);
 });
 })->export('xlsx');

with()メソッド

fromArrayメソッドの代わりに、withメソッドを使用することもできます。

$sheet->with([
 ['data1,'data2'],
 ['data3,'data4']
 ]);

use($data)

外部からクロージャーに変数を渡したい場合は、use()を使用することができます。

public function getIndex(){
 $data = User::all();
 Excel::create('ユーザー一覧', function($excel) use($data) {
 $excel->sheet('ユーザー一覧', function($sheet) use($data) {
 $sheet->fromArray($data);
 });
 })->export('xlsx');
 }

下記のようなExcelファイルが簡単に作成できます。

2014-08-16 16-34-27

0の値の表示

デフォルトでは、配列データに0の値を指定しても、空白セルと判断して、何も表示されません。そこで、第4引数にtrueを指定することで、0の値を0と判断して、0の文字を表示するようになります。

見出し行の生成の有無

上記の画像でも分かるように、デフォルトでは、モデルの属性名を見出し行として、生成します。見出し行としてモデルの属性名を使用したくないときは、fromArrayメソッドの第5引数にfalseを指定するか、app/config/packages/maatewbsite/excel/export.phpの48行目のtrueをfalseに変更します。

‘generate_heading_by_indices’  => false,

 fromModel(‘モデル名’)

fromModelメソッドを使用すれば、Eloquentモデルからデータを取得することができます。