亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

搜索

React.js與PHP后端集成:構(gòu)建RESTful API應(yīng)用教程

碧海醫(yī)心
發(fā)布: 2025-10-16 12:30:02
原創(chuàng)
277人瀏覽過(guò)

React.js與PHP后端集成:構(gòu)建RESTful API應(yīng)用教程

本教程詳細(xì)介紹了如何將react.js前端php后端通過(guò)restful api進(jìn)行連接。文章將涵蓋后端api的構(gòu)建、前端數(shù)據(jù)請(qǐng)求與處理,以及跨域資源共享(cors)等關(guān)鍵配置,旨在幫助開(kāi)發(fā)者高效地構(gòu)建全棧web應(yīng)用。

在現(xiàn)代Web開(kāi)發(fā)中,前端與后端分離已成為主流實(shí)踐。React.js作為流行的前端庫(kù),負(fù)責(zé)構(gòu)建用戶界面;而PHP則常用于處理服務(wù)器端邏輯、數(shù)據(jù)庫(kù)交互和API服務(wù)。通過(guò)RESTful API,兩者可以無(wú)縫協(xié)作,共同構(gòu)建功能強(qiáng)大的Web應(yīng)用程序。

理解React.js與PHP的協(xié)作模式

React.js應(yīng)用通常運(yùn)行在用戶的瀏覽器中,負(fù)責(zé)渲染UI和響應(yīng)用戶操作。它通過(guò)HTTP請(qǐng)求(如GET、POST、PUT、DELETE)與后端API進(jìn)行通信,獲取或提交數(shù)據(jù)。PHP后端則接收這些請(qǐng)求,處理業(yè)務(wù)邏輯,與數(shù)據(jù)庫(kù)交互,并以JSON等格式返回?cái)?shù)據(jù)給前端。這種模式的核心是RESTful API,它定義了一套標(biāo)準(zhǔn)化的接口,使得不同技術(shù)棧的組件能夠互相理解和通信。

構(gòu)建PHP后端API

為了將原始的PHP CLI腳本轉(zhuǎn)換為可供React.js調(diào)用的Web API,我們需要進(jìn)行以下改造:

  1. 接收HTTP請(qǐng)求參數(shù):將CLI參數(shù)($_SERVER['argv'])替換為HTTP請(qǐng)求參數(shù)(如$_GET或$_POST)。
  2. 輸出JSON數(shù)據(jù):將純文本輸出改為JSON格式,并設(shè)置正確的Content-Type頭。
  3. 處理HTTP方法:雖然本示例主要使用GET請(qǐng)求,但在實(shí)際應(yīng)用中,后端應(yīng)能根據(jù)HTTP方法(GET、POST、PUT、DELETE)執(zhí)行不同的操作。

假設(shè)我們有一個(gè)data.json文件作為數(shù)據(jù)源:

立即學(xué)習(xí)PHP免費(fèi)學(xué)習(xí)筆記(深入)”;

[
    { "offerId": 1, "productTitle": "Laptop", "vendorId": 101, "price": 1200 },
    { "offerId": 2, "productTitle": "Mouse", "vendorId": 101, "price": 25 },
    { "offerId": 3, "productTitle": "Keyboard", "vendorId": 102, "price": 75 },
    { "offerId": 4, "productTitle": "Monitor", "vendorId": 103, "price": 300 },
    { "offerId": 5, "productTitle": "Webcam", "vendorId": 102, "price": 50 },
    { "offerId": 6, "productTitle": "Headphones", "vendorId": 101, "price": 150 }
]
登錄后復(fù)制

我們將原有的PHP代碼封裝為一個(gè)API入口文件 api.php:

集簡(jiǎn)云
集簡(jiǎn)云

軟件集成平臺(tái),快速建立企業(yè)自動(dòng)化與智能化

集簡(jiǎn)云22
查看詳情 集簡(jiǎn)云
<?php

// 設(shè)置CORS頭,允許React開(kāi)發(fā)服務(wù)器訪問(wèn)
header("Access-Control-Allow-Origin: http://localhost:3000"); // 替換為你的React應(yīng)用地址
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

// 處理OPTIONS請(qǐng)求,用于CORS預(yù)檢
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}

/**
 * The interface provides the contract for different readers
 * E.g. it can be XML/JSON Remote Endpoint, or CSV/JSON/XML local files
 */
interface ReaderInterface
{
    /**
     * Read in incoming data and parse to objects
     */
    public function read(string $input): OfferCollectionInterface;
}

/**
 * Interface of Data Transfer Object, that represents external JSON data
 */
interface OfferInterface
{
}

/**
 * Interface for The Collection class that contains Offers
 */
interface OfferCollectionInterface
{
    public function get(int $index): OfferInterface;
    public function getIterator(): Iterator;
}

/* *********************************** */

class Offer implements OfferInterface
{
    public $offerId;
    public $productTitle;
    public $vendorId;
    public $price;

    public function __toString(): string
    {
        return "$this->offerId | $this->productTitle | $this->vendorId | $this->price\n";
    }
}

class OfferCollection implements OfferCollectionInterface
{
    private $offersList = array();

    public function __construct($data)
    {
        if (is_array($data)) {
            foreach ($data as $json_object) {
                $offer = new Offer();
                $offer->offerId = $json_object->offerId;
                $offer->productTitle = $json_object->productTitle;
                $offer->vendorId = $json_object->vendorId;
                $offer->price = $json_object->price;

                array_push($this->offersList, $offer);
            }
        }
    }

    public function get(int $index): OfferInterface
    {
        return $this->offersList[$index];
    }

    public function getIterator(): Iterator
    {
        return new ArrayIterator($this->offersList);
    }

    public function __toString(): string
    {
        return implode("\n", $this->offersList);
    }

    // 新增方法:將OfferCollection轉(zhuǎn)換為數(shù)組,以便json_encode
    public function toArray(): array
    {
        $result = [];
        foreach ($this->offersList as $offer) {
            $result[] = [
                'offerId' => $offer->offerId,
                'productTitle' => $offer->productTitle,
                'vendorId' => $offer->vendorId,
                'price' => $offer->price,
            ];
        }
        return $result;
    }
}

class Reader implements ReaderInterface
{
    /**
     * Read in incoming data and parse to objects
     */
    public function read(string $input): OfferCollectionInterface
    {
        if ($input != null) {
            $content = file_get_contents($input);
            $json = json_decode($content);
            $result = new OfferCollection($json);

            return $result;
        }

        return new OfferCollection(null);
    }
}

class Logger
{
    private $filename = "logs.txt";

    public function info($message): void
    {
        $this->log($message, "INFO");
    }

    public function error($message): void
    {
        $this->log($message, "ERROR");
    }

    private function log($message, $type): void
    {
        $myfile = fopen($this->filename, "a") or die("Unable to open file!");
        $txt = "[$type] $message\n";
        fwrite($myfile, $txt);
        fclose($myfile);
    }
}

$json_url = 'data.json';

$json_reader = new Reader();
$offers_list = $json_reader->read($json_url);


function count_by_price_range($price_from, $price_to)
{
    global $offers_list;
    $count = 0;
    foreach ($offers_list->getIterator() as $offer) {
        if ($offer->price >= $price_from && $offer->price <= $price_to) {
            $count++;
        }
    }
    return $count;
}

function count_by_vendor_id($vendorId)
{
    global $offers_list;
    $count = 0;
    foreach ($offers_list->getIterator() as $offer) {
        if ($offer->vendorId == $vendorId) {
            $count++;
        }
    }
    return $count;
}

// 獲取請(qǐng)求路徑和參數(shù)
$request_uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path_segments = explode('/', trim($request_uri, '/'));
$api_endpoint = end($path_segments); // 假設(shè)API路徑的最后一段是功能名稱

$logger = new Logger();
$response_data = [];
$status_code = 200;

switch ($api_endpoint) {
    case "count_by_price_range": {
        $price_from = $_GET['from'] ?? null;
        $price_to = $_GET['to'] ?? null;

        if ($price_from !== null && $price_to !== null) {
            $logger->info("Getting Count By Price Range From: $price_from TO $price_to");
            $response_data = ['count' => count_by_price_range((float)$price_from, (float)$price_to)];
        } else {
            $status_code = 400;
            $response_data = ['error' => 'Missing price range parameters (from, to).'];
        }
        break;
    }
    case "count_by_vendor_id": {
        $vendorId = $_GET['vendorId'] ?? null;
        if ($vendorId !== null) {
            $logger->info("Getting Count By vendor Id: $vendorId");
            $response_data = ['count' => count_by_vendor_id((int)$vendorId)];
        } else {
            $status_code = 400;
            $response_data = ['error' => 'Missing vendorId parameter.'];
        }
        break;
    }
    case "offers": { // 新增一個(gè)獲取所有offer的接口
        $response_data = ['offers' => $offers_list->toArray()];
        break;
    }
    default: {
        $status_code = 404;
        $response_data = ['error' => 'API endpoint not found.'];
        break;
    }
}

http_response_code($status_code);
echo json_encode($response_data);

?>
登錄后復(fù)制

將 api.php 和 data.json 放在一個(gè)支持PHP的Web服務(wù)器(如Apache或Nginx)的根目錄下。 現(xiàn)在,你可以通過(guò)訪問(wèn)類似 http://localhost/api.php/count_by_price_range?from=50&to=200 或 http://localhost/api.php/offers 來(lái)測(cè)試API。

創(chuàng)建React.js前端應(yīng)用

接下來(lái),我們創(chuàng)建一個(gè)簡(jiǎn)單的React組件來(lái)調(diào)用這個(gè)PHP API并顯示數(shù)據(jù)。

  1. 初始化React項(xiàng)目 如果你還沒(méi)有React項(xiàng)目,可以使用Create React App快速搭建:

    npx create-react-app react-php-app
    cd react-php-app
    npm start
    登錄后復(fù)制
  2. 編寫(xiě)React組件 修改 src/App.js 文件,添加一個(gè)組件來(lái)獲取并展示數(shù)據(jù):

    import React, { useState, useEffect } from 'react';
    import './App.css';
    
    function App() {
      const [offers, setOffers] = useState([]);
      const [priceRangeCount, setPriceRangeCount] = useState(0);
      const [vendorIdCount, setVendorIdCount] = useState(0);
      const [loading, setLoading] = useState(true);
      const [error, setError] = useState(null);
    
      // PHP API 的基礎(chǔ)URL,請(qǐng)根據(jù)你的實(shí)際部署修改
      const API_BASE_URL = 'http://localhost/api.php'; 
    
      useEffect(() => {
        const fetchData = async () => {
          try {
            // 獲取所有Offers
            const offersResponse = await fetch(`${API_BASE_URL}/offers`);
            if (!offersResponse.ok) {
              throw new Error(`HTTP error! status: ${offersResponse.status}`);
            }
            const offersData = await offersResponse.json();
            setOffers(offersData.offers || []);
    
            // 獲取價(jià)格區(qū)間統(tǒng)計(jì)
            const priceRangeResponse = await fetch(`${API_BASE_URL}/count_by_price_range?from=50&to=200`);
            if (!priceRangeResponse.ok) {
              throw new Error(`HTTP error! status: ${priceRangeResponse.status}`);
            }
            const priceRangeData = await priceRangeResponse.json();
            setPriceRangeCount(priceRangeData.count || 0);
    
            // 獲取供應(yīng)商ID統(tǒng)計(jì)
            const vendorIdResponse = await fetch(`${API_BASE_URL}/count_by_vendor_id?vendorId=101`);
            if (!vendorIdResponse.ok) {
              throw new Error(`HTTP error! status: ${vendorIdResponse.status}`);
            }
            const vendorIdData = await vendorIdResponse.json();
            setVendorIdCount(vendorIdData.count || 0);
    
          } catch (error) {
            console.error("Error fetching data:", error);
            setError(error);
          } finally {
            setLoading(false);
          }
        };
    
        fetchData();
      }, []); // 空數(shù)組表示只在組件掛載時(shí)運(yùn)行一次
    
      if (loading) return <div>Loading data...</div>;
      if (error) return <div>Error: {error.message}</div>;
    
      return (
        <div className="App">
          <h1>React.js & PHP API 集成示例</h1>
    
          <h2>所有商品列表</h2>
          {offers.length > 0 ? (
            <ul>
              {offers.map(offer => (
                <li key={offer.offerId}>
                  ID: {offer.offerId}, Title: {offer.productTitle}, Vendor: {offer.vendorId}, Price: ${offer.price}
                </li>
              ))}
            </ul>
          ) : (
            <p>沒(méi)有商品數(shù)據(jù)。</p>
          )}
    
          <h2>統(tǒng)計(jì)信息</h2>
          <p>價(jià)格在 $50 到 $200 之間的商品數(shù)量: {priceRangeCount}</p>
          <p>供應(yīng)商ID為 101 的商品數(shù)量: {vendorIdCount}</p>
        </div>
      );
    }
    
    export default App;
    登錄后復(fù)制

處理跨域資源共享 (CORS)

在開(kāi)發(fā)階段,React應(yīng)用通常運(yùn)行在 http://localhost:3000,而PHP后端可能運(yùn)行在 http://localhost 或 http://localhost:80。由于它們端口或域名不同,瀏覽器會(huì)阻止React應(yīng)用直接訪問(wèn)PHP API,這就是所謂的“跨域”問(wèn)題。

為了解決這個(gè)問(wèn)題,PHP后端需要發(fā)送特定的HTTP響應(yīng)頭,告知瀏覽器允許來(lái)自React應(yīng)用源的請(qǐng)求。在 api.php 的開(kāi)頭,我們已經(jīng)添加了以下CORS頭:

header("Access-Control-Allow-Origin: http://localhost:3000"); // 允許來(lái)自React開(kāi)發(fā)服務(wù)器的請(qǐng)求
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); // 允許的HTTP方法
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");

// 處理OPTIONS請(qǐng)求,用于CORS預(yù)檢
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}
登錄后復(fù)制
  • Access-Control-Allow-Origin: 指定允許訪問(wèn)資源的源。在生產(chǎn)環(huán)境中,應(yīng)將其設(shè)置為你的前端域名,或者根據(jù)需要?jiǎng)討B(tài)設(shè)置。* 可以允許所有源,但出于安全考慮,不建議在生產(chǎn)環(huán)境中使用。
  • Access-Control-Allow-Methods: 指定允許的HTTP方法。
  • Access-Control-Allow-Headers: 指定在實(shí)際請(qǐng)求中可以使用的HTTP頭。
  • 當(dāng)瀏覽器發(fā)送跨域請(qǐng)求時(shí),對(duì)于某些復(fù)雜的請(qǐng)求(如帶有自定義頭或非簡(jiǎn)單方法的請(qǐng)求),會(huì)先發(fā)送一個(gè)OPTIONS請(qǐng)求(預(yù)檢請(qǐng)求)。后端需要正確響應(yīng)這個(gè)OPTIONS請(qǐng)求。

部署與注意事項(xiàng)

  1. 生產(chǎn)環(huán)境CORS配置:在生產(chǎn)環(huán)境中,Access-Control-Allow-Origin 應(yīng)精確設(shè)置為你的前端應(yīng)用的域名(例如 https://your-react-app.com),而不是 http://localhost:3000 或 *。
  2. API路由:對(duì)于更復(fù)雜的應(yīng)用,建議使用一個(gè)成熟的PHP框架(如Laravel、Symfony)來(lái)處理路由、請(qǐng)求驗(yàn)證和ORM,這會(huì)使API開(kāi)發(fā)更加高效和健壯。
  3. 安全性
    • 輸入驗(yàn)證:始終驗(yàn)證來(lái)自前端的所有輸入,防止SQL注入、XSS等攻擊。
    • 認(rèn)證與授權(quán):實(shí)現(xiàn)用戶認(rèn)證(如JWT、Session)和授權(quán)機(jī)制,確保只有經(jīng)過(guò)身份驗(yàn)證的用戶才能訪問(wèn)受保護(hù)的API資源。
    • HTTPS:在生產(chǎn)環(huán)境中,始終使用HTTPS來(lái)加密前后端之間的通信。
  4. 錯(cuò)誤處理:后端API應(yīng)提供清晰的錯(cuò)誤響應(yīng)(如HTTP狀態(tài)碼和JSON格式的錯(cuò)誤信息),前端也應(yīng)妥善處理這些錯(cuò)誤并向用戶展示友好的提示。
  5. 性能優(yōu)化:對(duì)于數(shù)據(jù)量大的API,考慮分頁(yè)、緩存、數(shù)據(jù)庫(kù)索引等優(yōu)化措施。

總結(jié)

通過(guò)RESTful API,React.js和PHP可以高效地協(xié)同工作,分別專注于前端的用戶體驗(yàn)和后端的業(yè)務(wù)邏輯。構(gòu)建一個(gè)穩(wěn)健的API涉及請(qǐng)求處理、數(shù)據(jù)格式化、CORS配置以及安全性考量。遵循本教程的指導(dǎo),開(kāi)發(fā)者可以順利地將React.js前端與PHP后端集成,構(gòu)建出功能完善、結(jié)構(gòu)清晰的Web應(yīng)用程序。

以上就是React.js與PHP后端集成:構(gòu)建RESTful API應(yīng)用教程的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!

PHP速學(xué)教程(入門(mén)到精通)
PHP速學(xué)教程(入門(mén)到精通)

PHP怎么學(xué)習(xí)?PHP怎么入門(mén)?PHP在哪學(xué)?PHP怎么學(xué)才快?不用擔(dān)心,這里為大家提供了PHP速學(xué)教程(入門(mén)到精通),有需要的小伙伴保存下載就能學(xué)習(xí)啦!

下載
來(lái)源:php中文網(wǎng)
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請(qǐng)聯(lián)系admin@php.cn
最新問(wèn)題
開(kāi)源免費(fèi)商場(chǎng)系統(tǒng)廣告
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見(jiàn)反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長(zhǎng)!
關(guān)注服務(wù)號(hào) 技術(shù)交流群
PHP中文網(wǎng)訂閱號(hào)
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時(shí)隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號(hào)
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)