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

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

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

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

Laravel

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

PHP

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

解決済

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

asahiko123
asahiko123

総合スコア38

Vue.js

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

Laravel

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

PHP

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

3回答

0評価

1クリップ

372閲覧

投稿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

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests\StoreCards; use App\Models\Cards; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Auth; class CardsController extends Controller { public function __construct(){ $this->middleware('auth'); } /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { // } /** * 投稿 * * @return \Illuminate\Http\Response */ public function create(StoreCards $request) { $extension = $request->posted_image->extension(); //png $cards = new Cards(); $cards->posted_image = $cards->id . '.' . $extension; //ここで$cards->idの値がないのでエラーになっている $cards->post = $request->post; var_dump($cards->posted_image); dd($cards->posted_image,$cards->post); //中略 return response($cards,201); }

Cards.php

php

<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use App\Http\Helper; class Cards extends Model { use HasFactory; protected $keyType = 'string'; protected $table = 'cards'; public $incrementing = false; protected $guarded =[]; protected static function boot(){ parent::boot(); static::creating(function($model){ $randomId = Helper::getRandomId(); $exists = Cards::where('id',$randomId)->exists(); if(!$exists){ $model->id = $randomId; } }); } }

php

<?php namespace App\Http\Helper; class Helper{ function getRandomId(){ $characters = array_merge( range(0,9), range('a','z'), range('A','Z'), ['_','-'] ); $length = count($characters); $id = ''; for($i = 0; $i < 12; $i++){ $id .= $characters[random_int(0,$length -1)]; } return $id; } }

php

<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('cards', function (Blueprint $table) { $table->string('id')->primary(); $table->unsignedBigInteger('user_id')->comment('ユーザID'); $table->string('post')->comment('本文'); $table->longtext('posted_image')->comment('投稿画像'); $table->softDeletes(); $table->timestamps(); $table->index('id'); $table->index('user_id'); $table->index('post'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('cards'); } };

php

<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; use App\Http\Controllers\Auth\LoginController; use App\Http\Controllers\Auth\RegisterController; use App\Http\Controllers\CardsController; Route::post('/login',[LoginController::class,'login']); Route::post('/logout',[LoginController::class,'logout'])->name('login'); Route::post('/register',[RegisterController::class, 'register'])->name('register'); Route::middleware('auth:sanctum')->group(function(){ Route::post('/cards',[CardsController::class, 'create'])->name('cards.create'); });

Vue

<template> <v-dialog transition="dialog-bottom-transition" max-width="600"> <template v-slot:activator="{ on, attrs }"> <v-btn v-bind="attrs" v-on="on"> <span>投稿する</span> <v-icon>mdi-timeline</v-icon> </v-btn> </template> <template v-slot="dialog"> <v-card> <v-toolbar> </v-toolbar> <v-text-field placeholder="ここに投稿" name = "post" required outlined dense v-model="post"> </v-text-field> <input class="form__item" type="file" @change="onFileChange"> <output class="form__output" v-if="preview" > <img :src="preview" alt="" width="400" height="400"> </output> <v-card-actions class="justify-end"> <v-form ref="form" @submit.prevent ="submit"> <!-- <div class="errors" v-if="errors"> <ul v-if="errors.posted_image"> <li v-for="msg in errors.posted_image" :key="msg">{{ msg }}</li> </ul> </div> --> <v-btn type="submit" color="rgb(106, 118, 171)" class="float-right">投稿する</v-btn> </v-form> <v-btn text @click="dialog.value= false">Close</v-btn> </v-card-actions> </v-card> </template> </v-dialog> </template> <script> import axios from 'axios' import { INTERNAL_SERVER_ERROR} from '../../util' export default{ name: "PostModal", data(){ return{ preview: null, posted_image: null, post: null, errors: null } }, methods: { onFileChange(event){ const reader = new FileReader() reader.onload = e =>{ this.preview = e.target.result } reader.readAsDataURL(event.target.files[0]) this.posted_image = event.target.files[0] }, reset(){ this.preview = '', this.posted_image = null, this.$el.querySelector('input[type="file"]').value = null }, async submit(){ const formData = new FormData(); formData.append('posted_image',this.posted_image); formData.append('post',this.post); const response = await axios.post('/api/cards',formData) if (response.status === INTERNAL_SERVER_ERROR) { this.errors = response.data.errors return false } } } } </script>

試したこと

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

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

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

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

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Vue.js

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

Laravel

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

PHP

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