juza11
@juza11

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

axiosでデータ取得APIのget.phpを呼び出し、データ取得したい

解決したいこと

axiosでデータ取得APIのget.phpを呼び出し、データ取得したい

例)
vue.jsで練習のため簡単なアプリケーションを作っています。
axios通信の部分でエラーが発生しました。
解決方法を教えて下さい。

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

GET http://localhost:8080/api/get.php 404 (Not Found)
AxiosError {message: 'Request failed with status code 404'...省略

スクリーンショット 2024-03-11 115037.jpg

該当するソースコード

Users.vue
<script>
import { mapGetters } from 'vuex';
import axios from '@/axios-auth';
export default {
    data() {
        return {
            users: {},
            error: false    // ユーザ一覧が取得できない場合はここがtrueとなる
        }
    },
    computed: {
        ...mapGetters(['userDetail']),
    },
    methods: {
        toUserEdit(index) {
            this.$store.dispatch('toUserDetail',this.users[index]);
            this.$router.push('/users/edit/'+this.users[index].id, () => {});
        },
    },
    created() {
        /* ここにユーザ一覧情報を取得する処理を記載 */
        axios.get('/get.php')
        .then(response => {
            this.users = response.data;
        })
        .catch(error => {
            console.log(error);
            this.error = true;
            console.log('失敗');
        });
    },
    name: 'UserVue',
}
</script>
axios-suth.js
import axios from 'axios';

const axiosAuth = axios.create({
    // ここのURLは環境によって変わります
    baseURL: 'http://localhost:8080/api'
});
// axiosAuth.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
axiosAuth.defaults.headers.post['Content-Type'] = 'multipart/form-data; charset=utf-8';
axiosAuth.defaults.headers.common['Accept'] = 'application/json';

export default axiosAuth;
get.php
<?php
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: Content-Type');
    header('Access-Control-Allow-Methods: GET, POST');
    exit();
}
header('Access-Control-Allow-Origin: *');
header('Content-type: application/json; charset=UTF-8');

define('DB_HOST',   'localhost');
define('DB_USER',   'root');
define('DB_PASSWD', 'root');
define('DB_NAME',   'sample_api');

try {
    $dbh = new PDO('mysql:dbname='.DB_NAME.';host='.DB_HOST, DB_USER, DB_PASSWD);
    $sql = 'SELECT id,name,email,birthday,gender FROM users';
    $sth = $dbh->prepare($sql);
    $sth->execute();
    $result = $sth->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo "接続失敗: " . $e->getMessage() . "\n";
    exit();
}

header('Content-type: application/json');
echo json_encode($result);

ディレクトリ構造

C:\2023_現場準備\vue_adv
  ├── api
  │   └── get.php
  ├── src
  │   └── axios-auth.js
  └── ...

自分で試したこと

・PHPのビルトインサーバーを使用して、ブラウザで http://localhost:8080/get.php にアクセスした場合はデータが取得できました。
・ファイルパスを見直しましたが問題が分かりませんでした。
・別のディレクトリにもget.phpを配置して試してみましたが問題は解消できませんでした。

0

2Answer

404 エラーの原因は指定した url が間違っていることがほとんどです。まずそこを調べることが第一です。できれば質問する前に。


【追記】

下のコメントにも書きましたが、どうやら、

(1) フロントエンドから axios を使ってバックエンドのサーバーのリソースを取得するのが目的

(2) しかしながら、axios が要求を出したのはフロントエンドのサーバー

(3) 当然、フロントエンドのサーバーには要求したリソースはない

(4) 結果、フロントエンドのサーバーから HTTP 404 応答 (見つからない) が返ってきた

・・・ということになっているのだと思われます。

上の (2) 以降については質問者さんは「どういう動きをしているのか理解できていません」とのことですが、コメント欄のやり取りや画像を見る限り、質問者さんの開発環境ではサーバーが異なるのは間違いないと思います。即ち、

(a) フロントエンドの Vue をホストするサーバーは Node.js 開発サーバー (Express)

(b) バックエンドの Web API をホストするサーバーは PHP ビルドインサーバー

・・・となっているはずです。

なので、上記 (1) の目的を果たすには、開発環境で同時に (a), (b) 両方のサーバーを動かしておいて、(a) の axios から (b) に要求を出す必要があります。

(a) のポートが 8080 であれば (b) のポートをそれとは異なるものに設定すれば (例えば php -S localhost:5000 とするとか)、同時に両方動かすことはできると思いますので試してみてください。

ただし、そうすると、(a) と (b) とではポートが異なる (ドメインが異なる) ので、(a) から axios を使って (b) に要求を出すとクロスドメインの問題が起きます。

クロスドメインの問題を解決するには以下の方法があります。

(i) バックエンドで CORS 対応を行う、または

(ii) フロントエンドでプロキシを使ってバックエンドへの要求はプロキシを通す (http-proxy-module (HPM) という Node.js のプロキシが使えると思います)

検討してみてください。

2Like

Comments

  1. 下記URLを試してみましたがうまくいきませんでした。
    http://localhost:8080/get.php
    http://localhost:8080/api/get.php

    最初の質問に、

    ブラウザで http://localhost:8080/get.php にアクセスした場合はデータが取得できました。

    と書いてありましたけど??????

    質問の画像をみると http://localhost/api/get.php を要求して 404 Not Found となったと読めます。で、ブラウザで試したら http://localhost:8080/get.php で OK だったとのことなので、正解は http://localhost:8080/get.php だろうと思っていたのですが、違うのでしょうか。

  2. @juza11

    Questioner

    自分もそのように考え、

    baseURL: 'http://localhost:8080'
    axios.get('/get.php')
    

    に修正したのですが、
    GET http://localhost:8080/get.php 404 (Not Found)
    のエラーが出ました。

    ちなみに、サーバーは
    npm run serve
    で起動していますが、先ほどの

    ブラウザで http://localhost:8080/get.php にアクセスした場合はデータが取得できました。

    を試したときは、自身で設定している404ページへのリダイレクトを回避するために、
    php -S localhost:8080
    のコマンドでPHPのビルトインサーバーを起動しました。

  3. Fiddler とかブラウザの開発者ツールで要求・応答をキャプチャして、ブラウザで試してうまくいくときと、axios で試してダメな時とを見比べてみてはいかがですか?

    下の画像は Fiddler で見たものですが、質問者さんのケースでは赤枠の部分がブラウザで試した時と axios で試した時と異なるのではないですか? そうでなければブラウザで成功、axios で 404 になるはずはないと思いますけど。

    Fiddler.jpg

  4. @juza11

    Questioner

    何度もご回答ありがとうございます。
    chromeの検証ツールで見比べてみました。
    添付画像の上がaxios で試した時、下がブラウザで試したときのものですが、どちらもURLは同じように思います。他に違う部分はサーバーのみなので、そこに原因があるのでしょうか...
    axios 2024-03-11 171918.jpg
    ブラウザ2024-03-11 171726.jpg

  5. 他に違う部分はサーバーのみなので、そこに原因があるのでしょうか...

    確かにサーバーが違いますね。ダメな方は Express、うまくいくのは PHP/8.3.0 と読めますが、そもそもなぜ違うのですか?

    Express というのはフロントエンドをホストしているサーバー、PHP/8.3.0 というのはバックエンドをホストしているサーバーのようですが、であればフロントエンドからバックエンドに要求を出さねばならないはず。だから Express に要求を出したのではダメなのは当たり前ではないのですか?

  6. どうやら、

    (1) フロントエンドから axios を使ってバックエンドのサーバーのリソースを取得するのが目的

    (2) しかしながら、axios が要求を出したのはフロントエンドのサーバー

    (3) 当然、フロントエンドのサーバーには要求したリソースはない

    (4) 結果、フロントエンドのサーバーから HTTP 404 応答 (見つからない) が返ってきた

    ・・・ということのようですね。

    上の理解が正しいか返事をください。返事をもらったら、後で解答欄に対応案を書きます。

  7. @juza11

    Questioner

    返信が遅くなりすみません。
    ⑴の目的で合っています。
    ⑵以降については自分でもどういう動きをしているのか理解できていませんが、@SurferOnWwwさんがおっしゃる内容の通りだと思います。
    何卒よろしくお願いいたします。

  8. @juza11

    Questioner

    追記コメントを見る前に試したことですが、localhostを127.0.0.1に置き換え、http://127.0.0.1:8080/get.php でブラウザからリクエストした場合、添付画像の通りデータが取得できました。また、その時のネットワークタブを見ると、リクエストURLはhttp://localhost:8080/get.php になっていました。スクリーンショット 2024-03-12 112134.jpg

    追記のコメントを読んで、原因と解決法がしっかり理解できたと思います。
    解決までご対応いただき本当にありがとうございました。

  9. localhostを127.0.0.1に置き換え、http://127.0.0.1:8080/get.php でブラウザからリクエストした場合、添付画像の通りデータが取得できました。

    localhost と 127.0.0.1 は同じです。正確に言うと localhost を名前解決して ipv4 アドレスを取得すると 127.0.0.1 になります。

    Windows PC なら C:\Windows\System32\drivers\etc フォルダにある hosts ファイルに指定されています。そのあたり、ネットの基本なので勉強して知識をつけることをお勧めします。

  10. @juza11

    Questioner

    補足もありがとうございます。
    その部分もしっかり調べて見ます。

PHPのビルトインサーバーを使用して、ブラウザで http://localhost:8080/get.php にアクセスした場合はデータが取得できました。

エラーメッセーを見ると http://localhost:8080/api/get.phpにアクセスしています。
成功したときのURLと比較すると/apiの部分が異なっています。

成功:http://localhost:8080/get.php
失敗:http://localhost:8080/api/get.php

APIのURLが想定と異なっているか、リクエストURLが想定と異なっているかのどちらかだと思われます。

1Like

Comments

  1. VueとPHPの2つのアプリケーションがありますが、どのような状態で確認しているのかがわからない部分です。
    スクリーンショットを見るとPHPとVueのどちらもポート8080になっているように見えます。
    どちらのサーバーも起動した状態で、直接ブラウザからAPIにアクセスすると正常に動作して、axiosからアクセスすると404になる、という状況でしょうか?
    (同じポートで同時に起動すると問題がおきそうな気がしますが)

  2. @juza11

    Questioner

    先にaxiosからアクセスを試した際は、 npm run serve でサーバーを起動しました。
    その状態でphpのビルトインサーバーを起動し、直接ブラウザからAPIにアクセスを試しましたが、その時はVueのアプリがブラウザ表示されなくなっていたので、同時には起動していない状態だったと思います。

  3. では404エラーになるのは「PHPビルトインサーバーが起動していない」というのが考えられそうですね。
    VueアプリケーションとPHPアプリケーションを動かすサーバーは異なりますから、両方が機能していないとアプリケーション間での通信は行えないでしょう。
    ポート番号が同じだと同時に起動できないでしょうから、別々のポート番号を設定して接続を試してみてください。

  4. @juza11

    Questioner

    ありがとうございます。試してみます。

Your answer might help someone💌