phpoffice/math
Pure-PHP library for building and converting math formulas in MathML and Office MathML (OMML). Provides classes for elements like identifiers, operators, numbers, fractions, superscripts, rows, and semantics. Requires PHP 7.1+ and XML/XMLWriter.
Installation:
composer require phpoffice/math
Verify PHP 8.1+ and extensions (dom, libxml, xmlwriter) are enabled.
First Use Case: Render a basic equation in a Laravel Blade template:
use PHPOffice\Math\Math;
$math = new Math();
$math->writeToString('<math><mi>x</mi><mo>+</mo><mn>2</mn></math>');
echo $math->getLastError(); // Check for issues
Key Classes:
Math: Core class for reading/writing MathML.MathML: Namespace for MathML-specific operations (e.g., MathML::writeSemantics()).Where to Look First:
tests/ directory for usage patterns (e.g., MathMLReaderTest.php).// app/Helpers/MathHelper.php
use PHPOffice\Math\Math;
function renderMath($expression) {
$math = new Math();
$math->writeToString($expression);
return $math->output();
}
Usage in Blade:
@verbatim
{{ renderMath('<math><msup><mi>x</mi><mn>2</mn></msup></math>') }}
@endverbatim
Use MathML namespace for structured elements:
use PHPOffice\Math\MathML;
$math = new Math();
$math->writeToString(
MathML::writeFraction(
MathML::writeIdentifier('a'),
MathML::writeNumber('3')
)
);
$math = new Math();
$math->writeToString('<math><mi>E</mi><mo>=</mo><msup><mi>mc</mi><mn>2</mn></msup></math>');
$math->renderToImage('png');
$imageData = $math->output();
return response($imageData, 200, ['Content-Type' => 'image/png']);
// app/Jobs/RenderMathJob.php
use PHPOffice\Math\Math;
class RenderMathJob implements ShouldQueue {
public function handle() {
$math = new Math();
$math->writeToString('<math><mfrac><mi>a</mi><mn>b</mn></mfrac></math>');
$math->renderToImage('svg');
Storage::put('math_cache/' . uniqid() . '.svg', $math->output());
}
}
Dispatch:
RenderMathJob::dispatch();
use PHPOffice\Math\MathML;
$math = new Math();
$math->writeToString(
MathML::writeSemantics(
'equation',
'<math><mi>F</mi><mo>=</mo><mi>ma</mi></math>'
)
);
Service Provider:
Bind Math to the container for dependency injection:
// app/Providers/AppServiceProvider.php
public function register() {
$this->app->singleton(Math::class, function () {
return new Math();
});
}
Usage:
use Illuminate\Support\Facades\App;
$math = App::make(Math::class);
Caching Rendered Equations:
$cacheKey = 'math_' . md5($expression);
$cached = Cache::get($cacheKey);
if (!$cached) {
$math = new Math();
$math->writeToString($expression);
Cache::put($cacheKey, $math->output(), now()->addHours(1));
}
Validation:
Use Laravel’s FormRequest to validate MathML input:
public function rules() {
return [
'mathml' => 'required|string|max:10000',
];
}
Lazy-Load Heavy Operations: Defer image rendering until needed:
$math = new Math();
$math->writeToString($expression);
// Store MathML string in DB/cache, render only when requested.
Batch Processing:
Use Laravel’s collect() to process multiple equations:
$equations = ['<math>...</math>', '<math>...</math>'];
$results = collect($equations)->map(function ($eq) {
$math = new Math();
$math->writeToString($eq);
return $math->renderToImage('svg');
});
XXE Vulnerability (Critical):
$dom = new DOMDocument();
$dom->loadXML($mathml, LIBXML_NOENT | LIBXML_DTDLOAD); // Disable DTD
Math::setDebug(true) to log suspicious input.&entity;).MathML Complexity:
$math->getLastError() after writing.Image Generation Failures:
gd/imagick extensions.webp may not work).if (!extension_loaded('gd')) {
throw new \RuntimeException('GD extension required for image output.');
}
PHP 8.4+ Changes:
MathML methods may have stricter type hints.^0.3.0 and test edge cases.Memory Limits:
memory_limit.ini_set('memory_limit', '256M').Math::setMemoryLimit(50) (if supported).Enable Debug Mode:
$math = new Math();
$math->setDebug(true);
$math->writeToString($expression);
// Check logs for warnings/errors.
Validate MathML:
$math = new Math();
$math->writeToString($expression);
if ($math->getLastError()) {
Log::error('MathML Error: ' . $math->getLastError());
abort(500);
}
Inspect Output:
image/png vs. image/svg+xml).Common Errors:
| Error | Cause | Solution |
|---|---|---|
Unsupported tag: <mrow> |
Invalid MathML syntax | Use MathML::writeRow() helper. |
Failed to load XML |
Malformed input | Validate with DOMDocument::loadXML(). |
ImageMagick not installed |
Missing imagick extension |
Install via pecl install imagick. |
Custom MathML Elements:
Extend PHPOffice\Math\MathML to add domain-specific tags:
namespace App\Extensions;
use PHPOffice\Math\MathML;
class CustomMathML extends MathML {
public static function writeVector($elements) {
return '<mrow>' . implode('', $elements) . '</mrow>';
}
}
Alternative Output Formats:
Wrap Math in a facade to support multiple formats:
// app/Facades/MathRenderer.php
use Illuminate\Support\Facades\Facade;
class MathRendererFacade extends Facade
How can I help you explore Laravel packages today?