2010-01-22 3 views
0

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

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

Почему я не могу установить 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; 

?> 

ответ

2

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

<?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; 

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

+0

Хотя это альтернатива тому, что вы ищете, я бы рекомендовал, возможно, установить массив как закрытый для хранения значений и использования магических переменных PHP __get __set и извлекать значения массива. – William

+0

На самом деле это своего рода то, что я думал о том, как это нужно сделать, чтобы это хорошо +1 – JasonDavis

+0

Обновлено с лучшим примером. – William

3

Элементы должны быть инициализированы постоянным выражением (например, константой строки, числовым литералом и т. Д.). 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() крюк, чтобы сделать некоторые статические инициализации ...

+0

Знаете ли вы хорошие альтернативы, чтобы получить аналогичный результат? – JasonDavis

+0

Обратите внимание, что для людей, придерживающихся PHP4, 'C :: init()' работает, но 'C :: $ var' не делает. – user535673

0

Это не будет работать, потому что PHP просто не разрешить это.

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

+0

Я думаю о создании класса, который будет тянуть файл массива, поэтому я могу просто передать путь к файлу массива или что-то в этом направлении. – JasonDavis

0

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

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

Заканчивать этот вопрос, например: What's Is the Best File Format for Configuration Files

+0

По крайней мере, скажите мне, почему вы остановились. Я ответил на его вопрос и даже сделал предложение ... –

1

Не прямой ответ на ваш вопрос, но почему бы вам не использовать менее жесткий код, например.общий класс 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

Если я его правильно понимаю, он хочет, чтобы конфиг был в глобальной области. Хотя он мог легко решить это, изменив его на шаблон Singleton или используя шаблон реестра. – William

+0

Это, вероятно, маршрут, по которому я поеду, и да, мне нужно сделать его доступным для всего мира. – JasonDavis

+0

. Я бы предпочел контейнер для инъекций для зависимостей, но, поскольку я предложил это Джейсону в ряде случаев сейчас, я думаю у него есть причины не использовать его. Без этого я бы пошел с реестром по Singleton, просто чтобы иметь несколько объектов Config, и на всякий случай мне нужно иметь что-то еще, что я хочу иметь глобально доступным, а не Config. Реестр более посвящен этому. – Gordon

1

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

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

В конце концов, это будет сделать проще код для поддержания.

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

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

+0

Основная причина для создания себя - это действительно для изучения. Я люблю изучать код из таких вещей, как вы опубликовали, хотя – JasonDavis

2

попробуйте использовать 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; 
    } 
Смежные вопросы