やりたい事
こんな感じのwordpressライクなエディタを搭載したい。
blade
これでツールバー付きのメニューバーができる。
ドラック&ドロップで画像を登録できます。
blade
{{ Form::textarea('hoge', null) }}
//....
<script src="/js/tinymce/tinymce.min.js"></script>
<script>
tinymce.init({
selector: 'textarea',
language: 'ja',
icons: 'thin',
statusbar: false,
menubar: false,
plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount code',
// ツールバーは好みにカスタマイズ
// toolbar: 'blocks fontsize bold italic underline strikethrough forecolor removeformat | alignleft aligncenter alignright alignjustify | emoticons link image table | numlist bullist | code',
toolbar: 'fontsize bold underline strikethrough forecolor removeformat alignleft aligncenter alignright table emoticons link image code',
block_formats: 'Paragraph=p; Header 1=h3; Header 2=h4; Header 3=h5',
color_map: [
'#BFEDD2', 'Light Green',
'#FBEEB8', 'Light Yellow',
'#F8CAC6', 'Light Red',
'#ECCAFA', 'Light Purple',
'#C2E0F4', 'Light Blue',
'#2DC26B', 'Green',
'#F1C40F', 'Yellow',
'#E03E2D', 'Red',
'#B96AD9', 'Purple',
'#3598DB', 'Blue',
'#169179', 'Dark Turquoise',
'#E67E23', 'Orange',
'#BA372A', 'Dark Red',
'#843FA1', 'Dark Purple',
'#236FA1', 'Dark Blue',
'#ECF0F1', 'Light Gray',
'#CED4D9', 'Medium Gray',
'#95A5A6', 'Gray',
'#7E8C8D', 'Dark Gray',
'#34495E', 'Navy Blue',
'#000000', 'Black',
'#ffffff', 'White',
],
image_title: true,
relative_urls: false,
automatic_uploads: true,
// 画像が貼り付けられるとアクセスするリンク
images_upload_url: '/tinymce?_token={{csrf_token()}}&folder=fugu&id={{$id}}',
file_picker_types: 'image',
file_picker_callback: function(cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.onchange = function() {
var file = this.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var base64 = reader.result.split(',')[1];
var blobInfo = blobCache.create(id, file, base64);
blobCache.add(blobInfo);
cb(blobInfo.blobUri(), { title: file.name });
};
};
input.click();
}
});
</script>
Services追加
ドラック&ドロップされた画像がajaxで送られてくるので受け取ってstrageに保存する。
tinymceで削除された画像をstrageから消す。
app/Services/ImageService.php
<?php
namespace App\Services;
use App\Http\Requests\ProfileUpdateRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\View\View;
use Illuminate\Support\Facades\Storage;
class ImageService
{
//tinymceから送られた画像を保存
public static function tinymce(Request $request)
{
$folder = $request->input()['folder'].'/'.$request->input()['id'];
$file = $request->file('file');
$extension = $file->getClientOriginalExtension();
$fileName = 'tiro_tool_'.time().'.'.$extension;
$directoryPath = storage_path('app/public/' . $folder);
// フォルダが存在しない場合は作成
if (!file_exists($directoryPath)) {
mkdir($directoryPath, 0777, true);
}
chmod($directoryPath, 0777);
$file->storeAs('public/'.$folder.'/', $fileName);
return response()->json(['location'=>'/storage/'.$folder.'/'.$fileName]);
}
//tinymceで使われていない画像を削除
public static function tinymceClear($folder, $instance)
{
$folder .= '/'.$instance->id.'/';
if ($folder[0] !== '/') $folder = '/' . $folder;
$useingList = [];
$folderNeedle = 'public'.$folder;
$urlNeedle = '/storage'.$folder;
$nameNeedle = 'tiro_tool_';
//テーブルのカラム一覧を取得
$columns = $instance->getConnection()->getSchemaBuilder()->getColumnListing($instance->getTable());
foreach($columns as $c){
$text = $instance->$c;
$arr = explode($urlNeedle, $text);
foreach($arr as $a){
if(strpos($a, $nameNeedle)===0){
$useingList[] = (explode('"', $a))[0];
}
}
}
$files = Storage::files('public'.$folder);
foreach ($files as $file) {
$fileName = str_replace($folderNeedle, '', $file);
if(!in_array($fileName, $useingList)){
Storage::delete($file);
}
}
}
}
ルーティング
web.php
use App\Services\ImageService;
Route::post('/tinymce', [ImageService::class, 'tinymce']);