Download Laravel App
composer create-project --prefer-dist laravel/laravel my-app
C:\xampp\htdocs\laravel10project>composer create-project laravel/laravel laravel10project
Connecting our Database
open .env file root directory.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laraveldb
DB_USERNAME=root
DB_PASSWORD=
Create Model and Migration
C:\xampp\htdocs\laravel\laravelproject>php artisan make:model Product -m
A new file named Product.php will be created in the app directory and database/migrations directory to generate the table in our database
app/Models/Product.php
//app/Models/Product.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
protected $fillable = [
'name',
'image',
'description'
];
}
database\migrations\create_products_table.php
//database\migrations\create_products_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('image');
$table->text('description');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('products');
}
};
Database Migration php artisan migrate
C:\xampp\htdocs\laravel\laravel10project>php artisan migrate
Migration table created successfully.
check database table
Create Controller and Request
C:\xampp\htdocs\laravel\laravel10project>php artisan make:controller ProductController -r
app\Http\Controllers\ProductController.php
//app\Http\Controllers\ProductController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Product;
use App\Http\Requests\ProductStoreRequest;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage; //php artisan storage:link = php artisan storage:link = http://127.0.0.1:8000/storage/1.jpg
class ProductController extends Controller
{
public function index()
{
// All Product
$products = Product::all();
// Return Json Response
return response()->json([
'products' => $products
],200);
}
public function store(ProductStoreRequest $request)
{
try {
$imageName = Str::random(32).".".$request->image->getClientOriginalExtension();
// Create Product
Product::create([
'name' => $request->name,
'image' => $imageName,
'description' => $request->description
]);
// Save Image in Storage folder
Storage::disk('public')->put($imageName, file_get_contents($request->image));
// Return Json Response
return response()->json([
'message' => "Product successfully created."
],200);
} catch (\Exception $e) {
// Return Json Response
return response()->json([
'message' => "Something went really wrong!"
],500);
}
}
public function show($id)
{
// Product Detail
$product = Product::find($id);
if(!$product){
return response()->json([
'message'=>'Product Not Found.'
],404);
}
// Return Json Response
return response()->json([
'product' => $product
],200);
}
public function update(ProductStoreRequest $request, $id)
{
try {
// Find product
$product = Product::find($id);
if(!$product){
return response()->json([
'message'=>'Product Not Found.'
],404);
}
//echo "request : $request->image";
$product->name = $request->name;
$product->description = $request->description;
if($request->image) {
// Public storage
$storage = Storage::disk('public');
// Old iamge delete
if($storage->exists($product->image))
$storage->delete($product->image);
// Image name
$imageName = Str::random(32).".".$request->image->getClientOriginalExtension();
$product->image = $imageName;
// Image save in public folder
$storage->put($imageName, file_get_contents($request->image));
}
// Update Product
$product->save();
// Return Json Response
return response()->json([
'message' => "Product successfully updated."
],200);
} catch (\Exception $e) {
// Return Json Response
return response()->json([
'message' => "Something went really wrong!"
],500);
}
}
public function destroy($id)
{
// Detail
$product = Product::find($id);
if(!$product){
return response()->json([
'message'=>'Product Not Found.'
],404);
}
// Public storage
$storage = Storage::disk('public');
// Iamge delete
if($storage->exists($product->image))
$storage->delete($product->image);
// Delete Product
$product->delete();
// Return Json Response
return response()->json([
'message' => "Product successfully deleted."
],200);
}
}
Next, create a Request C:\xampp\htdocs\laravel\laravel10project>php artisan make:request ProductStoreRequest
app\Http\Requests\ProductStoreRequest.php
//app\Http\Requests\ProductStoreRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ProductStoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
//return false;
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
*/
public function rules(): array
{
if(request()->isMethod('post')) {
return [
'name' => 'required|string|max:258',
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'description' => 'required|string'
];
} else {
return [
'name' => 'required|string|max:258',
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'description' => 'required|string'
];
}
}
public function messages()
{
if(request()->isMethod('post')) {
return [
'name.required' => 'Name is required!',
'image.required' => 'Image is required!',
'description.required' => 'Descritpion is required!'
];
} else {
return [
'name.required' => 'Name is required!',
'description.required' => 'Descritpion is required!'
];
}
}
}
Routes All API requests will need the header Accept: application/json.
open routes/api.php and update the following code
routes\api.php
//routes\api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
Route::get('products', [ProductController::class, 'index']);
Route::get('products/{id}', [ProductController::class, 'show']);
Route::post('products', [ProductController::class, 'store']);
Route::put('productsupdate/{id}', [ProductController::class, 'update']);
Route::delete('productdelete/{id}', [ProductController::class, 'destroy']);
generate symbolic links C:\xampp\htdocs\laravel\laravel10project>php artisan storage:link Run C:\xampp\htdocs\laravel\laravel10project>php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
open postman new request
GET api/products Index All products return.
GET : http://127.0.0.1:8000/api/products
GET api/products/{id} Show Detail of a particular post by ID.
GET : http://127.0.0.1:8000/api/products/1
POST api/products Store Create a new product.
POST : http://127.0.0.1:8000/api/products
body
key value
name Iphone 13
image iphone.jpg = file
description product description
PUT api/products/{id} Update Update a particular product by ID.
POST : http://127.0.0.1:8000/api/products/1
body
key value
_method PUT
name Iphone 13 updated
image iphone.jpg = file
description product description updated
DELETE api/products/{id} Destroy Delete a particular product by ID.
DELETE : http://127.0.0.1:8000/api/products/1
React JS
https://create-react-app.dev/
Create Project
C:\react-js>npx create-react-app myreactdev
Run
C:\react-js\myreactdev> npm start
https://github.com/axios/axios
Installing the Axios Client
$ npm install axios
Install React Router Dom
https://www.npmjs.com/package/react-router-dom
C:\react-js\myreactdev>npm i react-router-dom --save
C:\reactdev\myreactdev>npm install axios
C:\react-js\myreactdev\src\App.js
//C:\react-js\myreactdev\src\App.js
import React, { } from "react";
import "./App.css";
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import Header from './Component/Header';
import Home from './Component/Home';
import Addproduct from './Component/Addproduct';
import Productlist from './Component/Productlist';
import EditProduct from './Component/EditProduct';
import Footer from './Component/Footer';
function App() {
return (
<div className="App">
<Router>
<Header/>
<Routes>
<Route exact path="/" element={<Home/>}/>
<Route exact path="/addproduct" element={<Addproduct/>}/>
<Route exact path="/productlist" element={<Productlist/>}/>
<Route path="editproduct/:id/edit" element={<EditProduct />} />
</Routes>
<Footer/>
</Router>
</div>
);
}
export default App;
C:\react-js\myreactdev\src\Component\Header.js
//C:\react-js\myreactdev\src\Component\Header.js
import React, { } from "react";
import {NavLink} from 'react-router-dom';
function Header()
{
return(
<React.Fragment>
<nav className="navbar navbar-expand-lg bg-primary" >
<div className="container">
<NavLink to="/" className="navbar-brand">Cairocoders</NavLink>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav me-auto mb-2 mb-lg-0">
<li className="nav-item">
<NavLink to="/" className="nav-link" aria-current="page">Home</NavLink>
</li>
<li className="nav-item">
<NavLink to="/productlist" className="nav-link"> Product List</NavLink>
</li>
<li className="nav-item">
<NavLink to="/addproduct" className="nav-link">Add Product</NavLink>
</li>
</ul>
</div>
</div>
</nav>
</React.Fragment>
);
}
export default Header;
C:\react-js\myreactdev\src\Component\Home.js
//C:\react-js\myreactdev\src\Component\Home.js
import React, { } from "react";
function Home()
{
return(
<React.Fragment>
<div className="container">
<div className="row">
<div className="col-md-12">
<h1>React Laravel 10 REST API Crud (Create, Read, Update and Delete) with Upload image</h1>
</div>
</div>
</div>
</React.Fragment>
);
}
export default Home;
C:\react-js\myreactdev\src\Component\Footer.js
//C:\react-js\myreactdev\src\Component\Footer.js
import React, { } from "react";
function Footer()
{
return(
<React.Fragment>
<footer className="bg-primary fixed-bottom">
<div className="container">
<div className="row">
<div className="col-md-12 mt-3">
<p>Copyright @2023 Cairocoders</p>
</div>
</div>
</div>
</footer>
</React.Fragment>
);
}
export default Footer;
C:\react-js\myreactdev\src\Component\Addproduct.js
//C:\react-js\myreactdev\src\Component\Addproduct.js
import React, { useState } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
function Addproduct()
{
const navigate = useNavigate();
const[txtname, setName]= useState('');
const[txtdescription, setdescription]= useState('');
const[fileimage, setPhoto]= useState('');
const[message, setMessage]= useState('');
const uploadProduct= async()=>{
console.log(fileimage)
const formData= new FormData();
formData.append('name', txtname);
formData.append('description',txtdescription);
formData.append('image', fileimage);
const responce= await axios.post("http://127.0.0.1:8000/api/products", formData, {
headers:{'Content-Type':"multipart/form-data"},
} );
if(responce)
{
console.log(responce)
setMessage(responce.message); //"message": "Product successfully created."
setTimeout(()=>{
navigate('/productlist');
}, 2000);
}
}
const handleSubmit= async(e)=>{
e.preventDefault();
await uploadProduct();
}
return(
<React.Fragment>
<div className="container">
<div className="row">
<div className="col-md-8 mt-4">
<h5 className="mb-4">Add Product </h5>
<p className="text-warning">{ message}</p>
<form onSubmit={ handleSubmit}>
<div className="mb-3 row">
<label className="col-sm-3">Product Title </label>
<div className="col-sm-9">
<input type="text" className="form-control" onChange={ (e)=>setName(e.target.value)}/>
</div>
</div>
<div className="mb-3 row">
<label className="col-sm-3">Description </label>
<div className="col-sm-9">
<input type="text" className="form-control" onChange={(e)=>setdescription(e.target.value)} />
</div>
</div>
<div className="mb-3 row">
<label className="col-sm-3">Product Image</label>
<div className="col-sm-9">
<input type="file" className="form-control" onChange={(e)=>setPhoto(e.target.files[0])} />
</div>
</div>
<div className="mb-3 row">
<label className="col-sm-3"></label>
<div className="col-sm-9">
<button type="submit" className="btn btn-success">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</React.Fragment>
);
}
export default Addproduct;
C:\react-js\myreactdev\src\Component\Productlist.js
//C:\react-js\myreactdev\src\Component\Productlist.js
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
function Productlist()
{
const[product, setProduct]= useState([]);
useEffect( ()=>{
const getProduct= ()=>{
fetch("http://127.0.0.1:8000/api/products")
.then(res=>{ return res.json()})
.then(response=>{
console.log(response.products)
setProduct(response.products)
})
.catch(error=>{ console.log(error)});
}
getProduct();
},[]);
const deleteProduct = (id) => {
axios.delete('http://127.0.0.1:8000/api/productdelete/'+id).then(function(response){
console.log(response.data);
alert("Successfully Deleted");
});
}
return(
<React.Fragment>
<div className="container container_overflow">
<div className="row">
<div className="col-12">
<h5 className="mb-4">Product List</h5>
<p className="text-danger"> </p>
<table className="table table-bordered">
<thead>
<tr>
<th scope="col">Sr.No</th>
<th scope="col">Product Title</th>
<th scope="col">Product Description</th>
<th scope="col">Product Image</th>
<th scope="col" width="200">Action</th>
</tr>
</thead>
<tbody>
{
product.map((pdata, index)=>(
<tr key={index}>
<td>{index+1 } </td>
<td>{pdata.name } </td>
<td>{pdata.description } </td>
<td><img src={`http://127.0.0.1:8000/storage/${pdata.image}`} alt="" height={50} width={90} /></td>
<td>
<Link to={`/editproduct/${pdata.id}/edit`} className="btn btn-success mx-2">Edit</Link>
<button onClick={() => deleteProduct(pdata.id)} className="btn btn-danger">Delete</button>
</td>
</tr>
))
}
</tbody>
</table>
</div>
</div>
</div>
</React.Fragment>
);
}
export default Productlist;
C:\react-js\myreactdev\src\Component\EditProduct.js
//C:\react-js\myreactdev\src\Component\EditProduct.js
import React, { useState, useEffect } from "react";
import axios from "axios";
import { useParams, useNavigate } from "react-router-dom";
function EditProduct()
{
const navigate = useNavigate();
const {id}= useParams();
const[message, setMessage]= useState('');
const [inputs, setInputs] = useState([]);
const [fileimage, setPhoto]= useState('');
const handleChange = (event) => {
const name = event.target.name;
const value = event.target.value;
setInputs(values => ({...values, [name]: value}));
}
const uploadProduct= async()=>{
const formData= new FormData();
formData.append('_method', 'PUT');
formData.append('name', inputs.name);
formData.append('description',inputs.description);
formData.append('image', fileimage);
const response= await axios.post("http://127.0.0.1:8000/api/productsupdate/"+id, formData, {
headers:{'Content-Type':"multipart/form-data"},
} );
setMessage(response.data.message); //"message": "Product successfully updated.."
console.log(response)
setTimeout(()=>{
navigate('/productlist');
}, 2000);
}
const handleSubmit= async(e)=>{
e.preventDefault();
await uploadProduct();
}
useEffect(() => {
getproduct();
}, []);
function getproduct() {
axios.get('http://127.0.0.1:8000/api/products/'+id).then(function(response) {
console.log(response);
setInputs(response.data.product);
});
}
return(
<React.Fragment>
<div className="container">
<div className="row">
<div className="col-md-8 mt-4">
<h5 className="mb-4">Edit Product </h5>
<p className="text-success"><b>{ message }</b></p>
<form onSubmit={ handleSubmit}>
<div className="mb-3 row">
<label className="col-sm-3">Product Title </label>
<div className="col-sm-9">
<input type="text" value={inputs.name} className="form-control" name="name" onChange={ handleChange}/>
</div>
</div>
<div className="mb-3 row">
<label className="col-sm-3">Description </label>
<div className="col-sm-9">
<input type="text" value={inputs.description} className="form-control" name="description" onChange={ handleChange} />
</div>
</div>
<div className="mb-3 row">
<label className="col-sm-3">Product Image</label>
<div className="col-sm-9">
<img src={`http://127.0.0.1:8000/storage/${inputs.image}`} alt="" height={300} width={300} />
<input type="file" className="form-control" onChange={(e)=>setPhoto(e.target.files[0])} />
</div>
</div>
<div className="mb-3 row">
<label className="col-sm-3"></label>
<div className="col-sm-9">
<button type="submit" className="btn btn-success">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</React.Fragment>
);
}
export default EditProduct;
react-js\myreactdev\src\App.css
//react-js\myreactdev\src\App.css
body{
background:#eee;
}
.nav-link {
color:#ffffff;
}
.navbar-brand{
color:#ffffff;
}
.fixed-bottom{
color:#ffffff;
}
react-js\myreactdev\public\index.html
//react-js\myreactdev\public\index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"/>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
Run C:\react-j\myreactdev>npm start http://localhost:3000/
