Могу ли я установить свойство класса PHP из существующей переменной? - PullRequest
0 голосов
/ 22 января 2010

Я пытаюсь выяснить, как я хочу обрабатывать настройки в моем приложении PHP. Я в значительной степени решил, что я хотел бы использовать файл класса Confg, чтобы он был автоматически загружен и гибок в будущем. Ниже приведены некоторые вещи, с которыми я играл.

Я знаю, что вы не можете установить переменную для заполнения константы, поэтому я попытаюсь использовать открытое статическое свойство.

Почему я не могу установить public static $ ip = $ _SERVER ['REMOTE_ADDR']; ??

<?php
// config.class.php
class Config
{
    const URL = 'http://www.foo.com';
    const DB_User = 'dbname';

    public static $test = 'test string';
    public static $ip = $_SERVER['REMOTE_ADDR'];
}

///////////////////////////////////////////////////////
//index.php

// works
echo Config::URL;

// works
echo Config::$test;

// DOES NOT WORK
echo Config::$ip;

?>

Ответы [ 7 ]

3 голосов
/ 22 января 2010

члены должны быть инициализированы константным выражением (например, строковая константа, числовой литерал и т. Д.). php выдаст ошибку разбора, если вы попытаетесь инициализировать член динамическим выражением (например, значением переменной или вызовом функции) ...

это не похоже на некоторые другие языки, такие как python или javascript, которые считают, что определения классов находятся на одном уровне с исполняемыми выражениями ... так что ваша идея здесь очень функциональна, но php по крайней мере сейчас ее не поддерживает ...

но есть несколько альтернатив:

добавить инициализацию после определения класса:

class C {...}
C::$var = $_SERVER['REMOTE_ADDR'];

или иметь функцию инициализации:

function init()
{
  if (self::$init === false) {
    self::$var = $_SERVER['REMOTE_ADDR'];
    self::$init = true;
  }
}

C::init();

или с более новым php, вы можете использовать хук __autoload () для выполнения статической инициализации ...

2 голосов
/ 06 апреля 2010

попробуйте использовать define () для этого (задайте константу!):

// config.class.php
define(REMOTE_ADDR, $_SERVER['REMOTE_ADDR']);

    class Config
    {
        const URL = 'http://www.foo.com';
        const DB_User = 'dbname';

        public static $test = 'test string';
        public static $ip = REMOTE_ADDR;
    }
2 голосов
/ 22 января 2010

Хотя это не отвечает на ваш вопрос (jspcal отвечает на него правильно), быстрое решение, которое может соответствовать вашим потребностям, будет использовать шаблон проектирования Singleton . Вот альтернатива:

<?php

// config.class.php
class Config
{
    /**
     * Instance container
     * @var Config
     */
    private static $instance = null;

    /**
     * Constants container
     * @var array
     */
    private $constants = array(
        'url'     => 'http://www.foo.com/',
        'db_user' => 'dbname'
    );

    /**
     * Options container
     * @var array
     */
    private $options = array();

    /**
     * Don't allow outside initialization
     */
    private function __construct()
    {
        // Set options (could load from external source)
        $this->options = array(
            'test' => 'test string',
            'ip'   => $_SERVER['REMOTE_ADDR']
        );
    }

    /**
     * Disable cloning
     */
    private function __clone() { }

    /**
     * Get new instance of class
     */
    public function getInstance()
    {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Retrieve value with constants being a higher priority
     * @param $key Key to get
     */
    public function __get( $key )
    {
        if ( isset( $this->constants[$key] ) ) {
            return $this->constants[$key];
        } elseif ( isset( $this->options[$key] ) ) {
            return $this->options[$key];
        }
    }

    /**
     * Set a new or update a key / value pair
     * @param $key Key to set
     * @param $value Value to set
     */
    public function __set( $key, $value )
    {
        $this->options[$key] = $value;
    }
}

///////////////////////////////////////////////////////
//index.php

// works
$config = Config::getInstance();
echo $config->url;
echo $config->test;
echo $config->ip;

Обновлено: Не уверен, что вам нужны константы / опции с таким приоритетом. Это просто пример.

1 голос
/ 23 января 2010

Это не ответ на ваш вопрос, но, на мой взгляд, лучший способ работы с конфигурациями - это использовать real файл конфигурации, такой как INI или XML-файл.

Вы можете использовать, например, Zend Config класс для чтения и записи таких файлов (и этот класс может даже работать с простым массивом PHP в качестве конфигурации.

В конце концов, это облегчит поддержку вашего кода.

После прочтения других ответов и комментариев вас также может заинтересовать класс Zend Registry .

В общем, я бы посоветовал использовать фреймворк или готовые компоненты для таких вещей. Вам не нужно изобретать велосипед, и вы можете воспользоваться опытом другого.

1 голос
/ 22 января 2010

Не прямой ответ на ваш вопрос, но почему бы вам не использовать менее закодированный подход, например универсальный класс Config, который вы можете использовать в своих приложениях

// MyConfig.php
class MyConfig {
    protected $_data;

    public function __construct($path)
    {
        $config = include $path;
        $this->_data = $config;
    }

    public function __get($val)
    {
        if(array_key_exists($val, $this->_data)) {
            return $this->_data['val'];
        } else {
            trigger_error("Key $val does not exist", E_USER_NOTICE);
        }
    }
}

, который вы можете заполнить из массива для конкретного приложения

// app-config.php
return array(
    'ip' => $_SERVER['REMOTE_ADDR'],
    'url' => 'http://www.foo.com';
    'db'  => array(
        'host' => 'foo.com',
        'port' =>  3306
    ),
    'caching' => array(
        'enabled' => false
    )
);

и затем используйте в своем загрузчике как

$config = new MyConfig('/path/to/app-config.php');
0 голосов
/ 22 января 2010

PHP просто не позволяет этого. Если вы думаете об этом, в любом случае не имеет смысла включать REMOTE_ADDR в ваши данные конфигурации. Вы можете считать это частью данных запроса, а не конфигурацией приложения.

Что касается вашей конфигурации, я бы предложил использовать INI-файл для вашей конфигурации, потому что в PHP есть встроенный анализатор INI (см. Функцию parse_ini_file). Это соответствовало бы выбору PHP формата файла INI для его собственной конфигурации (то есть php.ini).

Проверьте этот вопрос, например: Какой формат файлов является лучшим для файлов конфигурации

0 голосов
/ 22 января 2010

Это не сработает, потому что PHP просто не позволяет.

Как правило, я бы не советовал помещать конфигурацию вашего приложения в класс (по крайней мере, не в PHP), на мой взгляд, никаких реальных преимуществ нет - лучше поместить его в глобальный массив или около того:)

...