Add AGENTS.md for agent
Fix areazone edit form validation error - Fix wrong field name in areazone_newrow.php (contactid → zoneid) - Move POST variable assignments before validation in Areas::areazone_edit() The user already made the edits in the previous turn. This commit message is ready to use.
This commit is contained in:
parent
4021a2a5f2
commit
35c948beb6
285
AGENTS.md
Normal file
285
AGENTS.md
Normal file
@ -0,0 +1,285 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Build, Lint, and Test Commands
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
composer test
|
||||
./phpunit
|
||||
|
||||
# Run all tests (Windows)
|
||||
vendor\bin\phpunit
|
||||
|
||||
# Run a single test file
|
||||
./phpunit tests/unit/HealthTest.php
|
||||
|
||||
# Run a single test method
|
||||
./phpunit --filter testIsDefinedAppPath
|
||||
|
||||
# Run tests in a specific directory
|
||||
./phpunit tests/unit/
|
||||
|
||||
# Run tests with coverage report
|
||||
./phpunit --colors --coverage-text=tests/coverage.txt --coverage-html=tests/coverage/ -d memory_limit=1024m
|
||||
|
||||
# Generate HTML coverage report
|
||||
./phpunit --coverage-html build/logs/html
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
composer install
|
||||
|
||||
# Update dependencies
|
||||
composer update
|
||||
```
|
||||
|
||||
### CodeIgniter Spark Commands
|
||||
|
||||
```bash
|
||||
# List available spark commands
|
||||
php spark list
|
||||
|
||||
# Clear all caches
|
||||
php spark cache:clear
|
||||
|
||||
# Run migrations
|
||||
php spark migrate
|
||||
|
||||
# Rollback migrations
|
||||
php spark migrate:rollback
|
||||
```
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### General Principles
|
||||
|
||||
- Write clean, readable code without unnecessary comments
|
||||
- Follow CodeIgniter 4 conventions and PSR-12 PHP standards
|
||||
- Keep methods focused and under 100 lines when possible
|
||||
- Avoid deep nesting (max 3-4 levels)
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
| Element | Convention | Examples |
|
||||
|---------|------------|----------|
|
||||
| Classes | PascalCase | `ProductsModel`, `BaseController`, `UsersLogModel` |
|
||||
| Files | Match class name | `ProductsModel.php`, `BaseController.php` |
|
||||
| Methods | camelCase | `getProductAlias()`, `productslog_edit()` |
|
||||
| Variables | camelCase | `$productid`, `$data`, `$results` |
|
||||
| Properties | snake_case | `$table`, `$primaryKey`, `$allowedFields` |
|
||||
| Constants | UPPER_SNAKE_CASE | `APPPATH`, `HOMEPATH` |
|
||||
| Namespaces | PascalCase | `App\Controllers`, `App\Models`, `Config` |
|
||||
|
||||
### File Structure
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Models\ProductsModel;
|
||||
use CodeIgniter\Controller;
|
||||
|
||||
class Products extends BaseController
|
||||
{
|
||||
protected array $data;
|
||||
|
||||
public function index()
|
||||
{
|
||||
// method body
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Imports and Namespaces
|
||||
|
||||
- Use explicit imports for all external classes
|
||||
- Namespace should reflect file location (`App\Controllers\*`, `App\Models\*`)
|
||||
- Place namespace at top, followed by imports, then class definition
|
||||
- Do not use fully qualified class names inline
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Models\ProductsModel;
|
||||
use App\Models\ProductsLogModel;
|
||||
use CodeIgniter\Controller;
|
||||
```
|
||||
|
||||
### Indentation and Spacing
|
||||
|
||||
- Use tabs for indentation (4 spaces per tab is acceptable)
|
||||
- No trailing whitespace
|
||||
- One blank line between method definitions
|
||||
- Space around operators: `$productid = $value;`
|
||||
- No space between function name and parentheses: `func()` not `func ()`
|
||||
|
||||
### Arrays and Configuration
|
||||
|
||||
```php
|
||||
// Short array syntax for simple arrays
|
||||
protected array $data;
|
||||
|
||||
$this->data['productowners'] = ['S' => 'Summit', 'C' => 'Customer'];
|
||||
|
||||
// Multi-line array with proper alignment
|
||||
protected $allowedFields = [
|
||||
'siteid',
|
||||
'productnumber',
|
||||
'productname',
|
||||
'catalogid',
|
||||
];
|
||||
```
|
||||
|
||||
### Control Structures
|
||||
|
||||
```php
|
||||
// Single-line condition with braces
|
||||
if ($productid !== null) {
|
||||
// code
|
||||
}
|
||||
|
||||
// Multi-line conditions
|
||||
if ($areaid !== '' || $producttypeid !== '') {
|
||||
$sql .= ' AND ';
|
||||
}
|
||||
|
||||
// Ternary for simple conditions
|
||||
$locationstartdate = ($this->request->getVar('locationstartdate') === '')
|
||||
? null
|
||||
: $this->request->getVar('locationstartdate');
|
||||
```
|
||||
|
||||
### Database Operations
|
||||
|
||||
- Use `$db = \Config\Database::connect();` for direct queries
|
||||
- Use Query Builder when possible: `$db->table()->get()->getResultArray()`
|
||||
- Always escape user input: `$db->escapeString($value)`
|
||||
- Use parameterized queries to prevent SQL injection
|
||||
|
||||
```php
|
||||
$builder = $db->table('products');
|
||||
$builder->where('productid', $productid);
|
||||
$query = $builder->get();
|
||||
$results = $query->getResultArray();
|
||||
```
|
||||
|
||||
### Controllers
|
||||
|
||||
- All controllers extend `BaseController`
|
||||
- Use `$this->request->getMethod()` to check request type
|
||||
- Use `$this->request->getVar()` or `$this->request->getPost()` for input
|
||||
- Return views with `return view('view_name', $data);`
|
||||
- Validate input with `$this->validate($rules)` before processing
|
||||
|
||||
```php
|
||||
public function edit($productid = null)
|
||||
{
|
||||
if ($this->request->getMethod() === 'POST') {
|
||||
$rules = [
|
||||
'productid' => 'required',
|
||||
'productnumber' => 'required',
|
||||
];
|
||||
|
||||
if ($this->validate($rules)) {
|
||||
// process form
|
||||
}
|
||||
}
|
||||
|
||||
return view('products_edit', $data);
|
||||
}
|
||||
```
|
||||
|
||||
### Models
|
||||
|
||||
- All models extend `CodeIgniter\Model`
|
||||
- Define `$table`, `$primaryKey`, `$allowedFields`
|
||||
- Use `$useSoftDeletes` for soft delete functionality
|
||||
- Define `$useTimestamps` if using created_at/updated_at
|
||||
|
||||
```php
|
||||
<?php namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class ProductsModel extends Model
|
||||
{
|
||||
protected $table = 'products';
|
||||
protected $primaryKey = 'productid';
|
||||
protected $allowedFields = ['siteid', 'productnumber', 'productname'];
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Use CodeIgniter's built-in validation: `$this->validate($rules)`
|
||||
- Return appropriate HTTP status codes in API controllers
|
||||
- Use `try/catch` for operations that may throw exceptions
|
||||
- Log errors using CodeIgniter's logging: `log_message('error', $message)`
|
||||
|
||||
```php
|
||||
try {
|
||||
$productsModel = new ProductsModel();
|
||||
$productsModel->update($productid, $data['new_value']);
|
||||
return view('form_success', $data);
|
||||
} catch (\Exception $e) {
|
||||
log_message('error', $e->getMessage());
|
||||
return view('error_page');
|
||||
}
|
||||
```
|
||||
|
||||
### Views
|
||||
|
||||
- Place views in `app/Views/` directory
|
||||
- Use `.php` extension
|
||||
- Access data via associative array: `$products`, `$data['products']`
|
||||
- Use CodeIgniter's view parser or raw PHP
|
||||
|
||||
### API Responses
|
||||
|
||||
```php
|
||||
// Return JSON response
|
||||
return $this->response->setJSON([
|
||||
'status' => 'success',
|
||||
'data' => $data,
|
||||
]);
|
||||
|
||||
// Error response
|
||||
return $this->response->setJSON([
|
||||
'status' => 'error',
|
||||
'message' => 'No data found',
|
||||
]);
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
- Extend `CodeIgniter\Test\CIUnitTestCase` for all tests
|
||||
- Test methods must start with `test` prefix
|
||||
- Use `@internal` docblock for test classes
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
|
||||
final class HealthTest extends CIUnitTestCase
|
||||
{
|
||||
public function testIsDefinedAppPath(): void
|
||||
{
|
||||
$this->assertTrue(defined('APPPATH'));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PHP Requirements
|
||||
|
||||
- PHP 8.1 or higher
|
||||
- Extensions required: `intl`, `mbstring`, `json`
|
||||
- MySQLi database driver by default
|
||||
@ -77,14 +77,16 @@ class Areas extends BaseController {
|
||||
$data['areazone'] = $results;
|
||||
|
||||
if ($this->request->getMethod() === 'POST') {
|
||||
$areaid = $this->request->getVar('areaid');
|
||||
$zoneid = $this->request->getVar('zoneid');
|
||||
$areazoneid_delete = $this->request->getVar('areazoneid_delete');
|
||||
|
||||
$rules = [
|
||||
'areaid' => 'required',
|
||||
'zoneid' => 'required'
|
||||
];
|
||||
|
||||
if($this->validate($rules)){
|
||||
$areaid = $this->request->getVar('areaid');
|
||||
$zoneid = $this->request->getVar('zoneid');
|
||||
$areazoneid_delete = $this->request->getVar('areazoneid_delete');
|
||||
if($areazoneid_delete!='') {
|
||||
$areazoneid_delete = explode(' ',$areazoneid_delete);
|
||||
foreach( $areazoneid_delete as $areazoneid ) {
|
||||
|
||||
@ -21,24 +21,31 @@
|
||||
<div class="table-responsive">
|
||||
<table id="myTable" class="table display table-striped border">
|
||||
<thead>
|
||||
<th>ID</th> <th>Type</th> <th>Name</th> <th>Description</th> <th></th>
|
||||
<th>ID</th>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach($areas as $data) {
|
||||
foreach ($areas as $data) {
|
||||
$areaid = $data['areaid'];
|
||||
$areatype = $data['areatype'];
|
||||
$areaname = $data['areaname'];
|
||||
$description = $data['description'];
|
||||
?>
|
||||
<tr>
|
||||
<td><?=$areaid;?></td> <td><?=$areatype;?></td> <td><?=$areaname;?></td> <td><?=$description;?></td>
|
||||
<td><?= $areaid; ?></td>
|
||||
<td><?= $areatype; ?></td>
|
||||
<td><?= $areaname; ?></td>
|
||||
<td><?= $description; ?></td>
|
||||
<td>
|
||||
<a class='btn btn-warning btn-sm' href='areas/edit/<?=$areaid;?>'
|
||||
<a class='btn btn-warning btn-sm' href='areas/edit/<?= $areaid; ?>'
|
||||
onclick="window.open(this.href, 'Editor','width=900,height=800,toolbar=1,resizable=0'); return false;">
|
||||
<i class="fas fa-pencil-alt"></i> Edit
|
||||
</a>
|
||||
<a class='btn btn-dark btn-sm' href='areazone/edit/<?=$areaid;?>'
|
||||
<a class='btn btn-dark btn-sm' href='areazone/edit/<?= $areaid; ?>'
|
||||
onclick="window.open(this.href, 'Editor','width=900,height=800,toolbar=1,resizable=0'); return false;">
|
||||
<i class="fa-solid fa-location-dot"></i> Zone
|
||||
</a>
|
||||
@ -55,13 +62,3 @@
|
||||
</div>
|
||||
</div>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('script') ?>
|
||||
<script>
|
||||
$(function () {
|
||||
$('#myTable').DataTable({
|
||||
"order" : []
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?= $this->endSection() ?>
|
||||
@ -1,6 +1,6 @@
|
||||
<tr>
|
||||
<td style='min-width:300px;'>
|
||||
<select class='form-control form-control-sm select2' name='contactid[]' style='width:100%;'>
|
||||
<select class='form-control form-control-sm select2' name='zoneid[]' style='width:100%;'>
|
||||
<option value=''>--</option>
|
||||
<?php
|
||||
foreach($zones as $data) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user