Files
ONE-OS/.agents/skills/ui-ux-pro-max/data/stacks/laravel.csv
王冕 2018e34473 feat(web): 同步当前原型页与工具配置改动
统一提交当前工作区内的页面原型调整、新增运维相关页面以及本地工具配置目录变更,便于整体同步到远端环境继续联调与演示。

Made-with: Cursor
2026-04-01 13:28:56 +08:00

18 KiB

1NoCategoryGuidelineDescriptionDoDon'tCode GoodCode BadSeverityDocs URL
22Blade TemplatesUse layouts with @extends and @sectionDefine one master layout and extend it per page@extends layout with named @section blocksDuplicate header/footer HTML in every view@extends('layouts.app') @section('content')Full HTML in every view fileHighhttps://laravel.com/docs/blade#layouts-using-template-inheritance
33Blade TemplatesUse @props for component type-safetyDeclare accepted props inside components with @props@props with defaults to document component APIPass arbitrary variables without declaration@props(['title' => '' 'variant' => 'primary'])No @props declaration in componentMediumhttps://laravel.com/docs/blade#component-data-and-attributes
46Blade TemplatesUse Blade directives instead of raw PHPBlade directives are readable and IDE-supported@if @foreach @forelse @empty instead of <?php ?>Raw PHP tags inside Blade templates@forelse($items as $item) ... @empty <p>None</p> @endforelse<?php foreach($items as $item): ?>Highhttps://laravel.com/docs/blade#blade-directives
57Blade TemplatesEscape output with {{ }}Use double curly braces for XSS-safe output{{ }} for all user-supplied or dynamic text{!! !!} for untrusted data{{ $user->name }}{!! $user->name !!}Highhttps://laravel.com/docs/blade#displaying-data
612LivewireUse lifecycle hooks appropriatelymount() for init; updated() for reactive side effectsmount() for initialization updatedFoo() for property changesHeavy logic in render() or __construct()public function mount(): void { $this->items = Item::all(); }public function render(): View { $this->items = Item::all(); }Mediumhttps://livewire.laravel.com/docs/lifecycle-hooks
713LivewireUse lazy loading for heavy componentsDefer render of expensive components until visiblewire:init or lazy attribute on componentsLoad all Livewire components on page load<livewire:analytics-chart lazy /><livewire:analytics-chart /> with heavy DB queries on mountMediumhttps://livewire.laravel.com/docs/lazy
817Inertia.jsUse Inertia page components as route endpointsEach page is a Vue/React component rendered server-side via Inertia::render()Inertia::render('Dashboard' ['data' => $data]) in controllersReturn JSON and fetch from JavaScriptreturn Inertia::render('Users/Index' ['users' => $users]);return response()->json($users); with client-side fetchHighhttps://inertiajs.com/responses
918Inertia.jsShare global data via HandleInertiaRequestsMiddleware share() provides auth user and flash to every pageShare auth/flash in HandleInertiaRequests middlewarePass auth to every Inertia::render() callpublic function share(Request $r): array { return ['auth' => ['user' => $r->user()]]; }Inertia::render('Page' ['auth' => auth()->user()]) every controllerHighhttps://inertiajs.com/shared-data
1020Inertia.jsUse useForm for form state and submissionInertia's useForm manages progress errors and transformsuseForm for all page-level forms, form.post() for submitAxios/fetch for form submissions on Inertia pagesconst form = useForm({ name: '' }); form.post('/users');axios.post('/users', { name });Highhttps://inertiajs.com/forms
1121Inertia.jsUse persistent layouts to preserve stateWrap pages in a persistent layout so header/sidebar don't remountlayout property on page component for persistent UIRe-render full layout on every page visitMyPage.layout = (page) => <AppLayout>{page}</AppLayout>No layout — full page reload feel on navigationMediumhttps://inertiajs.com/pages#persistent-layouts
1222Inertia.jsEnable SSR for public pagesServer-side rendering improves SEO and first paintEnable Inertia SSR for marketing and public pagesClient-only rendering for all pages including publicphp artisan inertia:start-ssr with @inertiaHeadNo SSR on pages requiring good SEOMediumhttps://inertiajs.com/server-side-rendering
1323StylingSet up Tailwind CSS via ViteUse Vite + tailwindcss plugin for fast HMR and optimized buildsInstall tailwindcss @tailwindcss/vite and configure vite.config.jsLaravel Mix or manual PostCSS pipeline for new projectsplugins: [tailwindcss()] in vite.config.js + @import 'tailwindcss' in app.cssLaravel Mix with require('tailwindcss') in webpackHighhttps://tailwindcss.com/docs/installation/framework-guides
1424StylingPurge unused styles via content configTailwind scans Blade and JS files to tree-shake unused classescontent: ['./resources/views/**/*.blade.php' './resources/js/**/*.{jsvue}']No content config — ship all 3MB of CSScontent: ['./resources/**/*.blade.php' './resources/**/*.js']content: []Highhttps://tailwindcss.com/docs/content-configuration
1525StylingUse dark mode class strategyclass-based dark mode integrates with server-rendered preferencedarkMode: 'class' with a toggle that sets class on <html>Media query only — no user override possibledarkMode: 'class'; document.documentElement.classList.toggle('dark')darkMode: 'media' — no programmatic controlMediumhttps://tailwindcss.com/docs/dark-mode
1626StylingUse @apply sparingly in component CSSExtract only truly repeated multi-class patterns@apply for BEM base classes shared across many components@apply for every single element — defeats Tailwind's purpose@apply flex items-center gap-2 (shared button base)@apply text-sm for a single useLowhttps://tailwindcss.com/docs/functions-and-directives#apply
1727StylingConfigure custom design tokens in CSSDefine brand colors spacing fonts as CSS variables consumed by TailwindCustom @theme tokens matched to brand guidelinesMagic color hex codes scattered across Blade templates@theme { --color-brand: oklch(0.6 0.2 250); }bg-[#1a2b3c] inline throughout templatesMediumhttps://tailwindcss.com/docs/theme
1829ComponentsUse class-based components for complex logicPHP class components can inject services and pre-process dataapp/View/Components/ class when component needs PHP logicBlade @php blocks for business logic inside templatesclass AlertComponent { public function __construct(public string $type) {} }@php $color = $type === 'error' ? 'red' : 'green'; @endphpMediumhttps://laravel.com/docs/blade#components
1931ComponentsSeparate variant logic from templatesKeep variant/size/color logic in a PHP class or helper not in BladeVariant class or match() expression in component classLong @if chains for variants inside Blade templatespublic function classes(): string { return match($this->variant) { 'primary' => 'bg-blue-600', } }@if($variant === 'primary') bg-blue-600 @elseif($variant === 'secondary')...Mediumhttps://laravel.com/docs/blade#components
2032ComponentsProvide default slot contentUse {{ $slot ?? '' }} or named slot defaults so components are usable emptyDefault content in slots for optional regionsRequire every slot to be filled — throws errors on empty usage{{ $icon ?? '' }} in component Blade file{{ $icon }} — fatal if caller omits slotLowhttps://laravel.com/docs/blade#slots
2133ComponentsUse component namespacing for packagesPrefix third-party or module components to avoid collisionsRegister custom prefix via Blade::componentNamespace()Mix first-party and package component names with no prefixBlade::componentNamespace('Modules\\Shop\\Views' 'shop'); <x-shop::product-card /><x-product-card /> colliding with first-party cardLowhttps://laravel.com/docs/blade#manually-registering-components
2234FormsValidate with Form Request classesMove validation rules out of controllers into dedicated FormRequest classesphp artisan make:request and define rules() + authorize()Inline validate() in controller actionsclass StorePostRequest extends FormRequest { public function rules() { return ['title' => 'required|max:255']; } }public function store(Request $r) { $r->validate(['title' => 'required']); }Highhttps://laravel.com/docs/validation#form-request-validation
2340PerformanceEager load relationships to prevent N+1Always eager load related models used in views with with()with() in queries before passing collections to viewsLazy-load relations inside Blade loopsUser::with('posts' 'avatar')->get()User::all() then @foreach $user->posts in BladeHighhttps://laravel.com/docs/eloquent-relationships#eager-loading
2441PerformanceCache rendered Blade fragmentsUse cache() helper to wrap expensive rendered partialscache() around slow partials that change infrequentlyRe-render identical content on every request@php echo cache()->remember('sidebar' 3600 fn() => view('sidebar')->render()); @endphp{{ view('sidebar')->render() }} on every page loadMediumhttps://laravel.com/docs/cache
2543PerformanceQueue slow background tasksOffload emails notifications and heavy processing to queuesDispatch jobs for anything taking >200msBlock HTTP request with slow operationsProcessImage::dispatch($file); return back();Storage::put(); Mail::send(); Image::resize(); in controllerHighhttps://laravel.com/docs/queues
2644PerformanceUse route model bindingLaravel resolves models automatically — avoids manual find()Type-hint model in controller methodManual User::findOrFail($id) in every methodpublic function show(User $user): View { return view('users.show' compact('user')); }public function show($id) { $user = User::findOrFail($id); }Mediumhttps://laravel.com/docs/routing#route-model-binding
2745PerformanceEnable HTTP response caching for static contentCache control headers for pages that rarely changeCache-Control headers via middleware for public pagesNo caching — serve every response freshresponse()->view('home')->header('Cache-Control' 'publicmax-age=3600')No cache headers on marketing pagesMediumhttps://laravel.com/docs/responses#response-headers
2846SecurityEscape all output in Blade{{ }} auto-escapes HTML — never use {!! !!} on user data{{ }} for all untrusted or dynamic content{!! !!} for user-controlled strings{{ $comment->body }}{!! $comment->body !!}Highhttps://laravel.com/docs/blade#displaying-data
2948SecurityValidate and authorize file uploadsCheck MIME type size and store outside public rootStore in storage/app/private + validate mimes and maxStore raw upload in public/ without validation'avatar' => ['required' 'image' 'mimes:jpg,png' 'max:2048']'avatar' => 'required' with no MIME or size checkHighhttps://laravel.com/docs/filesystem#file-uploads
3049SecurityUse signed URLs for temporary linksGenerate expiring URLs for private downloads or email confirmationsURL::signedRoute() or temporarySignedRoute()Expose sequential IDs in download URLs without authURL::temporarySignedRoute('file.download' now()->addMinutes(30) ['file' => $id])route('file.download' $id) with no expiry or signatureHighhttps://laravel.com/docs/urls#signed-urls
3150SecuritySet a strict Content Security PolicyCSP headers prevent XSS injection of external scriptsspatie/laravel-csp or custom middleware to emit CSP headerNo CSP — browser runs any injected scriptHeader: Content-Security-Policy: default-src 'self'; script-src 'self'No Content-Security-Policy header on responsesMediumhttps://laravel.com/docs/middleware