Validity of php variables - php

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)

Related

Cannot access global variable from within class constructor

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.

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

Is it possible in PHP to call a variable as function? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use a variable to define a PHP function
Use Variable as Function Name in PHP
I want to perform a conditional function call but I don't necessarily know what what the function will be, so that would be a long switch.
For example;
$userSelection = "calculator"; /* or "stocks" or whatever widget */
$widget->get_widget($userSelection);
public function __construct($userSelection){
/* pseudo code */
call function $userSelection();
}
public function calculator(){
/* Get Calculator */
}
Sure there is. This feature is called variable functions:
$functionName = "strlen";
$length = $$functionName("Hello world!");
The $$var(...) syntax is convenient, but it will only work with free functions. If you want to call a class method this way, you will need to use call_user_func or call_user_func_array (these functions can also handle the "free function" case).
Look at the call-user-func function. This allows you to call another function, e.g.
call_user_func('calculator')
call_user_func($userSelection);
http://php.net/manual/en/function.call-user-func.php
Take a look at this php functions:
call_user_func(): http://php.net/manual/de/function.call-user-func.php
call_user_func_array(): http://www.php.net/manual/de/function.call-user-func-array.php
create_function(): http://www.php.net/manual/de/function.create-function.php
There is also a direct (though ugly) execution syntax:
function some_func(args) {...}
$function_name='some_func';
$$function_name(args2);
You can use call_user_func() for that, like this:
$userSelection = "calculator";
call_user_func($userSelection[, $param1, $param2, ...]);
call_user_func_array($userSelection, $params);
If it's just a function you're after then using this should solve your problems
$function = "echo";
$$function "fooBar";
If it's a class method that you want to keep flexible use magic method __call() which will allow you to use method names that are not pre-defined.
__call() is triggered when invoking inaccessible methods in an object context.
i.e.
class Foo {
public function __call($name, $arguments) {
echo $name;
}
}
$foo = new Foo();
$foo->bar(); // will echo "bar"
PHP built-in function 'eval' can do everything, but beware of injection.
$var = "somefunction";
eval("$var();");
http://php.net/manual/en/function.eval.php
It's pretty simple if that's what you mean.
function calculator() {
echo 'foo';
}
$userSelection = "calculator";
if (function_exists($userSelection)) {
$userSelection();
}
Or within a class like in your example:
class widget {
public function __construct($userSelection) {
echo 'constructed widget<br>';
if (function_exists($userSelection)) {
$this->$userSelection();
}
}
public function calculator() {
echo 'bar';
}
}
$userSelection = "calculator";
$widget = new widget($userSelection);
Or from outside a class when the function is part of the class.
class widget {
public function calculator() {
echo 'bar';
}
}
$widget = new widget();
$userSelection = "calculator";
$widget->$userSelection();
I would work with if/else statements though to determine the function to be called just to be sure that only valid functions are executed (do you sanitize the user selection or do you just get it from a $_POST? The latter would be a very bad idea).
You can do following :
$var = 'abc';
switch ($var) {
case 'abc':
$result = $var('test param');
echo $result;
break;
default :
echo 'default';
break;
}
function abc($data) {
return $data;
}

PHP add methods to Functions

Is it possible to add methods to functions?
For example:
<?
function func(){
;
}
//add method
func->test = function(){
;
}
func->test();
func();
I'm coming from a javascript background, and therefore I'm used to 'everything is an object'.
EDIT:
I was just explaining where the misconception may often come from for new phpers. I understand the above code doesn't work.
EDIT 2
Figured it out.
class myfunc_class{
function __invoke(){
//function body
}
function __call($closure, $args)
{
call_user_func_array($this->$closure, $args);
}
}
$func = new myfunc_class;
$func->test = function(){
echo '<br>test<br>';
};
$func->test();
$func();
Even sexier :)
class func{
public $_function;
function __invoke(){
return call_user_func_array($this->_function,func_get_args());
}
function __construct($fun){
$this->_function = $fun;
}
function __call($closure, $args)
{
call_user_func_array($this->$closure, $args);
}
}
$func = new func(function($value){
echo $value;
});
$func->method = function(){
echo '<br>test<br>';
};
$func('someValue');
$func->method();
No.
Not everything is an object in PHP. In fact the only thing that is an object is, well, an object. More specifically, and generally, an instantiation of a class.
Your code converted to PHP
// function_object.php
<?php
class FunctionObject {
public method func() {
// do stuff
}
}
?>
In other code you would use it like this:
<?php
// example.php in same folder as function_object.php
include 'function_object.php';
$FuncObj = new FunctionObject;
$FuncObj->func();
Also: read more about PHP & OOP
No, because an object is a different PHP language construct than a function. Functions do not have properties, but are instead simply execution instructions.
But, if func were instead a pre-defined class, then yes... with a bit of witchcraft, ignoring public outcry, foregoing readability and PHP coding standards, and by using closures with the __call() magic method...
class func
{
function __call($func, $args)
{
return call_user_func_array($this->$func, $args);
}
}
$obj = new func;
$obj->test = function($param1, $param2)
{
return $param1 + $param2;
};
echo $obj->test(1,1);
This won't work as you'd think without __call(), because by $obj->test(1,1), PHP thinks you're trying to call a non-existent method of func when out of object scope. But inside, being that the new "test" property is of a type: closure, the call_user_func_array() just sees the "test" property as just another function, so you can hide this bit of trickery from outside scope.
You would need your function func() to return an object, then you'd be able to do something like: func()->test();
But please note that your way of handling objects is not right in PHP and I suggest that you go read the OO documentations here.
In difference to javacript, in PHP not everything is an object. Therefore you need to differ between function and class.
If you want to create an object, you need to define the class first.
class myClass {
}
You can then add as many functions to the class as you need. But you need to define them first:
class myClass {
function test() {
echo "test!\n";
}
}
When everything is ready, you can bring it to life then:
$class = new myClass;
$class->test();
Checkout the manual for more.
You can't do what you're trying to do, but you can define functions inside of other functions.
This example outputs text:
function a() {
function b() { echo 'Hi'; }
}
a();
b();
Output: HiHi
This example outputs an error:
function a() {
function b() { echo 'Hi'; }
}
b();
Output: ERROR

Lazy Function Definition in PHP - is it possible?

In JavaScript, you can use Lazy Function Definitions to optimize the 2nd - Nth call to a function by performing the expensive one-time operations only on the first call to the function.
I'd like to do the same sort of thing in PHP 5, but redefining a function is not allowed, nor is overloading a function.
Effectively what I'd like to do is like the following, only optimized so the 2nd - Nth calls (say 25-100) don't need to re-check if they are the first call.
$called = false;
function foo($param_1){
global $called;
if($called == false){
doExpensiveStuff($param_1);
$called = true;
}
echo '<b>'.$param_1.'</b>';
}
PS I've thought about using an include_once() or require_once() as the first line in the function to execute the external code just once, but I've heard that these too are expensive.
Any Ideas? or is there a better way to tackle this?
Use a local static var:
function foo() {
static $called = false;
if ($called == false) {
$called = true;
expensive_stuff();
}
}
Avoid using a global for this. It clutters the global namespace and makes the function less encapsulated. If other places besides the innards of the function need to know if it's been called, then it'd be worth it to put this function inside a class like Alan Storm indicated.
Have you actually profiled this code? I'm doubtful that an extra boolean test is going to have any measurable impact on page rendering time.
you can do conditional function definiton.
if( !function_exists('baz') )
{
function baz( $args ){
echo $args;
}
}
But at present, a function becomes a brick when defined.
You can use create_function, but I would suggest you DONT because it is slow, uses lots of memory, doesn't get free()'d untill php exits, and is a security hole as big as eval().
Wait till PHP5.3, where we have "closures" http://wiki.php.net/rfc/closures
Then you'll be permitted to do
if( !isset( $baz ) )
{
$baz = function( $args )
{
echo $args;
}
}
$baz('hello');
$baz = function( $args )
{
echo $args + "world";
}
$baz('hello');
Upon further reading, this is the effect you want.
$fname = 'f_first';
function f_first( $even )
{
global $fname;
doExpensiveStuff();
$fname = 'f_others';
$fname( $even );
/* code */
}
function f_others( $odd )
{
print "<b>".$odd."</b>";
}
foreach( $blah as $i=>$v )
{
$fname($v);
}
It'll do what you want, but the call might be a bit more expensive than a normal function call.
In PHP5.3 This should be valid too:
$func = function( $x ) use ( $func )
{
doexpensive();
$func = function( $y )
{
print "<b>".$y."</b>";
}
$func($x);
}
foreach( range(1..200) as $i=>$v )
{
$func( $v );
}
( Personally, I think of course that all these neat tricks are going to be epically slower than your earlier comparison of 2 positive bits. ;) )
If you're really concerned about getting the best speed everywhere
$data = // some array structure
doslowthing();
foreach( $data as $i => $v )
{
// code here
}
You may not be able to do that however, but you've not given enough scope to clarify. If you can do that however, then well, simple answers are often the best :)
Please don't use include() or include_once(), unless you don't care if the include() fails. If you're including code, then you care. Always use require_once().
If you do wind up finding that an extra boolean test is going to be too expensive, you can set a variable to the name of a function and call it:
$func = "foo";
function foo()
{
global $func;
$func = "bar";
echo "expensive stuff";
};
function bar()
{
echo "do nothing, i guess";
};
for($i=0; $i<5; $i++)
{
$func();
}
Give that a shot
PHP doesn't have lexical scope, so you can't do what you want with a function. However, PHP has classes, which conceptually works in exactly the same way for this purpose.
In javascript, you would do:
var cache = null;
function doStuff() {
if (cache == null) {
cache = doExpensiveStuff();
}
return cache;
}
With classes (In PHP), you would do:
class StuffDoer {
function doStuff() {
if ($this->cache == null) {
$this->cache = $this->doExpensiveStuff();
}
return $this->cache;
}
}
Yes, class-based oop is more verbose than functional programming, but performance-wise they should be about similar.
All that aside, PHP 5.3 will probably get lexical scope/closure support, so when that comes out you can write in a more fluent functional-programming style. See the PHP rfc-wiki for a detailed description of this feature.
How about using local static variables?
function doStuff($param1) {
static $called = false;
if (!$called) {
doExpensiveStuff($param1);
$called = true;
}
// do the rest
}
If you need to do expensive stuff only once for given parameter value, you could use an array buffer:
function doStuff($param1) {
static $buffer = array();
if (!array_key_exists($param1, $buffer)) {
doExpensiveStuff($param1);
$buffer[$param1] = true;
}
// do the rest
}
Local static variables are persistent across function calls. They remember the value after return.
Any reason you're commited to a functional style pattern? Despite having anonymous functions and plans for closure, PHP really isn't a functional language. It seems like a class and object would be the better solution here.
Class SomeClass{
protected $whatever_called;
function __construct(){
$this->called = false;
}
public function whatever(){
if(!$this->whatever_called){
//expensive stuff
$this->whatever_called = true;
}
//rest of the function
}
}
If you wanted to get fancy you could use the magic methods to avoid having to predefine the called booleans. If you don't want to instantiate an object, go static.

Categories