laravel — 画像保存のアプリ

カモメのススメ」というサイトを参考させて頂きました。

プロジェクの作成と基本的な設定

プロジェクトを作成します。


composer create-project laravel/laravel imgup

「imgdb」というデータベースを作成して、.env を編集します。

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=imgdb
DB_USERNAME=root
DB_PASSWORD=pass

migration ファイルを作成します。


php artisan make:migration create_images_table --create=images

migration ファイルを編集します。

database/migrations/******_create_images_table

    public function up()
    {
        Schema::create('images', function (Blueprint $table) {
            $table->id();
            $table->string('img_path');
            $table->timestamps();
        });
    }

migration。


php artisan migrate

データベースとテーブルの項目を確認します。

model の作成と編集


php artisan make:model Image
app/Models/Image.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Image extends Model
{
    use HasFactory;

    protected $table = 'images';
    protected $fillable = [
        'img_path',
    ];
}

controller の作成と編集


php artisan make:controller ImageController
app/Http/Controllers/ImageController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Image;

class ImageController extends Controller
{
	public function index()
	{
		$items = Image::get();
		return view('item.index', compact('items'));
	}

	public function create(Request $request)
	{
		return view('item.create');
	}

	public function store(Request $request)
	{
		$img = $request->file('img_path');
		if (isset($img)) 
		{
			$path = $img->store('img','public');
			if ($path) 
			{
				Image::create([
					'img_path' => $path,
				]);
			}
		}
		return redirect()->route('item.index');
	}
}

view ファイルの作成

「resources/views」の中に item というディレクトリを作成し、その中に 2 つのファイルを新規作成します。

resources/views/item/index.blade.php

<h1>一覧画面</h1>
@foreach ($items as $item)
    <img src="{{ Storage::url($item->img_path) }}" width="25%">
@endforeach
resources/views/item/create.blade.php

<form action="{{ route('item.store') }}" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="img_path">
<input type="submit" value="アップロード">
</form>

routing

routes/web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ImageController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', [ImageController::class, 'index'])->name('item.index');
Route::get('/create', [ImageController::class, 'create'])->name('item.create');
Route::post('/store', [ImageController::class, 'store'])->name('item.store');

画像保存ディレクトリへのシンボリックリンクを作成

laravel では、画像は public フォルダから見える場所に置くというルールがあるようで、通常はシンボリックリンクを作成する習わしになっているようです。


php artisan storage:link

起動と画像の保存

起動。


cd ~/imgup
php artisan serve

127.0.0.1:8000/create」にアクセス。

参照ボタンで画像を選択してアップロードします。

画像を閲覧

127.0.0.1:8000」にアクセスするとアップロードした画像が一覧できます。

問題点

画像のファイリング方法は django と違って、一括して保存されます。

django みたいに「年/月/日」のディレクトリが作成されて、その中に保存された方がいいような気がします。

………..

ImageController.php の保存先を以下のように変更すれば django と同じような構造で保存できます。

app/Http/Controllers/ImageController.php

<?php

	public function store(Request $request)
	{
		$img = $request->file('img_path');
		if (isset($img)) 
		{
			$stockdir = date("Y/m/d") ;#変更部分
			$path = $img->store($stockdir,'public');#変更部分
			if ($path) 
			{
				Image::create([
					'img_path' => $path,
				]);
			}
		}
		return redirect()->route('item.index');
	}

こうすると以下のような構造になります。


public
└── 2022
    └── 11
        └── 22
            ├── AKAMpACQBlNQ8zMqCRsjeqMKXAqLa1T5tALogHfO.jpg
            ├── FhDFTsTh66hdk7pxo2TLK2FsslYtoO5OOzJ0w7X9.jpg
            └── kWWPkZk9u9fNr2LymqIde5YsYxfl59imvmw4grQq.jpg

もちろん、データベースの内容もきちんとパスが記録されています。