Cusy
Cusy

Reputation: 243

require_once not working but require does in php

I need to access a configuration variable from inside a method in a public class. The file where the variable is stored is included into the ajax.php page where I also call the class constructor and his method

<?php
    include_once('../config/config.php');
    [...]
    $myclass = new myclass();
    $res = $myclass->mymethod();
    echo json_encode($res);
?>

I tried to print the $config variable stored into config.php from inside the myclass method mymethod and it doesn't do anything. If I try to call include_once('../config/config.php') it doesn't load anything and the $config varialbe is always empty, while if I try to include('../config/config.php') I can access the $config variable data without problem.

So, if I understand correctly how include and include_once works, the _once just skip to import the file 'cause it has already been included before. My question is, how can I access $config without being forced to include it again with include (not _once) ?

Upvotes: 0

Views: 799

Answers (2)

Senhorzim
Senhorzim

Reputation: 141

As a another way to do the same thing as was suggested before:

config.php

<?php 
return array(
    'hostname' => 'localhost',
    'username' => 'dev',
    'passwrod' => '',
);

MyConfig.php

<?php
class MyConfig extends ArrayObject
{
    public function __construct($filename)
    {
        parent::__construct();
        $this->setFlags(ArrayObject::ARRAY_AS_PROPS);

        if (!is_readable($filename)) {
            throw new InvalidArgumentException("Invalid file name: ".$filename);
        }
        $loaded_data = include($filename);

        foreach ($loaded_data as $index => $value) {
            $this->offsetSet($index,$value);
        }
    }
}

And then you can use like this MyClass.php

class MyClass{
    private $config;

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

    public function mymethod(){
        return $this->config->hostname .":". $this->config->username;
        // or even
        //return $this->config['hostname'] .":". $this->config['username'];
    }
}

the nice thing about MyConfig inheriting ArrayObject is that you can use the array values as properties.

Upvotes: 1

Steve
Steve

Reputation: 20469

Your problem is understanding variable scope. You need a way to make your config array accessible to your class level methods.

The simplest method would be to pass a copy to the class in the constructor (or the individual method if it is only required in one):

//config.php

$config=array(
    'something'=>'value',
    'somethingelse'=>10
);

//myclass.php    
class MyClass{
    private $config;

    public function __construct(array $config){

        $this->config = $config;
    }

    public function mymethod(){

        return $this->config['something'];
    }
}

//index.php 
include_once('../config/config.php');

$myclass = new MyClass($config);

echo $myclass->mymethod();//outputs 'value'

If this is purely readonly another option would be to wrap config array in a static class method:

//config.php
class Config{
    public static function getConfig(){
    return array(
        'something'=>'value',
        'somethingelse'=>10
        );
    }
}

//index.php 
include_once('../config/config.php');

//anywhere in your code
$config = Config::getConfig();

echo $config['something'];

This initializes a new array every time its called so its not a great option.

A third option would be to wrap your config in a singleton class, which is initialized only once but available via a static method call anywhere

//config.php
class Config{
    public $config;
    private static $inst=null;

    private function __construct(){
        $this->config=array(
            'something'=>'value',
            'somethingelse'=>10
        );
    }

    public static function Instance(){
        if(static::$inst==null){
            static::$inst=new Config();
        }
        return static::$inst;
    }
}

//index.php 
include_once('../config/config.php');

//anywhere in your code

echo Config::Instance()->config['something'];

The singleton pattern is convenient, but has its (often debated well publicised) problems.

Ultimatly the 1st option is probably what you need.

Upvotes: 2

Related Questions