Page 1 of 1
Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Wed Jul 30, 2025 2:55 pm
by prashantt
Hello,
I was in the process of manual installation of Forma LMS with AlmaLinux release 8.10 on PHP 7.4, Apache 2.4 , MYSQL 5.7 downloaded from :
https://sourceforge.net/projects/forma/ ... p/download
However while starting installation i.e visiting
http://example.com/manual/forma4019/install/
No output is being displayed . On turning display_errors = On via php.ini as well.
So to debug the issue i added debug code to get error in index.php i.e
Code: Select all
function get_error()
{
print_r(error_get_last());
}
register_shutdown_function('get_error');
So the following error is being displayed i.e
Code: Select all
Array ( [type] => 4 [message] => syntax error, unexpected 'static' (T_STATIC) [file] => /{{PATH}}/{{TO}}/{{FORMA_LMS}}/lib/Cache/Lang/LangCache.php [line] => 12 )
It seems that the code :
Code: Select all
public static function getInstance(?string $format = self::FORMAT_JSON, ?int $ttl = self::CACHE_TTL, ?string $namespace = null): static
return type declaration static is causing the issue. As per PHP official docs 'Support for the return only type static' was added in PHP 8.0
https://www.php.net/manual/en/language. ... ations.php
Are PHP requirements for FormaLMS changed ?.
I see PHP 7.4 listed in official docs for version 4.x i.e :
https://docs2.formalms.org/books/refere ... quirements
Could you please replicate this at your end on PHP 7.4 and resolve this?.
Awaiting your kind reply.
Re: Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Wed Jul 30, 2025 4:39 pm
by alfa24
Try with this /lib/Cache/BaseCache.php:
Code: Select all
<?php
namespace FormaLms\lib\Cache;
abstract class BaseCache
{
public const FORMAT_PHP = 'php';
public const FORMAT_JSON = 'json';
public const FORMAT_MSGPACK = 'msgpack';
public const FORMAT_IGBINARY = 'igbinary';
protected string $cacheDir;
protected string $namespace;
protected array $memoryCache = [];
protected string $cacheFormat;
protected int $cacheTTL;
protected static $instances = [];
protected function __construct(
string $subDir,
?string $format = self::FORMAT_JSON,
?int $ttl = null,
?string $namespace = null
) {
$this->cacheDir = _files_ . '/cache/' . trim($subDir, '/') . '/';
$this->namespace = $namespace ?? static::class;
$this->cacheTTL = $ttl ?? 3600;
$this->cacheFormat = $this->determineFormat($format);
$this->ensureStructure();
}
public function __clone() {}
public function __wakeup() {}
public static function getInstance(
?string $format = 'php',
?int $ttl = null,
?string $namespace = null
) {
$class = static::class;
$key = $class . '_' . ($format ?? 'default') . '_' . ($ttl ?? 'default');
if (!isset(self::$instances[$key])) {
self::$instances[$key] = new static(
static::getSubDir(),
$format,
$ttl,
$namespace
);
}
return self::$instances[$key];
}
public static function resetInstances(): void
{
self::$instances = [];
}
abstract protected static function getSubDir(): string;
protected function ensureStructure(): void
{
if (!is_dir($this->cacheDir) && !mkdir($this->cacheDir, 0755, true) && !is_dir($this->cacheDir)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $this->cacheDir));
}
}
protected function determineFormat(?string $format = null): string
{
$selectedFormat = strtolower(\FormaLms\lib\Get::cfg('cache_format', $format));
switch ($selectedFormat) {
case 'msgpack':
return extension_loaded('msgpack') ? self::FORMAT_MSGPACK : self::FORMAT_JSON;
case 'igbinary':
return extension_loaded('igbinary') ? self::FORMAT_IGBINARY : self::FORMAT_JSON;
case 'php':
return self::FORMAT_PHP;
case 'json':
default:
return self::FORMAT_JSON;
}
}
public function getCacheFormat(): string
{
return $this->cacheFormat;
}
public function getTTL(): int
{
return $this->cacheTTL;
}
public function setTTL(int $ttl): void
{
$this->cacheTTL = $ttl;
}
public function get($key, $subKey, $type = 'default')
{
$cacheKey = $this->buildMemoryCacheKey($key, $subKey, $type);
if (isset($this->memoryCache[$cacheKey])) {
return $this->memoryCache[$cacheKey];
}
$file = $this->getCacheFile($key, $subKey, $type);
if (!file_exists($file)) {
return null;
}
try {
$content = file_get_contents($file);
if ($content === false) {
return null;
}
$data = $this->unserialize($content);
if (!is_array($data) || !isset($data['timestamp']) || !isset($data['data'])) {
return null;
}
if ((time() - $data['timestamp']) > $this->cacheTTL) {
@unlink($file);
return null;
}
$this->memoryCache[$cacheKey] = $data['data'];
return $data['data'];
} catch (\Throwable $e) {
return null;
}
}
public function set($key, $subKey, $data, $type = 'default'): bool
{
try {
$file = $this->getCacheFile($key, $subKey, $type);
$cacheKey = $this->buildMemoryCacheKey($key, $subKey, $type);
$this->memoryCache[$cacheKey] = $data;
$dir = dirname($file);
if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir));
}
$cacheData = [
'timestamp' => time(),
'data' => $data
];
$content = $this->serialize($cacheData);
if (file_put_contents($file, $content) === false) {
return false;
}
if (function_exists('opcache_invalidate')) {
opcache_invalidate($file, true);
if ($this->cacheFormat === self::FORMAT_PHP) {
opcache_compile_file($file);
}
}
return true;
} catch (\Throwable $e) {
return false;
}
}
protected function serialize($data): string
{
switch ($this->cacheFormat) {
case self::FORMAT_PHP:
return sprintf("<?php\nreturn %s;", var_export($data, true));
case self::FORMAT_JSON:
return json_encode($data, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE);
case self::FORMAT_MSGPACK:
return msgpack_pack($data);
case self::FORMAT_IGBINARY:
return igbinary_serialize($data);
default:
throw new \RuntimeException("Unsupported cache format: {$this->cacheFormat}");
}
}
protected function unserialize($content)
{
switch ($this->cacheFormat) {
case self::FORMAT_PHP:
return include $content;
case self::FORMAT_JSON:
return json_decode($content, true, 512, JSON_THROW_ON_ERROR);
case self::FORMAT_MSGPACK:
return msgpack_unpack($content);
case self::FORMAT_IGBINARY:
return igbinary_unserialize($content);
default:
throw new \RuntimeException("Unsupported cache format: {$this->cacheFormat}");
}
}
protected function getCacheExtension(): string
{
switch ($this->cacheFormat) {
case self::FORMAT_PHP:
return '.php';
case self::FORMAT_JSON:
return '.json';
case self::FORMAT_MSGPACK:
return '.msg';
case self::FORMAT_IGBINARY:
return '.igb';
default:
return '.cache';
}
}
protected function buildMemoryCacheKey($key, $subKey, $type): string
{
return sprintf('%s_%s_%s', $type, $key, $subKey);
}
protected function getCacheFile($key, $subKey, $type): string
{
return $this->cacheDir . $type . '/' . $key . '/' . $subKey . $this->getCacheExtension();
}
public function clear($key = null, $subKey = null, $type = null): void
{
if ($key === null && $subKey === null && $type === null) {
$this->memoryCache = [];
} else {
$pattern = sprintf(
'%s%s%s',
$type === null ? '' : $type . '_',
$key === null ? '' : $key . '_',
$subKey ?? ''
);
foreach ($this->memoryCache as $cacheKey => $value) {
if (strpos($cacheKey, $pattern) === 0) {
unset($this->memoryCache[$cacheKey]);
}
}
}
if ($key === null && $subKey === null && $type === null) {
$this->clearDirectory($this->cacheDir);
$this->ensureStructure();
return;
}
if ($type !== null) {
$typeDir = $this->cacheDir . $type;
if ($key === null) {
$this->clearDirectory($typeDir);
return;
}
$keyDir = $typeDir . '/' . $key;
if ($subKey === null) {
$this->clearDirectory($keyDir);
return;
}
$file = $this->getCacheFile($key, $subKey, $type);
if (file_exists($file)) {
unlink($file);
if (function_exists('opcache_invalidate')) {
opcache_invalidate($file, true);
}
}
}
}
protected function clearDirectory(string $dir): void
{
if (!is_dir($dir)) return;
$files = glob($dir . '/*');
foreach ($files as $file) {
if (is_dir($file)) {
$this->clearDirectory($file);
@rmdir($file);
} else {
@unlink($file);
if (function_exists('opcache_invalidate')) {
opcache_invalidate($file, true);
}
}
}
}
public function getStats(): array
{
return [
'format' => $this->cacheFormat,
'ttl' => $this->cacheTTL,
'memory_cache_size' => count($this->memoryCache),
'directory' => $this->cacheDir,
'extensions' => [
'msgpack' => extension_loaded('msgpack'),
'igbinary' => extension_loaded('igbinary'),
'opcache' => function_exists('opcache_invalidate')
]
];
}
}
And with this /lib/Cache/Lang/LangCache.php:
Code: Select all
<?php
namespace FormaLms\lib\Cache\Lang;
use FormaLms\lib\Cache\BaseCache;
class LangCache extends BaseCache
{
private const CACHE_DIR = 'languages';
private const CACHE_TTL = 86400;
// Compatibile con PHP 7.4: rimosso `: static`
public static function getInstance(?string $format = self::FORMAT_JSON, ?int $ttl = self::CACHE_TTL, ?string $namespace = null)
{
return parent::getInstance($format, $ttl, $namespace);
}
protected static function getSubDir(): string
{
return self::CACHE_DIR;
}
/**
* Override ensureStructure to add specific directories for language cache
*/
protected function ensureStructure(): void
{
$dirs = [
$this->cacheDir . '/lists',
];
foreach ($dirs as $dir) {
if (!is_dir($dir) && !mkdir($dir, 0755, true) && !is_dir($dir)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir));
}
}
}
/**
* Override getCacheFile for language-specific path structure
*/
protected function getCacheFile($lang_code, $key, $type): string
{
switch ($type) {
case 'translation':
return $this->cacheDir . '/' . $lang_code . '/translations/' . $key . $this->getCacheExtension();
case 'language':
return $this->cacheDir . '/' . $lang_code . '/info' . $this->getCacheExtension();
case 'language_list':
return $this->cacheDir . '/lists/available' . $this->getCacheExtension();
case 'module_list':
return $this->cacheDir . '/lists/modules' . $this->getCacheExtension();
default:
return $this->cacheDir . '/' . $type . '/' . $lang_code . '/' . $key . $this->getCacheExtension();
}
}
}
Re: Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Thu Jul 31, 2025 9:37 am
by prashantt
Hello @alfa24,
Thanks for your reply.
After changing code as mentioned in those files the installation starts fine but i face another issue i.e
After entering the correct database information, I get the following error i.e :
Can't connect to DB, please check inserted data
I tested on two of servers where i have MYSQL 5.7.44 and same issue occurs.
What could be the issue?. Could you please replicate ?.
Re: Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Thu Jul 31, 2025 10:00 am
by alfa24
What is the full name of installed mysql package? You can find it in phpinfo
Re: Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Thu Jul 31, 2025 10:14 am
by prashantt
Hello @alfa24,
Following is the info of installed mysql package :

- phpinfo.png (10.72 KiB) Viewed 196 times
Please check.
Re: Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Thu Jul 31, 2025 10:35 am
by alfa24
What about the mysql SERVER version? I mean the package installed on your server. Depending on your o.s. you have different commands to obtain the info.
Re: Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Thu Jul 31, 2025 10:42 am
by prashantt
It's MYSQL community server 5.7.44. I have checked with mysql -v and here is the output :
Let me know if you need any further information.
Re: Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Thu Jul 31, 2025 10:47 am
by alfa24
That should be ok, the issue is to be found in authentication probably, but one should be on your instance to help further.
In any case, this is no more a Forma related issue.
Re: Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Thu Jul 31, 2025 11:11 am
by prashantt
Hello @alfa24,
Thanks for your good support . But is there any way to debug the same?. Cause I checked this now also with Alma Linux 9.6 and Server version: 8.0.43 MySQL Community Server - GPL. There too I get the same issue, even with the correct credentials being entered.
Re: Forma LMS 4.0.19 : Unable to start installation due to syntax error on PHP 7.4
Posted: Thu Jul 31, 2025 11:19 am
by alfa24
Debug is up to you... As I wrote, I can't help further without being on your instance, sorry.