質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

1069閲覧

【laravel】Modelクラスを作成時にランダムなIDを生成したい

asahiko123

総合スコア43

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2022/07/06 14:14

前提

laravelを使ってSPAなwebアプリを作っています。
SNSライクにテキストと画像をDBに新規登録する過程で問題があるので質問させて頂きます。

実現したいこと

DBのテーブルのprimary key(ID)をstringに変更したので、modelを生成する際にID用のランダムな文字列を作りましたが、model(Cards.php)からidの値を取り出した時に$cards->idの中身がありません。
Cardsモデルの中で値が作れていないということでしょうか。
ユーザー認証は成功しております。

発生している問題・エラーメッセージ

AXIOSでapi/cardsというルートにアクセスし、CardControllerのcreate(新規作成)メソッドを実行したところで
エラーになるようで、laravel.logには以下のように".png”ファイルは存在しない、となっています。

[2022-07-05 15:06:27] local.ERROR: The file ".png" does not exist {"userId":1,"exception":"[object] (Symfony\\Component\\HttpFoundation\\File\\Exception\\FileNotFoundException(code: 0): The file \".png\" does not exist at /var/www/html/vendor/symfony/http-foundation/File/File.php:36) [stacktrace]

CardsControllerのdd()の出力をみると、同じように拡張子だけがとれていてランダムな値は生成できていないように見えます。
fffは$cards->postの値。

イメージ説明

該当のソースコード

CardsController

php

1<?php 2 3namespace App\Http\Controllers; 4 5use Illuminate\Http\Request; 6use App\Http\Requests\StoreCards; 7use App\Models\Cards; 8use Illuminate\Support\Facades\Storage; 9use Illuminate\Support\Facades\DB; 10use Illuminate\Support\Facades\Auth; 11 12 13class CardsController extends Controller 14{ 15 16 public function __construct(){ 17 18 $this->middleware('auth'); 19 20 } 21 /** 22 * Display a listing of the resource. 23 * 24 * @return \Illuminate\Http\Response 25 */ 26 public function index() 27 { 28 // 29 } 30 31 /** 32 * 投稿 33 * 34 * @return \Illuminate\Http\Response 35 */ 36 public function create(StoreCards $request) 37 { 38 $extension = $request->posted_image->extension(); //png 39 40 $cards = new Cards(); 41 42 $cards->posted_image = $cards->id . '.' . $extension; //ここで$cards->idの値がないのでエラーになっている 43 $cards->post = $request->post; 44 45 var_dump($cards->posted_image); 46 47 dd($cards->posted_image,$cards->post); 48 49 //中略 50 51 return response($cards,201); 52 } 53

Cards.php

php

1<?php 2 3namespace App\Models; 4 5use Illuminate\Database\Eloquent\Factories\HasFactory; 6use Illuminate\Database\Eloquent\Model; 7 8use App\Http\Helper; 9 10class Cards extends Model 11{ 12 use HasFactory; 13 14 15 protected $keyType = 'string'; 16 protected $table = 'cards'; 17 public $incrementing = false; 18 protected $guarded =[]; 19 20 21 protected static function boot(){ 22 23 parent::boot(); 24 25 static::creating(function($model){ 26 27 $randomId = Helper::getRandomId(); 28 29 $exists = Cards::where('id',$randomId)->exists(); 30 31 if(!$exists){ 32 $model->id = $randomId; 33 } 34 35 }); 36 } 37 38} 39 40

php

1<?php 2 3namespace App\Http\Helper; 4 5class Helper{ 6 7 function getRandomId(){ 8 9 $characters = array_merge( 10 range(0,9), 11 range('a','z'), 12 range('A','Z'), 13 ['_','-'] 14 ); 15 16 $length = count($characters); 17 18 $id = ''; 19 20 for($i = 0; $i < 12; $i++){ 21 22 $id .= $characters[random_int(0,$length -1)]; 23 } 24 25 return $id; 26 27 } 28 29} 30 31 32

php

1<?php 2 3use Illuminate\Database\Migrations\Migration; 4use Illuminate\Database\Schema\Blueprint; 5use Illuminate\Support\Facades\Schema; 6 7return new class extends Migration 8{ 9 /** 10 * Run the migrations. 11 * 12 * @return void 13 */ 14 public function up() 15 { 16 Schema::create('cards', function (Blueprint $table) { 17 $table->string('id')->primary(); 18 $table->unsignedBigInteger('user_id')->comment('ユーザID'); 19 $table->string('post')->comment('本文'); 20 $table->longtext('posted_image')->comment('投稿画像'); 21 $table->softDeletes(); 22 $table->timestamps(); 23 24 $table->index('id'); 25 $table->index('user_id'); 26 $table->index('post'); 27 28 $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade'); 29 }); 30 } 31 32 /** 33 * Reverse the migrations. 34 * 35 * @return void 36 */ 37 public function down() 38 { 39 Schema::dropIfExists('cards'); 40 } 41};

php

1<?php 2 3use Illuminate\Http\Request; 4use Illuminate\Support\Facades\Route; 5use App\Http\Controllers\Auth\LoginController; 6use App\Http\Controllers\Auth\RegisterController; 7use App\Http\Controllers\CardsController; 8 9Route::post('/login',[LoginController::class,'login']); 10Route::post('/logout',[LoginController::class,'logout'])->name('login'); 11Route::post('/register',[RegisterController::class, 'register'])->name('register'); 12 13 14Route::middleware('auth:sanctum')->group(function(){ 15 Route::post('/cards',[CardsController::class, 'create'])->name('cards.create'); 16}); 17

Vue

1 2<template> 3 4<v-dialog 5 transition="dialog-bottom-transition" 6 max-width="600"> 7 8 <template v-slot:activator="{ on, attrs }"> 9 10 <v-btn 11 v-bind="attrs" 12 v-on="on"> 13 <span>投稿する</span> 14 <v-icon>mdi-timeline</v-icon> 15 </v-btn> 16 17 </template> 18 <template v-slot="dialog"> 19 <v-card> 20 <v-toolbar> 21 22 </v-toolbar> 23 24 <v-text-field 25 placeholder="ここに投稿" 26 name = "post" 27 required 28 outlined 29 dense 30 v-model="post"> 31 </v-text-field> 32 33 34 <input class="form__item" type="file" @change="onFileChange"> 35 36 <output class="form__output" v-if="preview" > 37 <img :src="preview" alt="" width="400" height="400"> 38 </output> 39 40 41 <v-card-actions class="justify-end"> 42 <v-form ref="form" @submit.prevent ="submit"> 43 <!-- <div class="errors" v-if="errors"> 44 <ul v-if="errors.posted_image"> 45 <li v-for="msg in errors.posted_image" :key="msg">{{ msg }}</li> 46 </ul> 47 </div> --> 48 <v-btn type="submit" color="rgb(106, 118, 171)" class="float-right">投稿する</v-btn> 49 </v-form> 50 <v-btn 51 text 52 @click="dialog.value= false">Close</v-btn> 53 54 </v-card-actions> 55 </v-card> 56 </template> 57</v-dialog> 58 59 60</template> 61 62<script> 63 64import axios from 'axios' 65import { INTERNAL_SERVER_ERROR} from '../../util' 66 67 68export default{ 69 70 name: "PostModal", 71 72 data(){ 73 74 return{ 75 preview: null, 76 posted_image: null, 77 post: null, 78 errors: null 79 } 80 81 }, 82 83 methods: { 84 onFileChange(event){ 85 86 87 const reader = new FileReader() 88 89 reader.onload = e =>{ 90 91 this.preview = e.target.result 92 } 93 94 reader.readAsDataURL(event.target.files[0]) 95 96 this.posted_image = event.target.files[0] 97 98 99 }, 100 reset(){ 101 this.preview = '', 102 this.posted_image = null, 103 this.$el.querySelector('input[type="file"]').value = null 104 }, 105 async submit(){ 106 const formData = new FormData(); 107 108 formData.append('posted_image',this.posted_image); 109 formData.append('post',this.post); 110 111 const response = await axios.post('/api/cards',formData) 112 113 114 if (response.status === INTERNAL_SERVER_ERROR) { 115 this.errors = response.data.errors 116 return false 117 } 118 119 120 } 121 } 122} 123</script> 124 125

試したこと

Logや検証ツールで見るかぎり、フォームからControllerに値はわたっているようです。問題はControllerまたはModelのコードにあるようですが間違いが分かりませんでした。

長文で申し訳ありませんが、ご指摘頂ければと思います。

補足情報(FW/ツールのバージョンなど)

laravel9.18.0
laravel/sail1.14.11
vue2
vuetify2.6.6
php8.1.7
MySQL8.0.29

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

自己解決

モデルのコンストラクタ関数内で、attributesにsetIdする形にすることで
上手く意図したことができましたので自己解決とさせて頂きます。

php

1public function __construct(array $attributes = []) 2 { 3 parent::__construct($attributes); 4 5 if (! Arr::get($this->attributes, 'id')) { 6 $this->setId(); 7 } 8 } 9 10private function setId() 11 { 12 $this->attributes['id'] = $this->getRandomId(); 13 }

投稿2022/07/07 12:35

asahiko123

総合スコア43

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まずstring('id')をやめる。LaravelはidがUNSIGNED BIGINTなことを前提にしているのでここを変えるとあらゆるところで面倒になって必ず後悔する。
ランダムなIDが必要ならidとは別に用意すればいいだけ。

php

1use Illuminate\Support\Str; 2 3$card = new Cards(); 4$card->random = Str::random(12);

それ以前にファイルアップロードもできてないけど。
store()なら自動的にランダムなファイル名になるので自分で作る必要さえない。
ランダムなIDがファイル名だけに必要なのかCardでも必要なのか分からないのでこれ以上書きようがない。

投稿2022/07/06 23:44

kawax

総合スコア10377

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

DBのテーブルのprimary key(ID)をstringに変更したので、modelを生成する際にID用のランダムな文字列を作りましたが、model(Cards.php)からidの値を取り出した時に$cards->idの中身がありません。
Cardsモデルの中で値が作れていないということでしょうか。

php

1$cards = new Cards();

new しただけでは、IDは振られません。IDが振られるのは、「保存処理の終了時」です。

追記
UUID ライブラリでも使っているんですかね?その前提で回答しています。

https://github.com/goldspecdigital/laravel-eloquent-uuid

投稿2022/07/06 15:21

編集2022/07/06 15:23
phper.k

総合スコア3923

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

asahiko123

2022/07/07 12:35

言葉足らずで申し訳ありません。 uuidは使わず、モデル内でランダムな値を生成しようとしています。 自己解決欄の方法で行ったところ上手く意図したとおりになりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問