/src/ - Modern PSR-4 code (OpenEMR\ namespace)
/library/ - Legacy procedural PHP code
/interface/ - Web UI controllers and templates
/templates/ - Smarty/Twig templates
/tests/ - Test suite (unit, e2e, api, services)
/sql/ - Database schema and migrations
/public/ - Static assets
/docker/ - Docker configurations
/modules/ - Custom and third-party modules
- PHP: 8.2+ required
- Backend: Laminas MVC, Symfony components
- Templates: Twig 3.x (modern), Smarty 4.5 (legacy)
- Frontend: Angular 1.8, jQuery 3.7, Bootstrap 4.6
- Build: Gulp 4, SASS
- Database: MySQL via ADODB wrapper
- Testing: PHPUnit 11, Jest 29
See CONTRIBUTING.md for full setup instructions. Quick start:
cd docker/development-easy
docker compose up --detach --wait- App URL: http://localhost:8300/ or https://localhost:9300/
- Login:
admin/pass - phpMyAdmin: http://localhost:8310/
Tests run inside Docker via devtools. Run from docker/development-easy/:
# Run all tests
docker compose exec openemr /root/devtools clean-sweep-tests
# Individual test suites
docker compose exec openemr /root/devtools unit-test
docker compose exec openemr /root/devtools api-test
docker compose exec openemr /root/devtools e2e-test
docker compose exec openemr /root/devtools services-test
# View PHP error log
docker compose exec openemr /root/devtools php-logTip: Install openemr-cmd
for shorter commands (e.g., openemr-cmd ut for unit tests) from any directory.
Isolated tests run on the host without a database or Docker:
composer phpunit-isolated # Run all isolated testsTwig templates have two layers of testing (both isolated):
- Compilation tests verify every
.twigfile parses and references valid filters/functions/tests. These run automatically over all templates. - Render tests render specific templates with known parameters and compare
the full HTML output to expected fixture files in
tests/Tests/Isolated/Common/Twig/fixtures/render/.
When modifying a Twig template that has render test coverage, update the fixture files:
composer update-twig-fixtures # Regenerate fixture filesReview the diff before committing. See the fixtures README for details on adding new test cases.
These run on the host (requires local PHP/Node):
# Run all PHP quality checks (phpcs, phpstan, rector)
composer code-quality
# Individual checks (composer scripts handle memory limits)
composer phpstan # Static analysis
composer phpcs # PHP code style check
composer phpcbf # PHP code style auto-fix
composer rector-check # Code modernization (dry-run)
# JavaScript/CSS
npm run lint:js # ESLint check
npm run lint:js-fix # ESLint auto-fix
npm run stylelint # CSS/SCSS lintnpm run build # Production build
npm run dev # Development with file watching
npm run gulp-build # Build only (no watch)- Indentation: 4 spaces
- Line endings: LF (Unix)
- No strict_types: Project doesn't use
declare(strict_types=1) - Namespaces: PSR-4 with
OpenEMR\prefix for/src/ - New code goes in
/src/, legacy helpers in/library/
Follow Conventional Commits:
<type>(<scope>): <description>
Types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
Examples:
feat(api): add PATCH support for patient resourcefix(calendar): correct date parsing for recurring eventschore(deps): bump monolog/monolog to 3.10.0
New services should extend BaseService:
namespace OpenEMR\Services;
class ExampleService extends BaseService
{
public const TABLE_NAME = "table_name";
public function __construct()
{
parent::__construct(self::TABLE_NAME);
}
}When modifying PHP files, ensure proper docblock:
/**
* Brief description
*
* @package OpenEMR
* @link https://www.open-emr.org
* @author Your Name <your@email.com>
* @copyright Copyright (c) YEAR Your Name or Organization
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
*/Preserve existing authors/copyrights when editing files.
- Multiple template engines: check extension (.twig, .html, .php)
- Event system uses Symfony EventDispatcher
- Pre-commit hooks available via
.pre-commit-config.yaml
CONTRIBUTING.md- Contributing guidelinesAPI_README.md- REST API docsFHIR_README.md- FHIR implementationtests/Tests/README.md- Testing guide