😅Build a Simple Module Laravel Project (ok)
https://github.com/balanchi/Simple-Module-Laravel-Project/tree/master
Last updated
https://github.com/balanchi/Simple-Module-Laravel-Project/tree/master
Last updated
C:\xampp82\htdocs\lva4\Modules\Category\Database\Migrations\2023_10_23_043505_create_categories_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('categories');
}
};
C:\xampp82\htdocs\lva4\Modules\Category\Entities\Category.php
<?php
namespace Modules\Category\Entities;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Category extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = [
'name',
'description'
];
protected $guarded = ['id'];
protected static function newFactory()
{
// return \Modules\Category\Database\factories\CategoryFactory::new();
}
}
C:\xampp82\htdocs\lva4\Modules\Category\Http\Controllers\CategoryController.php
<?php
namespace Modules\Category\Http\Controllers;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\Category\Entities\Category;
use Modules\Category\Http\Requests\CreateCategoryRequest;
use Modules\Category\Http\Requests\UpdateCategoryRequest;
class CategoryController extends Controller
{
/**
* Display a listing of the resource.
* @return Renderable
*/
public function index()
{
$categories = Category::all();
return view('category::index', compact('categories'));
}
/**
* Show the form for creating a new resource.
* @return Renderable
*/
public function create()
{
return view('category::create');
}
/**
* Store a newly created resource in storage.
* @param Request $request
* @return Renderable
*/
public function store(CreateCategoryRequest $request)
{
$inputs = $request->all();
Category::create($inputs);
return to_route('category.index');
}
/**
* Show the specified resource.
* @param int $id
* @return Renderable
*/
public function show($id)
{
return view('category::show');
}
/**
* Show the form for editing the specified resource.
* @param int $id
* @return Renderable
*/
public function edit(Category $category)
{
return view('category::edit', compact('category'));
}
/**
* Update the specified resource in storage.
* @param Request $request
* @param int $id
* @return Renderable
*/
public function update(UpdateCategoryRequest $request, Category $category)
{
$inputs = $request->all();
$category->update(['name' => $inputs['name'], 'description' => $inputs['description']]);
return to_route('category.index');
}
/**
* Remove the specified resource from storage.
* @param int $id
* @return Renderable
*/
public function destroy(Category $category)
{
$category->delete();
return back();
}
}
C:\xampp82\htdocs\lva4\Modules\Category\Http\Requests\CreateCategoryRequest.php
<?php
namespace Modules\Category\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CreateCategoryRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|max:120|min:2|regex:/^[ا-یa-zA-Z0-9\-۰-۹ء-ي., ]+$/u',
'description' => 'required|max:1200|min:2|regex:/^[ا-یa-zA-Z0-9\-۰-۹ء-ي., ]+$/u',
];
}
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
}
C:\xampp82\htdocs\lva4\Modules\Category\Http\Requests\UpdateCategoryRequest.php
<?php
namespace Modules\Category\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateCategoryRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|max:120|min:2|regex:/^[ا-یa-zA-Z0-9\-۰-۹ء-ي., ]+$/u',
'description' => 'required|max:1200|min:2|regex:/^[ا-یa-zA-Z0-9\-۰-۹ء-ي., ]+$/u',
];
}
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
}
C:\xampp82\htdocs\lva4\Modules\Category\Resources\views\layouts\master.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Module Category</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
@if ($errors->any())
<div class="text-bg-danger p-4 m-3 rounded">
@foreach ($errors->all() as $error)
<div>{{ $error }}</div>
@endforeach
</div>
@endif
@yield('content')
</body>
</html>
C:\xampp82\htdocs\lva4\Modules\Category\Resources\views\create.blade.php
@extends('category::layouts.master')
@section('content')
<div class="container mt-3">
<h2>Create Category</h2>
<form action="{{ route('category.store') }}" method="post">
@csrf
<div class="mb-3 mt-3">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" placeholder="Enter Name" name="name">
</div>
<div class="mb-3">
<label for="description">Description:</label>
<input type="text" class="form-control" id="description" placeholder="Enter Description" name="description">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
@endsection
C:\xampp82\htdocs\lva4\Modules\Category\Resources\views\edit.blade.php
@extends('category::layouts.master')
@section('content')
<div class="container mt-3">
<h2>Edit Category</h2>
<form action="{{ route('category.update', $category) }}" method="post">
@csrf
@method('PUT')
<div class="mb-3 mt-3">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" value="{{ old('name', $category->name) }}" name="name">
</div>
<div class="mb-3">
<label for="description">Description:</label>
<input type="text" class="form-control" id="description" value="{{ old('description', $category->description) }}"
name="description">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
@endsection
C:\xampp82\htdocs\lva4\Modules\Category\Resources\views\index.blade.php
@extends('category::layouts.master')
@section('content')
<div class="container mt-3">
<h2>Category</h2>
<div class="d-flex justify-content-end">
<a class="btn btn-info" href="{{ route('category.create') }}">create</a>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Description</th>
<th>Setting</th>
</tr>
</thead>
<tbody>
@foreach ($categories as $category)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $category->name }}</td>
<td>{{ $category->description }}</td>
<td>
<form class="d-inline" action="{{ route('category.destroy', $category)}}" method="post">
@csrf
@method('DELETE')
<button class="btn btn-danger">Delete</button>
</form>
<a class="btn btn-warning" href="{{ route('category.edit', $category) }}">Edit</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endsection
C:\xampp82\htdocs\lva4\Modules\Category\Routes\web.php
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
use Modules\Category\Http\Controllers\CategoryController;
Route::resource('category', CategoryController::class);
C:\xampp82\htdocs\lva4\composer.json
{
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"require": {
"php": "^8.1",
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.0",
"laravel/sanctum": "^3.2",
"laravel/tinker": "^2.8",
"laravel/ui": "^4.2",
"laravelcollective/html": "^6.4",
"nwidart/laravel-modules": "^10.0",
"spatie/laravel-medialibrary": "^10.13",
"unisharp/laravel-filemanager": "^2.6"
},
"require-dev": {
"barryvdh/laravel-debugbar": "^3.8",
"fakerphp/faker": "^1.9.1",
"laravel/pint": "^1.0",
"laravel/sail": "^1.18",
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^7.0",
"phpunit/phpunit": "^10.0",
"spatie/laravel-ignition": "^2.0",
"sven/artisan-view": "^3.6"
},
"autoload": {
"psr-4": {
"App\\": "app/",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/",
"Modules\\": "Modules/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-update-cmd": [
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
],
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi"
]
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
},
"minimum-stability": "stable",
"prefer-stable": true
}
C:\xampp82\htdocs\lva4\Modules\Post\Database\Migrations\2023_10_23_061430_create_posts_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('slug')->nullable();
$table->text('content')->nullable();
$table->string('featured_image')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
};
C:\xampp82\htdocs\lva4\Modules\Post\Entities\Post.php
<?php
namespace Modules\Post\Entities;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Post extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = [
'name',
'slug',
'content',
'featured_image'
];
protected static function newFactory()
{
// return \Modules\Post\Database\factories\PostFactory::new();
}
}
C:\xampp82\htdocs\lva4\Modules\Post\Http\Controllers\PostController.php
<?php
namespace Modules\Post\Http\Controllers;
use Illuminate\Contracts\Support\Renderable;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\Post\Entities\Post;
use Modules\Post\Http\Requests\PostsRequest;
class PostController extends Controller
{
/**
* Display a listing of the resource.
* @return Renderable
*/
public function index()
{
$posts = Post::all();
return view('post::index', compact('posts'));
}
/**
* Show the form for creating a new resource.
* @return Renderable
*/
public function create()
{
return view('post::create');
}
/**
* Store a newly created resource in storage.
* @param Request $request
* @return Renderable
*/
public function store(PostsRequest $request)
{
$inputs = $request->except('files');
Post::create($inputs);
return back();
}
/**
* Show the specified resource.
* @param int $id
* @return Renderable
*/
public function show($id)
{
return view('post::show');
}
/**
* Show the form for editing the specified resource.
* @param int $id
* @return Renderable
*/
public function edit($id)
{
return view('post::edit');
}
/**
* Update the specified resource in storage.
* @param Request $request
* @param int $id
* @return Renderable
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
* @param int $id
* @return Renderable
*/
public function destroy($id)
{
//
}
}
C:\xampp82\htdocs\lva4\Modules\Post\Http\Requests\PostsRequest.php
<?php
namespace Modules\Post\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class PostsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|max:191',
'slug' => 'nullable|max:191',
'content' => 'required',
'featured_image' => 'required|max:191'
];
}
}
C:\xampp82\htdocs\lva4\Modules\Post\Resources\views\layouts\master.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Module Category</title>
<script src="{{ asset('vendor/jquery/jquery-3.6.4.min.js') }}"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
@stack('after-styles')
</head>
<body>
@if ($errors->any())
<div class="text-bg-danger p-4 m-3 rounded">
@foreach ($errors->all() as $error)
<div>{{ $error }}</div>
@endforeach
</div>
@endif
@yield('content')
@stack('after-scripts')
</body>
</html>
C:\xampp82\htdocs\lva4\Modules\Post\Resources\views\create.blade.php
@extends('post::layouts.master')
@section('content')
<div class="container mt-3">
<h2>Create Category</h2>
<form action="{{ route('post.store') }}" method="post">
@csrf
<div class="mb-3 mt-3">
<label for="name">Name:</label>
<input type="text" class="form-control" id="name" placeholder="Enter Name" name="name">
</div>
<div class="mb-3">
<label for="slug">Description:</label>
<input type="text" class="form-control" id="slug" placeholder="Enter Slug" name="slug">
</div>
<div class="mb-3">
<label for="content">Description:</label>
<textarea class="form-control" name="content" id="content" placeholder="Content" required></textarea>
</div>
<div class="mb-3">
<label for="featured_image">Description:</label>
<div class="form-group">
<label for="featured_image">Featured Image</label> <span class="text-danger">*</span>
<div class="input-group mb-3">
<input class="form-control" type="text" name="featured_image" id="featured_image" placeholder="Featured Image"
required aria-label="Image" aria-describedby="button-image">
<div class="input-group-append">
<button class="btn btn-info" type="button" id="button-image" data-input="featured_image"><i
class="fas fa-folder-open"></i> Browse</button>
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
@endsection
@push('after-styles')
<!-- File Manager -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.20/summernote-lite.min.css" rel="stylesheet">
<style>
.note-editor.note-frame :after {
display: none;
}
.note-editor .note-toolbar .note-dropdown-menu,
.note-popover .popover-content .note-dropdown-menu {
min-width: 180px;
}
</style>
@endpush
@push ('after-scripts')
<script type="module" src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.20/summernote-lite.min.js"></script>
<script type="module">
// Define function to open filemanager window
var lfm = function(options, cb) {
var route_prefix = (options && options.prefix) ? options.prefix : '/laravel-filemanager';
window.open(route_prefix + '?type=' + options.type || 'file', 'FileManager', 'width=900,height=600');
window.SetUrl = cb;
};
// Define LFM summernote button
var LFMButton = function(context) {
var ui = $.summernote.ui;
var button = ui.button({
contents: '<i class="note-icon-picture"></i> ',
tooltip: 'Insert image with filemanager',
click: function() {
lfm({
type: 'image',
prefix: '/laravel-filemanager'
}, function(lfmItems, path) {
lfmItems.forEach(function(lfmItem) {
context.invoke('insertImage', lfmItem.url);
});
});
}
});
return button.render();
};
$('#content').summernote({
height: 120,
toolbar: [
['style', ['style']],
['font', ['fontname', 'fontsize', 'bold', 'underline', 'clear']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['table', ['table']],
['insert', ['link', 'lfm', 'video']],
['view', ['codeview', 'undo', 'redo', 'help']],
],
buttons: {
lfm: LFMButton
}
});
</script>
<script type="module" src="{{ asset('vendor/laravel-filemanager/js/stand-alone-button.js') }}"></script>
<script type="module">
$('#button-image').filemanager('image');
</script>
@endpush
C:\xampp82\htdocs\lva4\Modules\Post\Resources\views\index.blade.php
@extends('category::layouts.master')
@section('content')
<div class="container mt-3">
<h2>Category</h2>
<div class="d-flex justify-content-end">
<a class="btn btn-info" href="{{ route('post.create') }}">create</a>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Slug</th>
<th>Featured</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach ($posts as $post)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $post->name }}</td>
<td>{{ $post->slug }}</td>
<td>{{ $post->featured_image }}</td>
<td>
<form class="d-inline" action="{{ route('post.destroy', $post)}}" method="post">
@csrf
@method('DELETE')
<button class="btn btn-danger">Delete</button>
</form>
<a class="btn btn-warning" href="{{ route('post.edit', $post) }}">Edit</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endsection
C:\xampp82\htdocs\lva4\Modules\Post\Routes\web.php
<?php
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
use Modules\Post\Http\Controllers\PostController;
Route::resource('post', PostController::class);