So I've got a bug somewhere in my code that stops certain elements from being included in an array, this is the best way that I can explain it.
I've got a static file (Config.php) that contains a large array full of data, within this array there is another array with a key of "PredefinedValues", this contains values that need to be referenced by other parts of the script.
The issue: I can reference everything in the array except for 5 values that I recently added, I var_dump the array and they're not there when they're clearly in the file. I've reuploaded the files to my web server around 5/6 times, restarted php, restarted the server and it's not fixed. The issue does not occur on my local machine (Windows) but it does occur on my Linux server (Ubuntu).
The array is structured like this:
<?php
global $Configuration;
$Configuration = array(
"PredefinedValues" => array(
"Example" => "example",
"123" => "test",
"abc" => "test2",
"asdf" => "value2",
"val2" => "value3",
),
And the values I wouldn't be able to access are abc/asdf - but all of the values above/below it are fine.
Init file:
require_once("config/Config.php");
Class Lib
{
Public $Root = __DIR__;
Public $DependencyRoot;
Public function __construct()
{
//error_reporting(E_ERROR | E_WARNING | E_PARSE);
error_reporting(E_ALL);
Global $Configuration;
var_dump($Configuration["PredefinedValues"]);
$this->DependencyRoot = __DIR__ . "/libs/Dependencies/";
}
}
?>
Var_dumping the array within the __construct doesn't work, but when I var_dump it straight after the require, it works fine.
Any ideas? Help would be greatly appreciated.
Related
I suppose I am a noob with PHP so apologies if I sound dumb, but, I do have a troubling dilemma, I have spent the last six hours plus scouring Google for any hints and found none so here I am on the SO forum looking for some 'pointers' in the right direction.
I have an issue with returning 3DAA's from a function in a class to other parts of my code and no matter what I try I'm getting a null value back, according to the error log anyway, but when I run this code separately from the framework, in a single file using the same declarations it miraculously starts working and echos the specified part of the array to the screen wahey, but I don't know why it suddenly works nor why it won't work in the framework and supplies a null value.
I was wondering if anyone out there has experienced such weird errors with returning 3DAA's and if so, how they got around it. If you want to see the code ask and I'll post it.
<?php
class Core {
public function GetConfiguration() {
$configuration = array(
"cobalt" => array(
"name" => 'Cobalt',
"version" => '1.0.7',
"directory" => array(
"root" => 'application',
"modules" => 'application/modules',
"html" => 'application/html'
)
),
"application" => array(
"name" => 'Cardinal Technologies',
"version" => '1.0.2',
"server" => 'http://localhost',
"seo" => array(
"copyright" => 'Ida Boustead',
"description" => 'Welcome to Cardinal Technologies, here at Cardinal Technologies we pride ourselves in providing the best possible customer service whether you need a repair or upgrade for a computer, android phone or tablet, even alarms and CCTV',
"keywords" => 'computer repair,computer upgrade,computer upgrades,android phone repair,phone repair,android tablet repair,tablet repair,alarms,cctv,network installation,network install',
"robots" => 'index,follow'
)
)
);
return $configuration;
}
public function LoadModule($module) {
require_once 'application/modules/' . $module . '.class.php';
}
}
?>
Hope this helps.
I'm calling it like this.
require_once 'application/Core.class.php';
$core = new Core();
$configuration = $core->GetConfiguration();
and getting an array value like this.
$dir = $configuration['cobalt']['directory']['html'];
the prior is a snippet from a larger file but this is what relates to that function.
I get PHP Notice: Undefined variable: dir in the log which is what led me to believe the function was the problem.
If I echo $dir it echos application/html which is what it's supposed to, but it is not usable for anything other than echo which is pointless to me as I need that value to make other parts of the framework work.
Right it was me being a dumb dumb, I put the declarations in the wrong place, outside of the class and it did not like it.
I moved them to inside of each function that stalled the code and it fixed that issue. Thanks anyway.
I'm learning the basics of PHP and Laravel. I need to understand the syntax of this piece of code taken from a Laravel config file named app.php . I shortened the contents of this file to fit here. I'm only interested in the syntax.
<?php
return [
'name' => env('APP_NAME', 'Laravel'),
'env' => env('APP_ENV', 'production'),
'providers' => [
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
],
];
?>
I know what return does in a function. It terminates the function and returns a value. But here it is all by itself returning an array I think. Please correct me if I'm wrong. It returns an associative array where the keys are: name, env, providers. The double arrows assign values to the keys in the array. So for instance env('APP_ENV', 'production'); is assigned as a value to 'env' key.
Another thing is where this return returns the array? Is this file included in some other file?
The other thing I don't understand is the env() call. Is it a built in PHP function? What does it do?
Where this return returns the array? Is this file included in some other file?
Laravel reads and then uses the arrays returned by config files in the Illuminate\Config\Repository class.
So, when you read the value with something like config('app.name'), it does:
public function get($key, $default = null)
{
if (is_array($key)) {
return $this->getMany($key);
}
return Arr::get($this->items, $key, $default);
}
Where $this->items is config data read from config files (the arrays you're talking about). If you curious how and where it Laravel read config files, check the Illuminate\Foundation\Bootstrap\LoadConfiguration class:
protected function loadConfigurationFiles(Application $app, RepositoryContract $repository)
{
$files = $this->getConfigurationFiles($app);
if (! isset($files['app'])) {
throw new Exception('Unable to load the "app" configuration file.');
}
foreach ($files as $key => $path) {
$repository->set($key, require $path);
}
}
include can also return a value (in this case an array) that will be assigned to a variable in the script that is doing the include. See the section in the PHP Docs (immediately below the security warning)
Also, it's possible to return values from included files. You can take the value of the include call as you would for a normal function.
And look at Example #5
And env() is a Laravel function
The env function retrieves the value of an environment variable or returns a default value
I am using CakePHP3.
I prefer to put my application-wide PHP constants and Configure::write values inside a separate php file, usually called constants.php
And then at the end of the bootstrap.php, I will include this constants.php file.
I have no problems with the PHP constants. However, I have issues using Configure::write inside this separate file.
Is there a way to use Configure::write in a separate php file? I have tried using
use Cake\Core\Configure;
inside constants.php but I still get errors.
EDIT
Example of constants.php
<?php
/**
* provide all the kinds of site ID
*/
Configure::write('ADMINISTRATOR_SIDEBAR', array(
'quotations' => [
'link' => '/quotations',
],
'projects' => [
'sub_menu' => [
[
'title' => 'Project 1',
'icon' => '',
'link' => '/job_projects/view/5',
]
],
'link' => '/job_projects'
]
));
When I write that and then
require __DIR__ . '/constants.php';
in the last line of bootstrap.php
I get
Error: Class 'Configure' not found
File ...constants.php
Line: 8
When I then added use Cake\Core\Configure; at the top of constants.php, the error is removed.
Does this mean my issue is solved?
Do you have that many constants? Use class constants instead:
class UserType {
const ADMIN = 'admin';
const USER = 'user';
}
IMO it is better to keep them organized in classes than having tons of global constants. I dislike constants most of the time because you can't really never ever change them at run time. So this leaves just two use cases for them:
Things that should never ever change at runtime (which is rare)
Using them for "identifiers" instead of strings
Explaining 2. a little more: $userRole === 'admin' can fail because of a typo, you won't get an error and might end up with a pretty shitty to debug situation while doing $userRole === UserRole::ADMIN will throw an error if it is not present.
You're not showing any code, so no idea what you're doing wrong with Configure. Why are you not simply using Configure::load() and the `$config = []' array in the file you're going to load with that method?
I have the following setup with Laravel 4.2:
bootstrap/start.php (hostname correct, environment is local)
$env = $app->detectEnvironment(array(
'production' => array('produrl'),
'local' => array('MBP-Ivo.local', 'iMac-Ivo.local'),
));
.env.local.php (in project root, .env.php is exactly the same except mysql info)
<?php
return [
// Code variables
'mysqlUsername' => 'user',
'mysqlPassword' => 'password',
'mysqlDatabase' => 'database',
'paymentIdeal' => false,
'shipmentCountries' => [
'Nederland' => 'Nederland',
'Belgie' => 'Belgie'
]
];
config/app.php (I don't overwrite with app/config/local/app.php)
<?php
return array(
'paymentIdeal' => $_ENV['paymentIdeal'],
'shipmentCountries' => $_ENV['shipmentCountries']
);
There are some more variables, but the problem is with shipmentCountries.
Undefined index: shipmentCountries
All variables declared are working (eg paymentIdeal), but shipmentCountries gives an error. I think because it's an array? The name is exactly the same everywhere, including capital letters.
Does anyone know why I can't get this working?
BTW: I'm choosing this option to prevent users having to change their application configs. I want to use only one *.env file to configure all important stuff. And yes, I know these values could be saved to the database, but that's for later :)
/edit:
When I dump the $_ENV, I get the following:
Array
(
[mysqlUsername] => ***
[mysqlPassword] => ***
[mysqlDatabase] => ***
[paymentIdeal] =>
[shipmentCountries.Nederland] => Nederland
[shipmentCountries.Belgie] => Belgie
);
Somehow it "flattens" the array shipmentCountries. Anyone knows how and why?
You're right, the file get's converted in a flat array using the dot notation (with array_dot)
I believe the reason behind this, is that environment variables are just not supposed to be arrays as they are normally passed in when using a CLI.
So, what can you do about it?
Convert the array from dot to non-dot
In your app/start/global.php use this code to convert the array back to it's original format:
$array = array();
foreach ($_ENV as $key => $value) {
array_set($array, $key, $value);
}
$_ENV = $array;
Use another file and load it yourself
Also inside app/start/global.php (this would be .my.env.local.php)
$config = require base_path().'/.my.env.'.app()->env.'.php';
$_ENV = array_merge($_ENV, $config);
Sidenotes
I'd think again if you really don't want to use config files. It is possible to have your own config file and maybe you can even place it in the root of the project.
Also I'd change the array to a numeric one:
'shipmentCountries' => [
'Nederland',
'Belgie'
]
With the tip of lukasgeiter, I went searching again, and found this:
https://github.com/laravel/framework/issues/5291 and https://github.com/laravel/framework/pull/4623
It looks like Laravel doesn't support this option.
What I do now is save it as a JSON string, and decode it when neccesary.
Another way is to json_encode your associative array in the env.local.php, then in your config
json_decode($_ENV['shipmentCountries'],true);
Don't forget the boolean argument there to make it convert into arrays.
This question already has answers here:
Reference: What is variable scope, which variables are accessible from where and what are "undefined variable" errors?
(3 answers)
Closed 9 years ago.
I am trying to get figure this out and haven't been able to. I'm trying to create a function that will include different config files into the script when needed. I want to store all the variables in arrays and then use a function to include them.
Example
Config.php
$array = array(
'var1' => 'something',
'var2' => 'something else'
);
uses.php
class uses{
public static function file($directory, $file){
if(is_dir($directory))
{
if(is_file($directory.$file))
{
include $directory.$file;
}
else
{
echo "File Not Found $directory$file";
}
}
else
{
echo 'Dir Not Found';
}
}
}
index.php after I've included uses the file
uses::file(Config.php);
print_r($array);
I know if you include a file inside a function they won't reach past the scope of the function. This would be loaded in by an auto loader so I would be able to use it anywhere inside my script.
Thanks in advance, if you need any more information please let me know.
It appears to me you may be going about this the wrong way. But first off the problems with the code you presented. Your code appears to be asking for two parameters but you are only passing in one. This will make your is_dir / is_file calls always fail because both of the conditions will never be true at the same time so your file isn't include.
Also you don't appear to be assigning the returned value to anything that has a lifetime greater then that of run time of your static function so even if the file was included your config variable would end up being thrown away.
To clean up your existing code you could do something along these lines.
<?php
class Config {
static public $config;
public static function load($path, $file){
if (file_exists($path.$file) && is_file($path.$file)){
self::$config = include ($path.file);
}
}
}
Then you would change your included file to return the data instead of assigning it to a variable. Like
<?php
return array(
'var1' => 'something',
'var2' => 'something else'
);
Then you would be able to use it like this.
Config::load("/path/to/config/", "Config.php");
echo Config::$config["var1"];
While this will make the code behave the way you are trying to do it this is probably a bad idea. You should be using Dependency injection within your other classes instead of invoking the static property with your other classes. This will afford you a seam when doing testing and also allow your methods and classes to document in the constructor and method signatures exactly what is needed to perform a given task. See this video for more information on what DI is, and this google clean code talk to help understand why using statics like this is a bad idea.
Take a look at this: http://php.net/manual/en/function.parse-ini-file.php
But in simple terms you could so this:
config.inc.php
$config['var1'] = 'Hello';
$config['var2'] = 'World';
Then in your php:
include_once('config.inc.php');
or you could use this for an INI style include file: http://php.net/manual/en/function.parse-ini-file.php
config.inc.php
[first_section]
one = 1
five = 5
animal = BIRD
[second_section]
path = "/usr/local/bin"
URL = "http://www.example.com/~username"
Then in your php:
$ini_array = parse_ini_file("sample.ini", true);
print_r($ini_array);