Best Practices

Guidelines for creating secure, performant, and maintainable plugins.

Security

Never Use Dangerous Functions

Forbidden functions:

  • eval(), exec(), shell_exec(), system()

  • passthru(), popen(), proc_open()

  • Dynamic require/include with user input

// BAD - Security vulnerability
eval($_GET['code']);
exec('rm -rf ' . $userInput);

// GOOD - Use safe alternatives
$sanitizedInput = escapeshellarg($userInput);
exec('safe-command ' . $sanitizedInput);

Validate All Input

use Symfony\Component\Validator\Constraints as Assert;

#[Assert\NotBlank]
#[Assert\Email]
private string $email;

#[Assert\Length(min: 8, max: 100)]
private string $password;

#[Assert\Range(min: 1, max: 100)]
private int $age;

Use Parameterized Queries

Sanitize Output

Encrypt Sensitive Data

Validate Webhooks

Performance

Use Caching

Optimize Database Queries

Add Database Indexes

Lazy-Load Heavy Services

Minimize Asset Size

  • Minify CSS/JS for production

  • Optimize images (compress, WebP format)

  • Use CDNs for common libraries

  • Bundle and compress assets

Batch Operations

Code Quality

Follow PSR-12 Coding Standards

Use Type Hints

Document Public Methods

Handle Errors Gracefully

Log Important Operations

Keep Classes Focused

Compatibility

Specify Version Constraints

Test with Minimum Version

Always test your plugin with the minimum PteroCA version you support.

Document Breaking Changes

In CHANGELOG.md:

Provide Upgrade Guides

Help users migrate between major versions with clear upgrade documentation.

Plugin Structure

Organize by Feature

Use Consistent Naming

  • Classes: PascalCase

  • Methods: camelCase

  • Constants: UPPER_SNAKE_CASE

  • Database tables: plg_prefix_table_name

Separate Concerns

  • Controllers: Handle HTTP

  • Services: Business logic

  • Repositories: Data access

  • Entities: Data models

Database

Use Migrations for Schema Changes

Always Use Table Prefix

Add Indexes for Performance

Handle DateTime Correctly

User Experience

Provide Clear Error Messages

Use Translations

Show Progress for Long Operations

Validate Forms

Testing

Write Tests

Test Edge Cases

  • Empty input

  • Invalid data

  • Boundary values

  • Error conditions

Use Meaningful Test Names

Documentation

Document Public APIs

Every public method should have PHPDoc.

Provide README.md

Include in your plugin:

Maintain CHANGELOG.md

Track all changes between versions.

Include Examples

Provide code examples in documentation.

Avoid Common Pitfalls

Don't Modify Core Files

Never edit PteroCA core code. Use events and services instead.

Don't Use Global State

Don't Hardcode Paths

Don't Skip Error Handling

Always handle potential exceptions, especially in:

  • External API calls

  • File operations

  • Database queries

Last updated