Cannot access global variable from within class constructor - php

Alright so I am trying to simply check if there is something inside the array from construct but it doesnt seem to work at all...
$DB_VALID = array("mysql");
class DB {
function __construct($conn) {
if(in_array($conn,$DB_VALID)) {
echo "exists!";
}
else {
echo "doesnt exist";
}
}
}
Now, since construct is inside a class, if I dump it I will get results saying NULL, but if I dump it outside the construct I will simply get the real results...
Usage
$conn = new DB("mysql");
Results?
in_array returns false

The variable $DB_VALID does not exist inside the __construction function scope.
The recommended solution is that you move $DB_VALID to a static variable inside the DB class, as such:
class DB {
static $DB_VALID = array("mysql");
function __construct($conn) {
if(in_array($conn,self::$DB_VALID)) {
echo "exists!";
}
else {
echo "doesnt exist";
}
}
}
You can later access that array in other parts of your code by referencing it as DB::$DB_VALID.
However, if you must keep the global variable and access it from within __construct, you can use the global keyword to bring it into the local scope, as such:
$DB_VALID = array("mysql");
class DB {
function __construct($conn) {
global $DB_VALID; // Brings the global variable to local scope
if(in_array($conn,$DB_VALID)) {
echo "exists!";
}
else {
echo "doesnt exist";
}
}
}
Please consider the first solution on the future, though, as using global variables is an easy way to have your applications break as they evolve.
Edit: As you mentioned in the comments your restriction is the order you're loading your scripts right now, you should also really look into class autoloading and namespaces, as your projects will get increasingly complex and harder to manage otherwise (see sitepoint.com/autoloading-and-the-psr-0-standard).

If you have to, use the global keyword.
$DB_VALID = array("mysql");
class DB {
function __construct($conn) {
global $DB_VALID; // Makes the variable available in the scope
if(in_array($conn,$DB_VALID)) {
echo "exists!";
}
else {
echo "doesnt exist";
}
}
}
$conn = new DB("mysql"); // will print "exists!"
Note that global variables usually hints organisation problems, so you should probably review your structure and see if it's really necessary to use global here.

Related

Global variable in sub-function no need to declare

whether to do a declare variable when a variable is in a sub-function ?
Like the example carried this:
function cobasaja(){
global $coba;
return $coba;
}
function ditampilkan(){
global $coba;
$coba = "content trying...";
return cobasaja();
}
echo "View: ".ditampilkan();
Why it can not be like this:
function cobasaja(){
global $coba;
return $coba;
}
function ditampilkan(){
//global $coba; <= not declare in viewer function
$coba = "content trying...";
return cobasaja();
}
echo "View: ".ditampilkan();
But the second experiment did not work.
Because as I recall, usually the second way can be done, but now I do it can not, is this because of its PHP version or setting in PHP.ini ?
Adding a function creates a new scope. Any variables you want to use in the function need to be either defined in that scope, brought in from the outer scope with global, or passed in as parameters. This general concept has not changed much over PHP versions as far as I know, so I don't believe your second experiment would have worked in an earlier PHP version, or could work by changing a configuration setting.
If your functions are in the same class, you can use object properties rather than global variables to achieve something like what you want.
class Example {
private $coba = '';
protected function cobasaja() {
return $this->coba;
}
public function ditampilkan() {
$this->coba = "content trying...";
return $this->cobasaja();
}
}

Cakephp 3 how to pass a variable to Contain query? [duplicate]

I want to write a function that does some dirty work logging a transaction, but the anonymous function scope does not seem to register the parent scope $db and $value variables. How can I pass the variables into the closure?
Ironically, the SO tag 'closures' does not describe the PHP version of it very accurately...?
class controller
{
function submit()
{
$db = new database();
$result = $db->execute_tx(function() {
$db->insert_model_a($value_a); // ERROR: $db is non-object
$db->insert_model_b($value_b);
});
}
}
class database
{
function execute_tx($atomic_action)
{
try
{
$this->start();
$atomic_action();
$this->commit();
// etc..
}
catch(...)
{
$this->rollback();
// etc..
}
finally
{
// etc..
}
}
function insert_model_a() { ... }
function insert_model_b() { ... }
}
Use the use keyword to bind variables into the function's scope.
function() use ($db) {
Closures may also inherit variables from the parent scope. Any such variables must be declared in the function header [using use].
http://www.php.net/manual/en/functions.anonymous.php
Since PHP 8.0, arrow functions have been available. These inherit variables from the parent scope without any declarations:
Arrow functions support the same features as anonymous functions, except that using variables from the parent scope is always automatic.
They are intended for use with single expressions, so are not ideal for the code in the question, but using two of them would work:
class Controller
{
function submit()
{
$db = new database();
// one assumes $value_a and $value_b are defined in the submit method
$result = $db->execute_tx(fn() => $db->insert_model_a($value_a));
$result = $db->execute_tx(fn() => $db->insert_model_b($value_b));
}
}

using a classes functions in the global space in php?

Is it possible to extract all methods out of a class instance and use them in the global space?
Say I have:
class Library {
public function num_one() { echo "number one"; }
public function num_two() { echo "number two"; }
}
After I load the class, I want to be able to use the functions without specifying the instance
include '/path/to/library-class.php';
$lib = new Library();
#$lib->num_one();
#$lib->num_two();
num_one();
num_two();
You could make them static, for example
class Library {
public static function num_one() { echo "number one"; }
public static function num_two() { echo "number two"; }
}
then you could use
Library::num_one()
Library::num_two()
You also wouldn't need the '$lib = new Library();' line then :)
I'm not sure why you'd need to do this, because one of the advantages of OOP is to encapsulate methods into namespaces safely and prevent collisions of function names.
However, if you absolutely need to do this (and I think you can and should refactor in a way to not have to do this), it can be done; you can add this to /path/to/library-class.php:
class Library {
public function num_one() { echo "number one"; }
public function num_two() { echo "number two"; }
}
$global_Library = new Library();
function num_one ($whateverParameter) {
global $global_Library;
return $global_Library->num_one($whateverParameter);
}
// Continue adding your wrapper functions here.
I'd still think that using static methods are better than what you're asking to do, even though they shouldn't be treated as a cure-all.
http://code.google.com/p/google-singleton-detector/wiki/WhySingletonsAreControversial

Global variable in PHP is not working

I need to access $layers from inside the function isOk($layer), but everything i tried the outside function variable $layers is ok, but inside the function, even with global is return null.
Here is the code:
$layers = array();
foreach($pcb['PcbFile'] as $file){
if(!empty($file['layer'])){
$layers[$file['layer']] = 'ok';
}
}
// Prints OK!
var_dump($layers);
function isOk($layer){
global $layers;
// Not OK! prints NULL
var_dump($layers);
if(array_key_exists($layer, $layers))
return ' ok';
return '';
}
// NOT OK
echo isOk('MD');
I always use Object orientation, but this was something so simple that i made with a simple function... Why $layers is not being 'received' correcly inside the function?
Watch this...
HalfAssedFramework.php
<?php
class HalfAssedFramework {
public static function run($path) {
include $path;
}
}
HalfAssedFramework::run('example.php');
example.php
<?php
$layers = array();
foreach($pcb['PcbFile'] as $file){
if(!empty($file['layer'])){
$layers[$file['layer']] = 'ok';
}
}
// Prints OK!
var_dump($layers);
function isOk($layer){
global $layers;
// Not OK! prints NULL
var_dump($layers);
if(array_key_exists($layer, $layers))
return ' ok';
return '';
}
// NOT OK
echo isOk('MD');
Run example.php directly, and it should work. Run HalfAssedFramework.php, and it won't.
The problem is scope. When example.php is included inside the run function, all the code inside it inherits the function's scope. In that scope, $layers isn't global by default.
To fix this, you have a couple of options:
If you know example.php will never run directly, you can say global $layers; at the beginning of the file. I'm not sure whether this will work if the script is run directly, though.
Replace $layers with $GLOBALS['layers'] everywhere.
Add $layers as an argument to isOk.
Put this code within a class, as suggested by Geoffrey.
Not exactly answering the question, but have you considered not using globals? Globals really aren't that cool: they make your code harder to read, harder to understand and as a consequence, harder to maintain.
Consider something like that:
<?php
class LayerCollection
{
private $layers;
public function __construct($layers)
{
$this->layers = $layers;
}
public static function fromPcbFile($data)
{
$layers = array();
foreach ($data['PcbFile'] as $layer) {
if (!empty($layer)) {
$layers[$layer] = true;
}
}
return new self($layers);
}
public function hasLayer($layer)
{
return array_key_exists($layer, $this->layers);
}
}
$layers = LayerCollection::fromPcbFile($pcb);
var_dump($layers->hasLayer('MD'));
Doesn't it look better? You can then proceed to enrich LayerCollection as you need more ways of interacting with your layers. This is not perfect, since there's still a static method lying around (makes testing harder, a factory would be better suited for that job), but that's a good start for a refactoring.
More about why globals are evil: https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil

Validity of php variables

It may sound silly but I'm quite php outdated/unexperienced and coming from Java programming back to php, so I mix up the concepts.
If in a php webpage I declare a variable
$debug=TRUE;
and try to access it from below within a function
a(){
if ($debug){
echo "I'm here";
}
}
the variable doesn't exists or isn't initiated? The whole file is just simply:
<?php
$debug=TRUE;
a(){
if ($debug){
echo "I'm here";
}
}
?>
Do I need to make a session variable or something else? I'm quite clueless & the same concept is confusing me for the use of other variables within. Also for the further use of variables, I am trying to be forced to pass all the variables I need forward to the function where I use them and a class concept as in Java perhaps would be cleaner but is a kind of too much for this simplicity. Or do I need the functions (it's a form processor) to be declared as a class?
I know this is silly, but I looked through Google and forums and the problem seems to be so obvious and simple that it's hard to find a webpage or entry targeting this (or perhaps I'm asking the wrong question).
http://php.net/manual/en/language.variables.scope.php
<?php
$debug = TRUE;
function a() {
global $debug;
if($debug === TRUE) {
echo "I'm here....\n"
}
}
Better, instead of using globals you can pass it in as a parameter:
<?php
$debug = TRUE;
function a($debug = TRUE) {
if($debug === TRUE) ....
}
You can also use the $_GLOBALS array:
<?php
$debug = TRUE;
function a() {
if($_GLOBALS['debug'] === TRUE) ...
}
You can use constants, which are always in scope:
<?php
define('DEBUG', TRUE);
function a() {
if(DEBUG === TRUE) ...
}
You can also use a singleton:
function a() {
if(SingletonClass::get_instance()->debug === TRUE) {
...
}
}
You'll have to create a singleton class which extends StdClass() to get implicit ->get and ->set methods.
http://www.talkphp.com/advanced-php-programming/1304-how-use-singleton-design-pattern.html
did you want something like this:
<?php
$debug=TRUE;
function a($debug){
if ($debug){
echo "I'm here";
}
}
a($debug);//outputs "I'm here"
?>
A few things here a(){} isn't defined as a function
function a(){
}
Next, you shouldn't try use globals unless you absolutely want them. But, you could
$debug = TRUE;
function a(){
global $debug;
if($debug)
{
echo "it is";
}
}
then call a() whenever you want to check it.
I must say I don't think this is a great practice in how you are trying to debug.
Pass variables to a function, like this:
$debug = true;
function a($debug) {
var_dump($debug);
}
a($debug);
// Outputs bool(true)

Categories