AVAVAVAVA
@AVAVAVAVA

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

laravelアプリをfly上でpostgreSQLと接続してデータをいじりたい

解決したいこと

laravelアプリをfly.ioにデプロイしpstgreSQLと接続したい。

発生している問題・エラー

デプロイは成功。
マイグレーションもエラーなく終了。
データを保存するメソッドを実行するボタンを押すとエラー

スクリーンショット 2024-01-10 23.00.35.png
スクリーンショット 2024-01-10 23.01.31.png

該当するソースコード

Vue.js
<script>
    export default {
        data () {
            return {
                categories: [],
                formContentsClass: 'createFormContents',
                formLabelClass: 'createFormInputLabel',
                formInputClass: 'createFormInput',
                inputName: 'name',
                inputCate: 'category',
                inputPPB: 'pricePerBox',
                inputSPB: 'snpPerBox',
                inputImg: 'image',
                submitName: '',
                submitCate: '',
                submitPPB: '',
                submitSPB: '',
                submitImg: '',
                createdPrizes: [],
                errors: [],
            }
        },

        props: {
            inputCategories: {},
        },

        methods: {
            CreatePrize () {
                if (!this.submitName || !this.submitCate || !this.submitPPB || !this.submitSPB) {
                    this.errors = [];

                    if (!this.submitName) {
                        this.errors.push('景品名を入力してください');
                    }

                    if (!this.submitCate) {
                        this.errors.push('カテゴリを入力してください');
                    }

                    if (!this.submitPPB) {
                        this.errors.push('箱単価を入力してください');
                    }

                    if (!this.submitSPB) {
                        this.errors.push('入り数を入力してください');
                    }

                    return false;
                }


                const url = 'http://localhost/create';
                axios.post(url, {
                    name: this.submitName,
                    category: this.submitCate,
                    pricePerBox: this.submitPPB,
                    snpPerBox: this.submitSPB,
                    img: this.submitImg

                }).then((response) => {
                    this.createdPrizes.push(
                        {
                            name: this.submitName,
                            category: this.submitCate,
                            pricePerBox: this.submitPPB,
                            snpPerBox: this.submitSPB
                        }
                    );
                    this.submitName =
                    this.submitCate =
                    this.submitPPB =
                    this.submitSPB =
                    this.submitImg = '';

                }).catch((error) => {
                    console.log(error);
                });
            },
            ImageToBinary (image) {
                const reader = new FileReader();
                const imgFile = image.target.files[0];

                if (image) {
                    reader.readAsDataURL(imgFile);
                } else {
                    this.submitImg = '';
                };

                reader.onload = () => {
                    this.submitImg = reader.result;
                }
            }
        },

        mounted() {
            this.categories = JSON.parse(this.inputCategories);
        }
    }
</script>

<template>
    <div id="createContainer">
        <form method="post" action="https://localhost/create">
            <div :class="formContentsClass">
                <label :for="inputName" :class="formLabelClass">景品名</label>
                <input :id="inputName" :class="formInputClass" v-model='submitName' type="text" placeholder="30字以内"/>
            </div>
            <div :class="formContentsClass">
                <label :for="inputCate" :class="formLabelClass">カテゴリ</label>
                <input :id="inputCate" :class="formInputClass" list="data-list" v-model='submitCate' type="text" placeholder="14字以内" />

                <datalist id="data-list">
                    <option v-for='category in categories'>{{ category }}</option>
                </datalist>
            </div>
            <div :class="formContentsClass">
                <label :for="inputPPB" :class="formLabelClass">箱単価</label>
                <input :id="inputPPB" :class="formInputClass" v-model='submitPPB' type="number" min="0" />
            </div>
            <div :class="formContentsClass">
                <label :for="inputSPB" :class="formLabelClass">入り数</label>
                <input :id="inputSPB" :class="formInputClass" v-model='submitSPB' type="number" min="0" />
            </div>
            <div :class="formContentsClass" v-if='false'>
                <label :for="inputImg" :class="formLabelClass">画像</label>
                <input :id="inputImg" :class="formInputClass" @change='ImageToBinary($event)' type="file" />
                <img :src='submitImg' />
            </div>
        </form>
        <button @click='CreatePrize'>作成</button>

        <ul v-if='errors'>
            <li v-for='error in errors'>
                {{ error }}
            </li>
        </ul>

        <table border="1">
            <colgroup>
                <col width="40%">
                <col width="25%">
                <col width="25%">
                <col width="10%">
            </colgroup>
            <tr>
                <td colspan="5">作成された景品</td>
            </tr>
            <tr v-if='createdPrizes.length == 0'>
                <td> </td>
                <td> </td>
                <td> </td>
                <td> </td>
            </tr>
            <tr v-for="(prize, index) in createdPrizes" :key=index>
                <td>{{ prize.name }}</td>
                <td>{{ prize.category }}</td>
                <td>{{ prize.pricePerBox }}</td>
                <td>{{ prize.snpPerBox }}</td>
            </tr>
        </table>
    </div>
</template>

<style>
    #createContainer {
        margin: 2rem 1rem;
    }

    .createFormContents {
        width: 25%;
        margin: 0.5rem 0;
    }

    .createFormInputLabel {
        display: inline-block;
        text-align: right;
        width: 35%;
    }

    .createFormInput {
        width: 65%;
    }

</style>

自分で試したこと

このページを参考にデプロイ。flyの仕様が変わったのか前半書いていることが違ったため
「fly上でLaravelアプリとデータベースを接続」
のところまでは参考程度に、その後は忠実に行いました。

エラーが出たためformのactionのhttpをhttpsに変えてみたり、.envファイルの中身を変えてみたりしましたがコネクション失敗、ホスト名を翻訳できませんでした等のエラーを行ったり来たりでした。

ほぼ独学でやっているため
「プロキシ?クラスタ?何それおいしいの?サーバ構築?MAMP設定の仕方調べてスタートボタンぽち〜」
レベルの知識しかありません。
原因究明に足りてない情報がありましたらお手数をおかけいたしますがコメントにて指示をお願いいたします。
また、理解はしたいため余裕がありましたら何が原因で起こるエラーなのか、どこがどういう悪さをしてエラーが起こっているかなど説明もつけていただけるとありがたいです。

解決法

コメントでおっしゃられている通りパスが間違っていました。
laravelのヘルパ関数のroute()でパスを調べ書き直すと解決しました。

次に出た500エラーはfly logsでログを確認したところ恐らくテーブルにupdated_atがないのにデータが送られてきているというエラーでした。調べるとlaravelはデフォルトでupdated_atなどを自動で保存する仕様のようです。
モデルに下のを記載で解決。試していないですがカラムを作成することでも解決するかも...?

publick $timestamps = false;
0

2Answer

fly.io とか触ったこともないのでハズレかもしれませんが・・・

運用環境にデプロイしてるのであれば、2 つ目の画像のエラーメッセージに 127.0.0.1 (localhost) というのが出てくるのが変です。接続文字列とか何か開発環境の設定のままでデプロイしたとか?

その前に、一番最初の画像の!マークもエラーのようで (そちらにも localhost と出てきてますね)、そちらを直すのが先かもしれませんが。

0Like

Comments

  1. @UMA9626 さん

    私の回答のコメント欄ではなくて、回答欄の方の書いていただけないでしょうか。

  2. 失礼しました。
    別回答にしてコメントは削除しました。

  3. @AVAVAVAVA

    Questioner

    回答ありがとうございます。返答が遅くなってしまい申し訳ありません。
    ご指摘の通りパスにlocaohostを指定していることが原因でした。書き直しましたところ新しく500エラーが発生しています。500エラーなため原因もいまいちわかっていません。

    スクリーンショット 2024-02-08 20.51.22.png
    スクリーンショット 2024-02-08 20.51.40.png

    一枚目がデータベースの情報をコピペしたもの、二枚目がfly.tomlに書いたコードになります。secretsも設定していましたが今は消してAPP_KEYだけ設定されています。
    恐縮ですが引き続きご教示お願いいたします。

@SurferOnWww さんと同意見で、おそらくlocalhostを指定しているのが間違いと思われます。
localhostは簡単に言うと「自分自身のIPアドレス」なのですが、Vue.jsで実行すると「現在Webページを表示しているPC」に対してAPIを叩いてしまいます。
APIが動いているのは自分のPC上ではなくfly.io上なので、そちらに対してAPIを叩く必要があります。

fly.io上のアプリのIPアドレスは以下などで確認できるかもしれません。
(間違っているかもですが...)

0Like

Comments

  1. 取り急ぎ、セキュリティのためDBのユーザー名/パスなどは伏せられた方が良いかと思います。

    また、「500エラーが出た」だけだと情報が不足していますので、以下などを参考にエラーログを探して頂けますでしょうか?
    https://fly.io/docs/flyctl/logs/

    念のため画面のconsoleログも共有ください。

  2. @AVAVAVAVA

    Questioner

    ご忠告ありがとうございます。解決いたしました。

  3. 良かったです!
    解決策も書いて頂きありがとうございます:bow:

Your answer might help someone💌