0

0

React.js与PHP后端集成:构建RESTful API应用教程

碧海醫心

碧海醫心

发布时间:2025-10-16 12:30:02

|

509人浏览过

|

来源于php中文网

原创

React.js与PHP后端集成:构建RESTful API应用教程

本教程详细介绍了如何将react.js前端php后端通过restful api进行连接。文章将涵盖后端api的构建、前端数据请求与处理,以及跨域资源共享(cors)等关键配置,旨在帮助开发者高效地构建全栈web应用。

在现代Web开发中,前端与后端分离已成为主流实践。React.js作为流行的前端库,负责构建用户界面;而PHP则常用于处理服务器端逻辑、数据库交互和API服务。通过RESTful API,两者可以无缝协作,共同构建功能强大的Web应用程序。

理解React.js与PHP的协作模式

React.js应用通常运行在用户的浏览器中,负责渲染UI和响应用户操作。它通过HTTP请求(如GET、POST、PUT、DELETE)与后端API进行通信,获取或提交数据。PHP后端则接收这些请求,处理业务逻辑,与数据库交互,并以JSON等格式返回数据给前端。这种模式的核心是RESTful API,它定义了一套标准化的接口,使得不同技术栈的组件能够互相理解和通信。

构建PHP后端API

为了将原始的PHP CLI脚本转换为可供React.js调用的Web API,我们需要进行以下改造:

  1. 接收HTTP请求参数:将CLI参数($_SERVER['argv'])替换为HTTP请求参数(如$_GET或$_POST)。
  2. 输出JSON数据:将纯文本输出改为JSON格式,并设置正确的Content-Type头。
  3. 处理HTTP方法:虽然本示例主要使用GET请求,但在实际应用中,后端应能根据HTTP方法(GET、POST、PUT、DELETE)执行不同的操作。

假设我们有一个data.json文件作为数据源:

立即学习PHP免费学习笔记(深入)”;

[
    { "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 }
]

我们将原有的PHP代码封装为一个API入口文件 api.php:

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转换为数组,以便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;
}

// 获取请求路径和参数
$request_uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$path_segments = explode('/', trim($request_uri, '/'));
$api_endpoint = end($path_segments); // 假设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": { // 新增一个获取所有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);

?>

将 api.php 和 data.json 放在一个支持PHP的Web服务器(如Apache或Nginx)的根目录下。 现在,你可以通过访问类似 http://localhost/api.php/count_by_price_range?from=50&to=200 或 http://localhost/api.php/offers 来测试API。

创建React.js前端应用

接下来,我们创建一个简单的React组件来调用这个PHP API并显示数据。

Sylius开源电子商务平台
Sylius开源电子商务平台

Sylius开源电子商务平台是一个开源的 PHP 电子商务网站框架,基于 Symfony 和 Doctrine 构建,为用户量身定制解决方案。可管理任意复杂的产品和分类,每个产品可以设置不同的税率,支持多种配送方法,集成 Omnipay 在线支付。功能特点:前后端分离Sylius 带有一个强大的 REST API,可以自定义并与您选择的前端或您的微服务架构很好地配合使用。如果您是 Symfony

下载
  1. 初始化React项目 如果你还没有React项目,可以使用Create React App快速搭建:

    npx create-react-app react-php-app
    cd react-php-app
    npm start
  2. 编写React组件 修改 src/App.js 文件,添加一个组件来获取并展示数据:

    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 的基础URL,请根据你的实际部署修改
      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 || []);
    
            // 获取价格区间统计
            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);
    
            // 获取供应商ID统计
            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();
      }, []); // 空数组表示只在组件挂载时运行一次
    
      if (loading) return 
    Loading data...
    ; if (error) return
    Error: {error.message}
    ; return (

    React.js & PHP API 集成示例

    所有商品列表

    {offers.length > 0 ? (
      {offers.map(offer => (
    • ID: {offer.offerId}, Title: {offer.productTitle}, Vendor: {offer.vendorId}, Price: ${offer.price}
    • ))}
    ) : (

    没有商品数据。

    )}

    统计信息

    价格在 $50 到 $200 之间的商品数量: {priceRangeCount}

    供应商ID为 101 的商品数量: {vendorIdCount}

    ); } export default App;

处理跨域资源共享 (CORS)

在开发阶段,React应用通常运行在 http://localhost:3000,而PHP后端可能运行在 http://localhost 或 http://localhost:80。由于它们端口或域名不同,浏览器会阻止React应用直接访问PHP API,这就是所谓的“跨域”问题。

为了解决这个问题,PHP后端需要发送特定的HTTP响应头,告知浏览器允许来自React应用源的请求。在 api.php 的开头,我们已经添加了以下CORS头:

header("Access-Control-Allow-Origin: http://localhost:3000"); // 允许来自React开发服务器的请求
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请求,用于CORS预检
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit();
}
  • Access-Control-Allow-Origin: 指定允许访问资源的源。在生产环境中,应将其设置为你的前端域名,或者根据需要动态设置。* 可以允许所有源,但出于安全考虑,不建议在生产环境中使用。
  • Access-Control-Allow-Methods: 指定允许的HTTP方法。
  • Access-Control-Allow-Headers: 指定在实际请求中可以使用的HTTP头。
  • 当浏览器发送跨域请求时,对于某些复杂的请求(如带有自定义头或非简单方法的请求),会先发送一个OPTIONS请求(预检请求)。后端需要正确响应这个OPTIONS请求。

部署与注意事项

  1. 生产环境CORS配置:在生产环境中,Access-Control-Allow-Origin 应精确设置为你的前端应用的域名(例如 https://your-react-app.com),而不是 http://localhost:3000 或 *。
  2. API路由:对于更复杂的应用,建议使用一个成熟的PHP框架(如Laravel、Symfony)来处理路由、请求验证和ORM,这会使API开发更加高效和健壮。
  3. 安全性
    • 输入验证:始终验证来自前端的所有输入,防止SQL注入、XSS等攻击。
    • 认证与授权:实现用户认证(如JWT、Session)和授权机制,确保只有经过身份验证的用户才能访问受保护的API资源。
    • HTTPS:在生产环境中,始终使用HTTPS来加密前后端之间的通信。
  4. 错误处理:后端API应提供清晰的错误响应(如HTTP状态码和JSON格式的错误信息),前端也应妥善处理这些错误并向用户展示友好的提示。
  5. 性能优化:对于数据量大的API,考虑分页、缓存、数据库索引等优化措施。

总结

通过RESTful API,React.js和PHP可以高效地协同工作,分别专注于前端的用户体验和后端的业务逻辑。构建一个稳健的API涉及请求处理、数据格式化、CORS配置以及安全性考量。遵循本教程的指导,开发者可以顺利地将React.js前端与PHP后端集成,构建出功能完善、结构清晰的Web应用程序。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

1811

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1215

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1106

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

948

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1396

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1229

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1439

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1303

2023.11.13

ip地址修改教程大全
ip地址修改教程大全

本专题整合了ip地址修改教程大全,阅读下面的文章自行寻找合适的解决教程。

121

2025.12.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.7万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.7万人学习

CSS教程
CSS教程

共754课时 | 17万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号