Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Core Laravel Package

catchadmin/core

CatchAdmin Core is the foundation package for the CatchAdmin Laravel admin framework, supplying shared utilities, base classes, and infrastructure for building backend management systems. It supports rapid CRUD scaffolding and permission handling, though community adoption remains limited.

View on GitHub
Deep Wiki
Context7

Getting Started

catchadmin/core is the backend backbone of CatchAdmin — a modular Laravel admin framework. The package itself is small; the value is in the base classes (Catch\Base\CatchController, Catch\Base\CatchModel) and support layer (Catch\Support\Excel, async contracts) that every module in the repo builds on. Plan to learn the framework through the repo's modules, not through this package alone.

Bootstrap order:

  1. Confirm PHP 8.3+, Composer, Git, Node 22+, and Yarn.
  2. Clone the matching frontend into web: git clone -b v5 https://gitee.com/catchadmin/catch-admin-vue.git web. The branch tag matters — it must match the backend major version.
  3. Read or create .env for DB_DATABASE, DB_USERNAME, DB_PASSWORD. Do not test the DB early; let Laravel migrations surface connection errors during install.
  4. Install modules: php artisan catch:module:install --all --no-interaction.
  5. Open an existing module first — modules/System/ is the canonical reference for controllers, models, routes, and Excel classes.

First use case: build a CRUD resource end-to-end. Scaffold the module skeleton (Installer.php, Providers/{ModuleName}ServiceProvider.php, routes/route.php, storage/app/modules.json entry), then generate CRUD from a CREATE TABLE statement, then wire the list page. The whole point of the package is that this path is turnkey — you should not be hand-writing list/search/pagination plumbing.

Implementation Patterns

Module layout. Everything lives under modules/{ModuleName}/. Controllers, models, routes/route.php, Providers/, and Excel/{Import,Export}/ are the standard subfolders. Registration is via storage/app/modules.json — that file is the module registry the framework reads.

Thin controllers. Extend Catch\Base\CatchController. Route requests, delegate to model or service, return data. Use protected readonly constructor injection for dependencies.

Fat models. Extend Catch\Base\CatchModel. Declare:

  • $table, $fillable, $fields, $form — the field/form contract the base CRUD flow reads.
  • $searchable — quick search fields.
  • creator_id in fillable when the model tracks creator.
  • $dataRange when data-permission filtering applies.
  • setBeforeGetList() for query tweaks scoped to the list query — this is the hook to use instead of overriding list methods.

Routes. Follow the target module's existing style. Prefer Route::adminResource for new admin CRUD; fall back to Route::apiResource when explicit only/except/names are needed. Keep prefixes lowercase. When editing a generator-managed route file, add new routes before the //next marker — the generator appends there.

Codegen workflow. SQL CREATE TABLE in → generated list page, dialog form, page form, and route file out. Output paths are fixed: web/src/views/{module}/{resource}/index.vue, .../{resource}/form/create.vue, modules/{Module}/routes/route.php. Trust the generated shape; adjust after, not instead.

Import/export. Import classes go in modules/{Module}/Excel/Import/, extend Catch\Support\Excel\Import, implement collection(Collection $rows): void and rules(): array. Export classes go in modules/{Module}/Excel/Export/; keep the controller export() action thin and wire catch-table with the exports prop to the export URL. Both have an async path (AsyncTaskInterface + AsyncTaskDispatch); use it for anything that can run long.

Frontend contract. catch-table for list pages, dialog slot for create/edit, <Create :primary="row?.id" :api="api" />. Forms use useCreate(props.api, props.primary), useShow(...) when editing, inject('closeDialog') to close. primary (not id) is the prop name. Admin components are auto-imported. Shared utilities live in web/src/support/ — http for custom/blob requests, helper, cache, message, options.

Uploads. Pick the component from web/src/components/admin/upload/ by storage target: UploadImage/UploadFile/UploadFiles/UploadAttach/index.vue for local, OssUpload/CosUpload/QiniuUpload for cloud, ChunkUpload for large files, AttachUpload for system attachments. Prefer useUpload.ts and useChunkUpload.ts over re-implementing.

Gotchas and Tips

  • Enums start at 1, not 0. Status is semantically hardcoded: 1 = Enabled, 2 = Disabled. Deviating from this will confuse every generated form and filter.
  • Timestamps are unsignedInteger Unix timestamps, not datetime. Soft-delete columns follow the same rule. Laravel's default timestamps() and date casting will not behave as expected — check migrations against this before debugging weird list ordering or date filters.
  • declare(strict_types=1); is required in every PHP file. Not stylistic; strict typing assumptions leak into the base classes.
  • The //next route marker is load-bearing. The route generator appends at that marker. Delete it or move business routes after it and regeneration silently duplicates or misplaces routes.
  • primary is the form prop name, not id. :primary="row?.id" is correct; :id will leave edit forms in create mode with no error.
  • Dialog forms must inject closeDialog and register it via onMounted(() => close(() => closeDialog())). Skip it and the dialog stays open after submit — a silent UX bug.
  • Import row access is positional, not named. $row[0], $row[1] in collection(), and rules keyed '0', '1'. Also set $start to match the first real data row; off-by-one here is the most common import bug. Keep $importMaxNum in place as a hard guard.
  • Do not override model list/CRUD methods casually. The base flow handles list, create, update, delete, toggle, and search. Reach for setBeforeGetList() first; overriding list will break pagination/search formatters in non-obvious ways.
  • $dataRange filtering is silent. If a user sees an empty list unexpectedly, check permissions and $dataRange before touching queries.
  • storage/app/modules.json is the registry. A module that "isn't loading" is almost always missing from this file, or the file is stale after a manual copy. Clear caches after touching it.
  • Install failures are resumable, not restartable. If initialization fails partway, verify the previous stage's outputs and continue from the failed stage — don't wipe and re-run catch:module:install --all blindly.
  • Frontend branch mismatch is a real failure mode. -b v5 on the frontend clone is not optional; API shape and composables drift across versions.
  • Extension points to know: Catch\Base\CatchController and Catch\Base\CatchModel for base behavior, Catch\Support\Excel\Import/Export for tabular flows, AsyncTaskInterface + AsyncTaskDispatch for background work. When stuck, read the closest existing module — the framework's real documentation is its own modules/System/ code.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect