lyrasoft / contact
LYRASOFT contact package
1.2.4
2026-03-25 07:00 UTC
Requires
- php: >=8.4.6
- lyrasoft/luna: ^2.2
- symfony/rate-limiter: ^6.0||^7.0||^8.0||^9.0
README
Installation
Install from composer
composer require lyrasoft/contact
Then copy files to project
php windwalker pkg:install lyrasoft/contact -t routes -t migrations -t seeders
Seeders
- Add
contact-seeder.phptoresources/seeders/main.php
Languages
Add this line to admin & front middleware:
$this->lang->loadAllFromVendor(\Lyrasoft\Contact\ContactPackage::class, 'ini');
If you want to copy language files, Run this command (Optional):
php windwalker pkg:install lyrasoft/contact -t lang
Register Admin Menu
Edit resources/menu/admin/sidemenu.menu.php
// Contact $menu->link('聯絡單') ->to($nav->to('contact_list', ['type' => 'main'])) ->icon('fal fa-phone-volume');
Support Multiple Types
Use Route to separate types:
/admin/contact/list/{type}
Use type param in Navigator.
$nav->to('contact_list', ['type' => '{type}']);
Frontend
One MVC per type. If you want another contact form with type: foo, just generate a FooContact MVC
php windwalker g controller Admin/FooContact php windwalker g view Admin/FooContact php windwalker g form Admin/FooContact/Form/EditForm
And remember set type when saving in controller:
$controller->prepareSave( function (PrepareSaveEvent $event) { $data = &$event->data; $data['type'] = 'foo'; } );
RateLimit
Front controller has rate limit function to prevent spam. you can configure it in etc/packages/contact.config.php
'rate_limit' => [ // Default rate limit config '_default' => [ 'policy' => 'fixed_window', 'limit' => 10, 'interval' => '1day', ], // You can add different rate limit for different type 'main' => [ 'policy' => 'fixed_window', 'limit' => 10, 'interval' => '1day', ], ],
If you create a new controller to save contact form, you can use rate limiter in controller:
public function save( AppContext $app, ContactService $contactService, // ... ): mixed { // Set your form type $type = 'inquiry'; // Check or throw $contactService->rateLimitOrThrow($type, $app->getAppRequest()->getClientIP()); // Or throw yourself $limit = $contactService->checkRateLimit($type, $app->getAppRequest()->getClientIP()); if (!$limit->isAccepted()) { throw new \RuntimeException('Rate limit exceeded', 429); } // ...
