如何使用 Laravel 11 和 React.js 创建 CRUD 应用程序

为什么应该选择 Laravel 和 React.js? React.js 是最流行的前端框架,拥有庞大的社区基础和许多支持的包。 另一方面,Laravel 是 PHP 生态系统中最流行的 MVC 框架。

在此 CRUD 应用程序中,我们将创建一个单页 Laravel 应用程序,其中包含所有前端和后端文件。 我们不会利用惯性; 相反,我们将使用 Vite 捆绑器在 Laravel 中配置 React.js。

但是,您可以将 React 和 Laravel 应用程序创建为单独的项目。 在这种情况下,Laravel 将成为 API 响应的后端服务器,React.js 将成为您的前端,其中包含客户端路由和组件。

以下是使用 Laravel 11 和 React.js 创建 CRUD 应用程序的分步指南:

第 1 步:创建一个新的 Laravel 11项目

使用以下命令创建一个新的 Laravel项目:

composer create-project --prefer-dist laravel/laravel larareact

导航到该文件夹​​。

cd larareact

使用以下命令安装前端依赖项:

npm install

安装下面的附加 npm 包以与 React 一起使用。

npm install --save-dev @vitejs/plugin-react bootstrap bootstrap-icons react react-bootstrap   react-router-dom react-dom

我们将使用 Bootstrap 5 CSS 框架。

一切安装完毕后,我们需要配置 vite.config.js 文件:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';

export default defineConfig({
    plugins: [
        laravel({
            input: ['resources/js/app.jsx'],
            refresh: true,
        }),
        react(),
    ],
});

第2步:配置数据库

转到项目的根目录并编辑 .env 文件以添加 mysql 数据库配置:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=8889
DB_DATABASE=larareact
DB_USERNAME=root
DB_PASSWORD=root

您可以替换主机名、端口、数据库、用户名和密码。

第 3 步:创建模型并迁移

我们将创建一个迁移文件来添加架构,然后将其迁移到数据库表中。

要使用以下命令创建迁移和模型文件“-m”标志:

php artisan make:model Item -m

上面的命令创建了一个名为的迁移文件 [timestamp]_create_items_table.php:

public function up(): void
{
     Schema::create('items', function (Blueprint $table) {
          $table->id();
          $table->string('name');
          $table->integer('price');
          $table->timestamps();
     });
}

转到 cmd 或终端并使用以下命令进行迁移:

php artisan migrate

现在,在 App\Models\Item.php 文件中添加以下代码:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'price'];
}

为了防止 MassAssignmentException,我们需要添加受保护的 $fillable 属性。

第四步:创建控制器文件

要在 Laravel 中创建资源控制器,请使用以下命令:

php artisan make:controller ItemController --resource

在 App\Http\Controllers\ItemController.php 文件中添加以下代码。

json($items);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $item = new Item([
            'name' => $request->get('name'),
            'price' => $request->get('price')
        ]);

        $item->save();
        return response()->json('Successfully added');
    }


    /**
     * Show the form for editing the specified resource.
     */
    public function edit(string $id)
    {
        $item = Item::find($id);
        return response()->json($item);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $id)
    {
        $item = Item::find($id);
        $item->name = $request->get('name');
        $item->price = $request->get('price');
        $item->save();

        return response()->json('Successfully Updated');
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(string $id)
    {
        $item = Item::find($id);
        $item->delete();

        return response()->json('Successfully Deleted');
    }
}

在这个Controller文件中,我们添加了五个函数:

  1. index():它将返回数据库中的所有项目。
  2. store():它将在数据库中存储单个项目。
  3. edit():它将从数据库中获取现有项目。
  4. update():它将更新项目到数据库。
  5. delete():将从数据库中删除该项目。

第 5 步:注册路由

打开routes >> web.php 文件并添加以下代码:

<?php

use App\Http\Controllers\ItemController;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

Route::resource('items', ItemController::class);

保存文件,转到 laravel项目的根目录,然后使用以下命令启动开发服务器:

php artisan serve

第6步:修改视图刀片文件

修改资源>>视图>>welcome.blade.php文件,如下所示:

getLocale() }}">
    
        
        
        
        Laravel React CRUD Application
        @viteReactRefresh
        @vite(['resources/js/app.jsx'])
    

:not(.darkmode--activated) .darkmode-toggle.darkmode-toggle{--wpr-bg-1de530f4-aa64-4c9a-a3a4-cdad00dc4e3f: url('https://0xzx.com/wp-content/plugins/dark-mode-toggle-pro/assets/img/light.svg');}.darkmode--activated .darkmode-toggle.darkmode-toggle{--wpr-bg-355cde9a-7b14-4276-8d47-957d5746edba: url('https://0xzx.com/wp-content/plugins/dark-mode-toggle-pro/assets/img/dark.svg');}.navhot:before{--wpr-bg-6311c85a-923d-472e-993d-18c819432475: url('https://0xzx.com/img/burn-fire-icon.svg');}.coinzilla-fav{--wpr-bg-3aaf91aa-ee4a-4852-aa3f-ebe7ea6296cd: url('https://0xzx.com/img/digital-ads-icon.svg');}.telegram-group{--wpr-bg-ed5b72f3-e05a-4f7d-93e8-2b07e8a13557: url('https://0xzx.com/img/bitcoin-money-icon.svg');}

const rocket_pairs = [{"selector":":not(.darkmode--activated) .darkmode-toggle.darkmode-toggle","style":":not(.darkmode--activated) .darkmode-toggle.darkmode-toggle{--wpr-bg-1de530f4-aa64-4c9a-a3a4-cdad00dc4e3f: url('https:\/\/0xzx.com\/wp-content\/plugins\/dark-mode-toggle-pro\/assets\/img\/light.svg');}","hash":"1de530f4-aa64-4c9a-a3a4-cdad00dc4e3f","url":"https:\/\/0xzx.com\/wp-content\/plugins\/dark-mode-toggle-pro\/assets\/img\/light.svg"},{"selector":".darkmode--activated .darkmode-toggle.darkmode-toggle","style":".darkmode--activated .darkmode-toggle.darkmode-toggle{--wpr-bg-355cde9a-7b14-4276-8d47-957d5746edba: url('https:\/\/0xzx.com\/wp-content\/plugins\/dark-mode-toggle-pro\/assets\/img\/dark.svg');}","hash":"355cde9a-7b14-4276-8d47-957d5746edba","url":"https:\/\/0xzx.com\/wp-content\/plugins\/dark-mode-toggle-pro\/assets\/img\/dark.svg"},{"selector":".navhot","style":".navhot:before{--wpr-bg-6311c85a-923d-472e-993d-18c819432475: url('https:\/\/0xzx.com\/img\/burn-fire-icon.svg');}","hash":"6311c85a-923d-472e-993d-18c819432475","url":"https:\/\/0xzx.com\/img\/burn-fire-icon.svg"},{"selector":".coinzilla-fav","style":".coinzilla-fav{--wpr-bg-3aaf91aa-ee4a-4852-aa3f-ebe7ea6296cd: url('https:\/\/0xzx.com\/img\/digital-ads-icon.svg');}","hash":"3aaf91aa-ee4a-4852-aa3f-ebe7ea6296cd","url":"https:\/\/0xzx.com\/img\/digital-ads-icon.svg"},{"selector":".telegram-group","style":".telegram-group{--wpr-bg-ed5b72f3-e05a-4f7d-93e8-2b07e8a13557: url('https:\/\/0xzx.com\/img\/bitcoin-money-icon.svg');}","hash":"ed5b72f3-e05a-4f7d-93e8-2b07e8a13557","url":"https:\/\/0xzx.com\/img\/bitcoin-money-icon.svg"}]; const rocket_excluded_pairs = [];
    
        
window.Laravel = csrf_token(), ]); ?> var rocket_lcp_data = {"ajax_url":"https:\/\/0xzx.com\/wp-admin\/admin-ajax.php","nonce":"f6439116ee","url":"https:\/\/0xzx.com\/2024041521324303668.html","is_mobile":false,"elements":"img, video, picture, p, main, div, li, svg","width_threshold":1600,"height_threshold":700,"debug":null}

在此代码中,我们使用 @viteReactRefresh 和 @vite 指令将 React 视图正确包含在我们的 Laravel项目中。

另外,修改 resources >> js >> bootstrap.js 文件:

import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-icons/font/bootstrap-icons.css';

import bootstrap from 'bootstrap/dist/js/bootstrap';
window.bootstrap = bootstrap;

import axios from 'axios';
window.axios = axios;

第7步:创建导航组件

在 resources >> js 文件夹中创建一个名为 Components 的文件夹,并在该文件夹中创建一个名为“Navigation.jsx”的 jsx 文件。 添加以下代码:

import { NavLink } from "react-router-dom";

export default function Navigation() {
    return (
        
    )
}

我们将把这个组件导入到主文件中,并将其包含在我们将来创建的所有页面中。

步骤 8:创建三个组件,用于列出项目、添加项目和更新项目

在 resources >> js >> Components 文件夹中,创建三个新文件:

  1. 创建.jsx
  2. 更新.jsx
  3. 索引.jsx

在 Create.jsx 文件中添加以下代码:

import React, { useState } from "react";
import { useNavigate } from "react-router-dom";

function Create() {
    const [item, setItem] = useState({ name: '', price: '' });
    const [successMessage, setSuccessMessage] = useState('');
    const navigate = useNavigate();

    const addItem = async (e) => {
        e.preventDefault();
        const uri = 'http://localhost:8000/items';

        try {
            await axios.post(uri, item);
            setSuccessMessage('Item added successfully!');
            setTimeout(() => {
                setSuccessMessage('');
                navigate('/');
            }, 1000);
        } catch (error) {
            console.error('Error adding item:', error);
        }
    };

    const handleInputChange = (e) => {
        const { name, value } = e.target;
        setItem(prevItem => ({ ...prevItem, [name]: value }));
    };

    return (
        

Create An Item

{successMessage && (
{successMessage} )}
); } export default Create;

在此代码中,我们创建了一个引导表单。 提交表单数据后,我们将包含数据的 POST 请求发送到 Laravel 服务器。

在 Update.jsx 文件中添加以下代码:

import React, { useEffect, useState } from "react";
import { useParams, useNavigate } from "react-router-dom";

function Update() {
    const [item, setItem] = useState({ name: '', price: '' });
    const [successMessage, setSuccessMessage] = useState('');
    const params = useParams();
    const navigate = useNavigate();

    useEffect(() => {
        const getItem = async () => {
            try {
                const uri = `http://localhost:8000/items/${params.id}/edit`;
                const response = await axios.get(uri);
                setItem(response.data);
            } catch (error) {
                console.error("Failed to fetch item:", error);
            }
        };

        getItem();
    }, [params.id]);

    const updateItem = async (e) => {
        e.preventDefault();
        const uri = `http://localhost:8000/items/${params.id}`;
        try {
            await axios.patch(uri, item);
            setSuccessMessage('Item Updated Successfully!');
            setTimeout(() => {
                setSuccessMessage('');
                navigate('/'); // Replace '/' with your actual route name for the item list
            }, 1000);
        } catch (error) {
            console.error("Failed to update item:", error);
        }
    };

    const handleInputChange = (e) => {
        const { name, value } = e.target;
        setItem(prevItem => ({ ...prevItem, [name]: value }));
    };

    return (
        

Edit an Item

{successMessage && (
{successMessage} )}
); } export default Update;

在此代码中,我们从数据库中获取现有数据,将其放入文本框中,当我们完成数据编辑后,它向 Laravel 服务器发送 Patch 请求以更新数据库中的数据。

在 Index.jsx 文件中添加以下代码:

import React, { useEffect, useState } from "react";
import { useNavigate, Link } from "react-router-dom";

import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';

function Index() {
    const [items, setItems] = useState([]);
    const [successMessage, setSuccessMessage] = useState('');
    const [showDeleteModal, setShowDeleteModal] = useState(false);
    const [itemIdToDelete, setItemIdToDelete] = useState(null);
    const navigate = useNavigate();

    useEffect(() => {
        const fetchItems = async () => {
            try {
                const uri = 'http://localhost:8000/items';
                const response = await axios.get(uri);
                setItems(response.data);
            } catch (error) {
                console.error('Error fetching items:', error);
            }
        };

        fetchItems();
    }, []);

    const openDeleteConfirmation = (id) => {
        setItemIdToDelete(id);
        setShowDeleteModal(true);
    };

    const closeModal = () => {
        setShowDeleteModal(false);
    };

    const confirmDelete = async () => {
        if (itemIdToDelete !== null) {
            try {
                const uri = `http://localhost:8000/items/${itemIdToDelete}`;
                await axios.delete(uri);
                setItems(currentItems => currentItems.filter((item) => item.id !== itemIdToDelete));
                setSuccessMessage('Item deleted successfully!');
                setTimeout(() => {
                    setSuccessMessage('');
                    navigate('/'); // Replace '/' with your actual route name for the item list
                }, 1000);
                closeModal();
            } catch (error) {
                console.error('Error deleting item:', error);
            }
        }
    };

    return (
        

Items

{successMessage && (
{successMessage} )}
Create New Item
{items.map((item) => ( ))}
ID Item Name Item Price Actions
{item.id} {item.name} {item.price} Edit
{/* Delete Confirmation Modal */} Confirm Delete Are you sure you want to delete this item? ); } export default Index;

在这个长文件中,我们将获取所有项目并使用“编辑”和“删除”按钮以列表格式显示它们。

如果单击“编辑”按钮,它将显示 Update.jsx 视图。

如果单击“删除”按钮,将打开一个包含确认消息的对话框。 如果您确认,数据将从数据库中删除。

第9步:配置前端路由

在 resources >> js 文件夹中创建一个名为 MainApp.jsx 的文件并添加以下代码。

import { Routes, Route } from "react-router-dom";

import Navigation from "./components/Navigation";

import Create from "./components/Create";
import Update from "./components/Update";
import Index from "./components/Index";

function App() {
  return (
    
<Route path="/" element={} /> <Route path="/create" element={} /> <Route path="/edit/:id" element={} /> ) } export default App;

在此代码中,我们声明并定义应用程序的路由。

我们为列表页面分配了一个“/” URL。

要创建项目,请使用“/create”URL。

在 resources >> js 文件夹中创建一个 app.jsx 文件,并在 app.jsx 文件中导入 MainApp 模块。

import './bootstrap'
import '../css/app.css'

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './MainApp';

import { BrowserRouter } from "react-router-dom"

ReactDOM.createRoot(document.getElementById('root')).render(
  
    
      
    
  ,
)

这是我们包含在welcome.blade.php 文件中的主文件。 这意味着我们现在已经将 React.js 视图注册到 Laravel 应用程序。

我的资源 >>​​ css >> app.css 文件如下所示:

.bg-gradient-primary {
    background: linear-gradient(45deg, #007bff, #6610f2);
}

保存文件,转到项目的根目录,然后使用以下命令运行 vite 开发服务器:

npm run dev

第10步:运行项目

确保您正在运行两个开发服务器:

  1. Laravel 开发服务器(php artisanserve)
  2. Vite开发服务器(npm run dev)

要创建项目,您需要访问此 URL:http://localhost:8000/create

创建页面如下所示:

在 React 中创建表单在 React 中创建表单

让我们创建六个项目。 当您每次创建一个项目时,您将被重定向到列表页面(http://localhost:8000/)。

创建 6 个项目后,我们的列表页面如下所示:

React 中的列表页面

如果单击“编辑”按钮,您将被重定向到更新页面,如下所示:

在 React 中更新页面

如果您更新商品价格,它将在数据库中更新,您将看到成功消息并被重定向到列表页面。

如果您尝试删除某个项目,系统将提示您确认,如下所示:

删除确认对话框

如果按删除按钮,则会从数据库中删除该项目。

删除项目后的列表

就是这样 这是 Laravel 11 中使用 React.js 不使用惯性的完整 CRUD 操作。

在这个项目中,我们没有将前端和后端做成独立的项目; 我们在同一个文件夹中完成了它。

但是,您可以选择采取不同的路径,两个项目都不同,并且您将使用 Laravel 作为后端 API。

这是 Github 上的完整代码。

帖子浏览次数:2 分享于:

克鲁纳尔·拉蒂亚

Krunal 在计算机科学领域拥有八年多的职业生涯,他的专业知识植根于坚实的实践经验基础,辅之以对知识的不断追求。

Laravel 11 CRUD:创建、读取、更新、删除的有趣旅程

资讯来源:由0x资讯编译自APPDIVIDEND,版权归作者Krunal Lathiya所有,未经许可,不得转载

资讯来源:由a0资讯编译自THECOINREPUBLIC。版权归作者A0资讯所有,未经许可,不得转载

上一篇 2024年 5月 31日
下一篇 2024年 5月 31日

相关推荐