@xzdev

Можно ли исправить эту очень полезную функцию PHP?

День добрый!
Имеется функция, которая должна рекурсивно получать значения и изменять массив в удобном для меня формате - через точки вместо кучи квадратных скобок.
Существует массив $CONF в котором заданы параметры. Эти параметры могут изменяться на лету, в процессе работы приложения. Это выглядит удачно, но это не работает:(
Возможно в старых версиях PHP такой синтаксис и пройдёт, но на PHP 7.2 выдаёт ошибку:
[ParseError] syntax error, unexpected '&' (0)
function aGetByKey(&$array, $key, $value = null) {
    list($index, $key) = explode('.', $key, 2);
    if (!isset($array[$index])) throw new Exception("No such key: " . $index);

    if(strlen($key) > 0)
        return aGetByKey(&$array[$index], $key, $value);

    $old = $array[$index];
    if ($value !== null) $array[$index] = $value;
    return $old;    
}

function conf($key, $value = null) {
    global $CONF;
    return aGetByKey(&$CONF, $key, $value);
}

Хотелось-бы чтобы она работала так:
echo conf('category.name'); //Hello
echo conf('category.name', 'World'); //true
echo conf('category.name'); // World

echo conf('category.data', ['amount' => 158, 'kind' => 36]); //true
echo conf('category.data')['amount']; //158


У меня не хватает опыта, чтобы портировать её на новый синтаксис, ибо не имею представления о том как оно должно работать эффективно, кроме как перебор через foreach и explode.
Прошу вашей помощи,ваш сниппет будет полезен многим заглянувшим.
  • Вопрос задан
  • 179 просмотров
Пригласить эксперта
Ответы на вопрос 3
Ninazu
@Ninazu
Если уже переписываете, то переписывайте нормально. Избавляйтесь от глобального массива $CONF, рекурсии и функций без неймспейсов. Также у вас функция как записывает так и читает значения, что немного выносит мозг. Также считаю что исключению там не место, лучше заменить на значение по умолчанию

class Config {

	protected static array $register = [];

	public static function get(string $name, $default = null) {
		$keys = explode('.', $name);

		$pointer = self::$register;

		foreach ($keys as $key) {
			if (!array_key_exists($key, $pointer)) {
				/*Если ключа нет, выставить его*/
				//self::set($name, $default);

				/*Бросить исключение*/
				//throw new Exception("No such key: {$name}");

				/*Вернуть значение по умолчанию*/
				return $default;
			}

			$pointer = &$pointer[$key];
		}

		return $pointer;
	}

	public static function set(string $name, $value = null) {
		$arr = &self::$register;
		$keys = explode('.', $name);

		foreach ($keys as $key) {
			$arr = &$arr[$key];
		}

		if (is_array($arr) && is_array($value)) {
			$arr = array_replace_recursive($arr, $value);
		} else {
			$arr = $value;
		}
	}

	public static function getTree() {
		return self::$register;
	}
}

Config::set("config", [
	"name" => "test",
]);
print_r(Config::get("config"));
echo "(config)\n\n";

Config::set("config.class.name", "A");
print_r(Config::get("config.class.name"));
echo "\n(config.class.name)\n\n";

Config::set("config", [
	"class" => [
		"test" => "B",
	],
]);
print_r(Config::get("config.class"));
echo "\n(config.class)\n\n";

Config::set("config.class", null);
print_r(Config::get("config.class"));
echo "\n(config.class)\n\n";

print_r(Config::get("config.fake.key.without.value", "UNDEFINED"));
echo "\n(config.fake.key.without.value)\n\n";

Config::set("config.nullable", null);
print_r(Config::get("config.nullable", "NULL"));
echo "\n(config.nullable)\n\n";

print_r(Config::getTree());
echo "\n(all)\n";


Работает в PHP7.4
Ответ написан
VladimirAndreev
@VladimirAndreev
php web dev
return aGetByKey($CONF, $key, $value);
Ответ написан
Комментировать
@AUser0
Чем больше знаю, тем лучше понимаю, как мало знаю.
Исходный вариант кода, но исправленный:
$CONF = array('category' => array('name' => "Hello", 'data' => array()));

function aGetByKey(&$array, $index, $value = null) {
    if (strpos($index, "."))
        list($index, $key) = explode('.', $index, 2);
    if (!isset($index) OR !isset($array[$index]))
        throw new Exception("No such key: " . $index);

    if(!empty($key))
        return aGetByKey($array[$index], $key, $value);

    $old = $array[$index];
    if ($value !== null)
        $array[$index] = $value;

    return $old;
}

function conf($key, $value = null) {
    global $CONF;
    return aGetByKey($CONF, $key, $value);
}

//Хотелось-бы чтобы она работала так:
echo conf('category.name'); //Hello
echo conf('category.name', 'World'); //Hello, потому что возвращается предыдущее значение $old
echo conf('category.name'); // World

conf('category.data', ['amount' => 158, 'kind' => 36]); // echo() нельзя, потому что вернётся массив
echo conf('category.data')['amount']; //158
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы