| Install | |
|---|---|
composer require amaraa019/laravel-universal-crud |
|
| Latest Version: | v1.1.3 |
| PHP: | ^8.1|^8.2|^8.3 |
Laravel 10, 11, 12-т зориулсан, Breeze (React) орчинд ажиллах, бүх төрлийн CRUD үйлдлийг хялбархан үүсгэх боломжийг олгодог сан. Энэхүү сан нь Shadcn/UI болон TanStack Table-г ашиглан орчин үеийн, хэрэглэгчид ээлтэй интерфэйсийг бий болгодог.
props-оор дамжуулан компонентийн ажиллагаа, харагдах байдлыг өргөн хүрээнд өөрчлөх боломжтой.^8.1^10.0 | ^11.0 | ^12.0Дараах алхмуудыг дагаж universal-crud санг төсөлдөө суулгана уу.
Терминал дээр дараах командыг ажиллуулна уу:
composer require amaraa019/laravel-universal-crud
Энэ команд нь шаардлагатай бүх тохиргоог автоматаар хийх болно.
php artisan universal-crud:install
Энэ команд дараах үйлдлүүдийг гүйцэтгэнэ:
UniversalCrud.jsx, api.js, lang/ г.м) таны resources/js/ хавтас руу хуулна (publish).package.json файлд автоматаар нэмнэ.Дээрх командын дараа package.json файлд нэмэгдсэн шинэ багцуудыг суулгана уу.
Тайлбар:
universal-crud:installкоманд нь таныpackage.jsonфайлдUniversalCrudкомпонент болон түүний хамааралтай багцууд болохreact-table,lucide-react,sonner,ckeditor5зэргийг автоматаар нэмнэ.
npm install
Энэ сан нь shadcn/ui-ийн компонентуудыг ашигладаг тул таны төсөлд тохируулах шаардлагатай.
1. Shadcn/UI-г эхлүүлэх (init):
Хэрэв таны төсөлд shadcn/ui тохируулагдаагүй бол дараах командыг ажиллуулна уу.
npx shadcn@latest init
Энэ үед танаас хэд хэдэн асуулт асуух бөгөөд дараах байдлаар хариулахыг зөвлөж байна:
Would you like to use TypeScript (recommended)? no / yes
Which style would you like to use? › Default
Which color would you like to use as base color? › Slate
Where is your global CSS file? › resources/css/app.css
Do you want to use CSS variables for colors? › yes
Where is your tailwind.config.js located? › tailwind.config.js
Configure the import alias for components: › @/components
Configure the import alias for utils: › @/lib/utils
Are you using React Server Components? › no
Write configuration to components.json. Proceed? › yes
2. Шаардлагатай компонентуудыг нэмэх:
universal-crud сан нь дараах shadcn/ui компонентуудаас хамаарна:
buttoninputselecttabledialogalert-dialogskeletoncardlabelswitchtextareacollapsibleДараах командыг ажиллуулж эдгээр компонентийг нэг дор суулгана уу.
npx shadcn@latest add button input select table dialog alert-dialog skeleton card label switch textarea collapsible
Төслийнхөө .env файлыг нээж, API-ийн үндсэн хаягийг зааж өгнө үү.
VITE_API_URL="${APP_URL}/api"
Бүх тохиргоог хийж дууссаны дараа development серверийг ажиллуулна уу.
npm run dev
Ингээд та UniversalCrud компонентийг ашиглахад бэлэн боллоо!
Controller:
UniversalCrud компонент нь Laravel-ийн стандарт Resource Controller-той хамтран ажиллахад зориулагдсан. Controller доторх index, store, update, destroy методууд нь JSON хариу буцаах ёстой.
// app/Http/Controllers/UserController.php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Inertia\Inertia;
class UserController extends Controller
{
/**
* Хүснэгтийн өгөгдлийг авч, хуудсыг харуулах
*/
public function index(Request $request)
{
$query = User::query();
// Нэрээр шүүх жишээ
if ($request->filled('name')) {
$query->where('name', 'like', '%' . $request->name . '%');
}
// И-мэйлээр шүүх жишээ
if ($request->filled('email')) {
$query->where('email', 'like', '%' . $request->email . '%');
}
$data = $query->paginate($request->input('limit', 10));
// Хэрэв хүсэлт нь AJAX (JSON) бол зөвхөн өгөгдлийг буцаана
if ($request->wantsJson()) {
return response()->json($data);
}
// Энгийн вэб хүсэлт бол Inertia хуудсыг рендер хийнэ
return Inertia::render('Users/Index', [
'dt' => $data // Анхны өгөгдлийг дамжуулах
]);
}
/**
* Шинэ өгөгдөл хадгалах (Create)
*/
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8',
]);
$validated['password'] = bcrypt($validated['password']);
User::create($validated);
return response()->json(['message' => 'success'], 201); // 201 Created
}
/**
* Одоо байгаа өгөгдлийг шинэчлэх (Update)
*/
public function update(Request $request, User $user)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => ['required', 'email', Rule::unique('users')->ignore($user->id)],
'password' => 'nullable|string|min:8', // Нууц үг заавал шаардлагагүй
]);
// Хэрэв нууц үг илгээгдсэн бол шинэчилнэ
if ($request->filled('password')) {
$validated['password'] = bcrypt($validated['password']);
} else {
unset($validated['password']);
}
$user->update($validated);
return response()->json(['message' => 'success'], 200); // 200 OK
}
/**
* Өгөгдлийг устгах (Delete)
*/
public function destroy(User $user)
{
$user->delete();
return response()->json(['message' => 'success'], 200); // 200 OK
}
}
Route:
routes/web.php болон routes/api.php файлуудад дараах замуудыг тодорхойлно. Энэхүү сан нь нэгдсэн Resource Controller ашиглах тул web.php дотор бүх замыг тодорхойлж өгөх нь илүү хялбар байдаг.
// routes/web.php
use App\Http\Controllers\UserController;
// Энэ нь index, store, update, destroy зэрэг бүх шаардлагатай замыг үүсгэнэ.
Route::resource('users', UserController::class)->middleware(['auth', 'verified']);
resources/js/Pages/Users/Index.jsx гэсэн файл үүсгэж, дотор нь UniversalCrud компонентийг ашиглана.
// resources/js/Pages/Users/Index.jsx
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import UniversalCrud from '@/components/UniversalCrud'; // Импорт хийх
import { Head } from '@inertiajs/react';
export default function Index({ auth, dt }) {
// Хүснэгтийн багануудыг тодорхойлох
const attributes = [
{ label: "ID", type: "id", display: ["id"] },
{ label: "Нэр", type: "text", display: ["name"] },
{ label: "И-мэйл", type: "email", display: ["email"] },
{ label: "Бүртгүүлсэн", type: "text", display: ["created_at"] },
];
// Формын талбаруудыг тодорхойлох
const form_attr = [
{ label: "Нэр", field: "name", type: "text", column: "col-span-6", value: "", required: true },
{ label: "И-мэйл", field: "email", type: "email", column: "col-span-6", value: "", required: true },
{ label: "Нууц үг", field: "password", type: "password", column: "col-span-6", value: "", required: false }, // Засах үед нууц үг заавал шаардлагагүй
];
// Шүүлтийн талбаруудыг тодорхойлох
const filters = [
{ label: "Нэрээр шүүх", field: "name", type: "text", value: "" },
{ label: "И-мэйлээр шүүх", field: "email", type: "text", value: "" },
];
return (
<AuthenticatedLayout
user={auth.user}
header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Хэрэглэгчид</h2>}
>
<Head title="Хэрэглэгчид" />
<div className="py-12">
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
<UniversalCrud
auth={auth}
dt={dt} // Controller-оос дамжуулсан анхны өгөгдөл
api_link="/users" // API endpoint
attributes={attributes}
form_attr={form_attr}
filters={filters}
subject="Хэрэглэгч"
modes={["add", "edit", "delete", "export"]} // Идэвхжүүлэх үйлдлүүд
methods={{ update: "post" }} // Laravel-д PUT ажиллахгүй бол POST ашиглах
dev={false} // Хөгжүүлэлтийн мэдээлэл харуулах эсэх
/>
</div>
</div>
</AuthenticatedLayout>
);
}
UniversalCrud Компонентийн Props| Prop | Төрөл | Тайлбар |
|---|---|---|
api_link |
string |
(Шаардлагатай) CRUD үйлдлүүдийг гүйцэтгэх API-ийн үндсэн зам. Жишээ: /users. |
dt |
object |
(Шаардлагатай) Controller-оос Inertia::render-ээр дамжуулсан анхны өгөгдөл. |
attributes |
array |
(Шаардлагатай) Хүснэгтийн багана, харагдах байдлыг тодорхойлох объектуудын массив. |
form_attr |
array |
(Шаардлагатай) Нэмэх/Засах формын талбаруудыг тодорхойлох объектуудын массив. |
subject |
string |
(Шаардлагатай) Тухайн CRUD-ийн нэр. Жишээ: "Хэрэглэгч". Орчуулгад ашиглагдана. |
filters |
array |
Шүүлтийн талбаруудыг тодорхойлох объектуудын массив. |
modes |
array |
Идэвхжүүлэх үйлдлүүдийн жагсаалт. Боломжит утгууд: add, edit, delete, export. |
methods |
object |
Засах үйлдэл PUT биш POST байх тохиолдолд ашиглана. Жишээ: { update: "post" }. |
transformInitialData |
function |
Засах үед формын анхны өгөгдлийг сервер рүү илгээхээс өмнө өөрчлөх функц. (data) => transformedData |
transformFormData |
function |
Формын өгөгдлийг сервер рүү илгээхээс өмнө өөрчлөх функц. (formData) => transformedFormData |
auth |
object |
Inertia-аас ирэх auth объект. |
lang |
string |
Компонентийн хэлийг тохируулна. Боломжит утга: mn, en. (Анхдагч: mn) |
showLangSwitcher |
boolean |
true байвал хэл солих товчлуурыг харуулна. (Анхдагч: false) |
lmt |
number |
Нэг хуудсанд харуулах мөрийн тооны анхдагч утга. (Default: 10) |
formSize |
string |
Формын цонхны өргөн. Жишээ: w-[1080px]. (Default: w-[1080px]) |
buttons |
ReactNode |
Хүснэгтийн толгой хэсэгт нэмэлт товчлуур, компонент оруулах функц. |
actions |
ReactNode |
Хүснэгтийн мөр бүрийн "Үйлдэл" баганад нэмэлт товчлуур, компонент оруулах функц. |
dev |
boolean |
true байвал формын доорх state мэдээллийг харуулна. (Default: false) |
attributes prop-ийн дэлгэрэнгүй тайлбарЭнэ prop нь хүснэгтийн багана бүрийг тодорхойлно. Багана бүр нь дараах шинж чанартай объект байна:
| Шинж чанар | Төрөл | Тайлбар |
|---|---|---|
label |
string |
Хүснэгтийн толгой дээр харагдах нэр. |
display |
array |
(Маш чухал) Өгөгдлийн объектоос ямар утгуудыг харуулахыг заана. Эхний утга нь эрэмбэлэлтэд ашиглагдана (accessorKey). |
type |
string |
Утгыг хэрхэн харуулахыг заана. Боломжит утгууд: text, id, email, image, boolean, money, enum, status, custom. |
relation |
string |
Хэрэв өгөгдөл нь Laravel-ийн relation-оор холбогдсон бол тэрхүү relation-ийн нэрийг заана. Цэгээр зааглан гүн рүү хандах боломжтой (user.profile). |
hidden |
boolean |
true байвал хүснэгтэд харуулахгүй. |
preview |
boolean |
type: "image" үед ашиглана. true байвал зураг дээр дарахад томруулж хардаг (Lightbox) болно. |
imageFallback |
string |
type: "image" үед ашиглана. Зургийн зам буруу эсвэл зураг байхгүй үед харуулах анхдагч зургийн зам. Жишээ: /images/placeholder.png. |
toggle |
boolean |
type: "boolean" үед ашиглана. true байвал "Тийм/Үгүй" гэсэн бичгийн оронд Switch компонент харуулна. |
values |
array / object |
type: "enum" үед ашиглана. Серверээс ирсэн утгыг (жишээ нь: 0, 1) харгалзах текст рүү хөрвүүлнэ. Жишээ: ["Хүлээгдэж буй", "Баталгаажсан"]. |
render |
function |
type: "custom" үед ашиглана. Тухайн нүдэнд харуулах React компонентийг буцаадаг функц. (item) => ReactNode. |
field |
string |
type: "custom" үед display байхгүй бол энэ талбарыг ашиглан баганын ID болон key үүсгэнэ. |
display prop-ийн жишээнүүд:
Энгийн харуулалт:
// "name" баганад `user.name`-ийг харуулна.
{ label: "Нэр", type: "text", display: ["name"] }
Олон утга залгаж харуулах:
// "Овог Нэр" баганад `user.last_name` болон `user.first_name`-ийг хоосон зай аван залгаж харуулна.
{ label: "Овог Нэр", type: "text", display: ["last_name", "first_name"] }
Relation-оос утга харуулах:
// Хэрэглэгчийн мэдээлэл `user` relation-оор орж ирдэг гэж үзье.
// "Хэрэглэгч" баганад `order.user.name`-ийг харуулна.
{ label: "Хэрэглэгч", type: "text", display: ["name"], relation: "user" }
Гүн relation-оос утга харуулах:
// "Профайл зураг" баганад `order.user.profile.avatar`-г харуулна.
{ label: "Профайл зураг", type: "image", display: ["avatar"], relation: "user.profile" }
Зураг томруулж харах (Lightbox):
// "Зураг" баганад `product.image_url`-г харуулна.
// `preview: true` гэж зааснаар зураг дээр дарахад томруулж харах боломжтой болно.
{ label: "Зураг", type: "image", display: ["image_url"], preview: true, imageFallback: "/img/no-image.jpg" }
Custom Component Render:
// "Купон" баганад custom логик ашиглан badge харуулах жишээ.
{
field: 'coupon',
label: 'Купон',
type: 'custom',
render: (item) => {
const coupon = item.orders && item.orders[0] && item.orders[0].coupon;
if (coupon) {
return (
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-purple-100 text-purple-800">
{coupon.code}
</span>
);
}
return <span className="text-gray-400">-</span>;
}
}
Buttons, Actions, transformInitialData болон transformFormData prop-ийн дэлгэрэнгүй тайлбарЭдгээр пропууд нь компонентийн стандарт үйлдлүүд дээр нэмэлт, өөрийн гэсэн товчлуур, логикийг нэмэх боломжийг олгодог.
1. buttons prop-ийн жишээ
Хүснэгтийн толгой хэсэгт нэмэлт товчлуур нэмэх. Энэ компонент нь data, setData, load гэсэн пропуудыг хүлээн авна.
// Users/Index.jsx дотор
const CustomHeaderButtons = ({ data, load }) => {
const handleCustomAction = () => {
alert(`Нийт ${data.length} хэрэглэгч байна.`);
};
return (
<Button variant="outline" onClick={handleCustomAction}>
Мэдээлэл харах
</Button>
);
};
// ...
<UniversalCrud
{...otherProps}
buttons={CustomHeaderButtons}
/>
2. actions prop-ийн жишээ
Хүснэгтийн мөр бүрд "И-мэйл илгээх" гэсэн нэмэлт товчлуур нэмэх. Энэ компонент нь item (тухайн мөрийн өгөгдөл), load зэрэг пропуудыг хүлээн авна.
// Users/Index.jsx дотор
const CustomRowActions = ({ item }) => {
const sendEmail = () => {
alert(`${item.email} хаяг руу и-мэйл илгээлээ.`);
};
return (
<Button variant="secondary" size="sm" onClick={sendEmail} title="И-мэйл илгээх">
<Mail size={16} />
</Button>
);
};
// ...
<UniversalCrud
{...otherProps}
actions={CustomRowActions}
/>
3. transformInitialData болон transformFormData prop-ийн жишээ
Серверээс ирсэн settings гэх JSON талбарыг форм дээр задгай харуулж, буцааж илгээхдээ нэгтгэх жишээ.
// Controller дээр User модел нь 'settings' гэсэн JSON талбартай гэж үзье.
// $user->settings = ['theme' => 'dark', 'notifications' => true];
// Users/Index.jsx дотор
// Формын талбарууд (settings-ийн талбаруудыг нэмж өгнө)
const form_attr = [
{ label: "Нэр", field: "name", type: "text", column: "col-span-12", required: true },
{ type: "section_header", label: "Тохиргоо", column: "col-span-12" }, // Хэсгийн гарчиг
{ label: "Хэрэглэгчийн нэр", field: "username", type: "text", column: "col-span-6" },
{ label: "Идэвхтэй эсэх", field: "active", type: "boolean", column: "col-span-6" },
];
// Серверээс ирсэн өгөгдлийг формд оруулахын өмнө өөрчлөх
const handleTransformInitialData = (data) => {
const settings = data.settings || {}; // 'settings' байхгүй бол хоосон объект
return {
...data,
username: settings.username || '',
active: settings.active ?? 1, // Анхдагч утга
};
};
// Формын өгөгдлийг сервер лүү илгээхийн өмнө өөрчлөх
const handleTransformFormData = (formData) => {
const { username, active, ...rest } = formData;
return {
...rest, // name, email, password г.м бусад талбарууд
settings: {
username: username,
active: active,
},
};
};
// ...
<UniversalCrud
{...otherProps}
form_attr={form_attr}
transformInitialData={handleTransformInitialData}
transformFormData={handleTransformFormData}
/>
Энэхүү сан нь MIT лиценз-ийн дор тараагдана.