我可以从现有变量设置PHP类属性吗?

时间:2010-01-22 20:42:18

标签: php class properties settings const

我想弄清楚我想如何处理我的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;

?>

8 个答案:

答案 0 :(得分:3)

必须使用常量表达式(如字符串常量,数字文字等)初始化

成员。如果您尝试使用动态表达式初始化成员(如变量或函数调用的值),PHP将给出解析错误...

这与其他一些lang类似,比如python或者javascript,它们认为类定义与可执行表达式相同......所以你的想法非常实用,但php现在至少不支持它...... / p>

但有一些替代方法可以解决这个问题:

在类定义后添加初始化:

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

或者有一个init函数:

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

C::init();

或者使用较新的php,您可以使用__autoload()钩子进行一些静态初始化...

答案 1 :(得分: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;

更新:不确定您是否希望常量/选项具有此类优先级。这只是一个例子。

答案 2 :(得分: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;
    }

答案 3 :(得分:1)

不能直接回答您的问题,但为什么不使用较少硬编码的方法,例如:您可以在应用中重复使用的通用配置类

// 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');

答案 4 :(得分:1)

这不是回答你的问题,但在我看来,处理配置的更好方法实际上是使用真正的配置文件,如INI或XML文件。

您可以使用例如Zend Config类来读取和写入这样的文件(这个类甚至可以处理普通的PHP数组作为配置。

最后,这将使您的代码更易于维护。

在阅读其他答案和评论后,您可能也会对Zend Registry课程感兴趣。

一般来说,我建议使用框架或现成的组件来做这些事情。你不需要重新发明轮子,你可以从对方的经验中获益。

答案 5 :(得分:0)

它不起作用,因为PHP不允许它。

一般情况下,我不会建议将你的应用程序的配置放到一个类中(至少不是在PHP中),我认为没有真正的优势 - 最好将它放入全局数组中:)

答案 6 :(得分:0)

PHP根本不允许这样做。如果你考虑一下,将REMOTE_ADDR作为配置数据的一部分是没有意义的。您可以将其视为请求数据的一部分,而不是应用程序配置。

至于您的配置,我建议您使用.ini文件进行配置,因为PHP有​​一个内置的INI解析器(请参阅parse_ini_file函数)。这与PHP为自己的配置(即php.ini)选择的INI文件格式一致。

查看此问题,例如:What's Is the Best File Format for Configuration Files

答案 7 :(得分:0)

不能将 $_SERVER['REMOTE_ADDR'] 分配给 class 属性的简单原因是这个。

在 PHP 中,Class 属性值只能是数据类型,不能是变量,而且由于 $_SERVER 是全局数组变量,所以不能赋值给属性。