Can PHP namespaces contain variables? - php

Can PHP namespaces contain variables? If so, how can this be accomplished?

No. You can set a variable after declaring a namespace, but variables will always exist in the global scope. They are never bound to namespaces. You can deduce that from the absence of any name resolution descriptions in
FAQ: things you need to know about namespaces (PHP 5 >= 5.3.0)
There would also be no allowed syntax to locate variables in a namespace.
print \namespace\$var; // syntax error
print "${namespace\\var}"; // "unexpected T_NS_SEPARATOR"

Try this
<?php
namespace App\login;
$p = 'login';
$test2 = '\App\\'.$p.'\\MyClass';
$test = new $test2;

No they cannot, as mario said.
To encapsulate variables use Classes. Polluting the global variable space should definitely be avoided.
Example
class_dbworker.php:
class DbWorker
{
//properties and method logic
}
class DbWorkerData
{
public static $hugerelationsmap = array(....);
public static ....
}
mainapp.php:
include_once 'class_dbworker.php';
print_r( DbWorkerData::$hugerelationsmap );
Example using namespaces
class_dbworker.php:
namespace staticdata;
class DbWorker
{
//properties and method logic
}
class DbWorkerData
{
public static $hugerelationsmap = array(....);
public static ....
}
mainapp.php:
include_once 'class_dbworker.php';
use staticdata as data;
print_r( \data\DbWorkerData::$hugerelationsmap );

It is not possible because $MYVARNAME is still in the global scope. Try following code.
namespace.php
<?php
namespace MYNAME;
use MYNAME as M;
const MYVAR = 'MYVARNAME';
${M\MYVAR} = date('Y');
echo $MYVARNAME; // PRINT YEAR
$MYVARNAME = 'X';
echo $MYVARNAME; // PRINT X
echo ${M\MYVAR} ; // PRINT X
include('file.php');
?>
file.php
<?php
${MYNAME\MYVAR}=date('Y');
echo $MYVARNAME; // PRINT YEAR
$MYVARNAME = 'X';
echo $MYVARNAME; // PRINT X
echo ${MYNAME\MYVAR}; // PRINT X
include('file2.php');
?>
file2.php
<?php
namespace MYNAME2;
use MYNAME2 as N;
const MYVAR = 'MYVARNAME';
${N\MYVAR} = 'Y';
echo $MYVARNAME; // PRINT Y
echo ${MYNAME\MYVAR}; /* PRINT Fatal error: Uncaught Error:
Undefined constant 'MYNAME2\MYNAME\MYVAR' */
?>

You can bound a variable to the namespace by wrapping the variable inside a function.
<?php
namespace furniture;
// instead of declaring a $version global variable, wrap it inside a function
function version(){
return "1.3.4";
}
?>

It can be done - sort of.
This is probably extremely bad and should never be done, but it is possible by using variable variables, and the magic constant for namespace.
So a string-variable to name the variable we want to use, like so:
<?php
namespace your\namespace;
$varname = __NAMESPACE__.'\your_variablename'; //__NAMESPACE__ is a magic constant
$namespaced_variable = $$varname; //Note the double dollar, a variable variable
?>

Store Complete classPath in Variable and use after 'new'.
It is very important to realize that because the backslash is used as an escape character within strings, it should always be doubled when used inside a string.
<?php
$a = "namespace\\className"; // 'which will print namespace/className'
$obj = new $a;
?>

Alternate ways that can make code more organized:
Instead of like \view\header\$links:
(1) Backslashes in array key for imaginary nesting,
Example:
$myVar['view\header\links'] = 'value';
// OR use multidimentional arrays
$view['header']['links'] = 'value';
(1.1) Use Global Array, Example
// START - SETUP
define('I', 'mySite_19582730');
// END - SETUP
// Usage:
$GLOBALS[I]['view\header\links'] = 'value';
// OR
$GLOBALS[I]['view__header__links'] = 'value';
(1.1.1) Functions to get & set value in Global Array
function set($key, $val){
if (is_string($key)) $GLOBALS['site_8619403725'][$key] = $val;
elseif (is_array($key)){
foreach($key as $ky => &$vl) {
$GLOBALS['mySite_19582730'][$vl] = $val;
}
}
}
function get($key){
return # $GLOBALS['mySite_19582730'][$key];
}
// Usage
set('view\header\search','<div></div>');
set(['view\header\logo','view\header\homeLink'], '');
get('view\header\search');
(2) Use __ (double underscores) in variable name to make imaginary nesting,
Example:
$view__header__links = 'value';

Related

Use variable as namespace

In some other file (someusername\classes\MyClass for instance), I have
<?php
namespace someusername;
class MyClass
{
static function Test()
{
echo "working";
}
}
?>
I have stumbled across an annoying little barrier:
<?php
$user = "someusername";
$class = "MyClass";
require_once "$user\\classes\\$class";
//This line should be the equivalent of 'use someusername as User;'
use $user as User; //Parse Error: syntax error, unexpected '$user'
$c = "User\\$class";
$UserSpecificClass = new $c();
?>
I can get around it via the following, but the use statement would make things a lot nicer
<?php
$user = "someusername";
$class = "MyClass";
require_once "$user\\classes\\$class";
$c = "$user\\$class";
$UserSpecificClass = new $c();
?>
Is it possible to use variables in use statement in PHP? Or is it better to avoid the use statement with this approach?
Importing is performed at compile-time.
Assigning the variable is done at run-time after compilation, at which point any import should already be imported.
So this is not possible. Best solution would indeed be to use the FQN in a string and initialize that.
$c = "$user\\$class";
$UserSpecificClass = new $c();

Can non-anonymous functions in PHP using 'use' keyword?

Can non-anonymous functions in PHP using 'use' keyword? Or it is available for anonymous functions only.
Can I write a php file like this
// L.php
// assume $_texts is in this context..
$_language = null;
function L_init($language) use (&$_language)
{
$_language = $language;
}
function L($key) use ($_texts, $_language)
{
$_texts[$_language][$key];
}
So, another file can use it like this
// client.php
require_once 'L.php';
L_init('en');
echo L('GREETING'); // Will output localize string of key 'GREETING'
It is available for anonymous functions, but you can assign it to a variable:
$some_external_var = "World!";
$function = function() use($some_external_var){
echo "Hello ".$some_external_var;
};
Finally you can invoke it with:
call_user_func($function);
or just:
$function();
No you can't.
The code generate syntax errors.

Using a function to initialise a variable if it not set - PHP

Upon executing a script, sometimes the variable will be set, and sometimes it won't. The times that it isn't, I'm given a notice that the variable is not defined.
In efforts to clear the notice, I simple added the following code
if(!isset($var)) {
$var = NULL;
}
That works just as needed because it tests if the variable isn't already set so that we don't set something that we need to NULL. But in a file where there are over 60 variables that are of this case and more to come, I thought creating a simple function to do so would be easier. So I started with this:
function init($var) {
if(!isset($var)) {
return $var = NULL;
}
}
Obviously that doesn't work and is also riddled with errors that will annoy most programmers out there (such as the !isset() inside a function, not supplying a return statement in case the if statement is false, etc.) but that's just to give you the basic jist of what I need so in the code I can just call init($var); to test if the variable isn't already set, and then creates one and sets it to NULL to avoid the notice.
Is this even possible? To use a function to test if a variable is already set outside of the function? Thanks in advance :)
You can't use a function to check if a variable exists without it being initialized in the process of passing it to the function as an argument. You can, however, define an array of variable names your script requires then loop through them and check if they exist one by one. Such as:
foreach(array('username','userid','userrole','posts','dob','friends') as $var)
{
if(!isset($$var))$$var=NULL;
}
Edit: Simplifying user4035's approach, you could get the function down to:
<?php
function init(&$var){}
init($myVariable);
var_dump($myVariable);
Or even avoid a function altogether:
<?php
array(&$var1,&$var2,&$var3);//define several variables in one shot as NULL if not already defined.
var_dump($var1);
var_dump($var2);
var_dump($var3);
Another approach would be to use extract:
<?php
$defaults=array('username'=>NULL,'userid'=>0,'userrole'=>'guest','posts'=>0,'dob'=>0,'friends'=>array());
$userid=24334;
$username='bob';
$friends=array(2,5,7);
extract($defaults, EXTR_SKIP);
echo '<pre>';
print_r(
array(
'userid'=>$userid,
'username'=>$username,
'friends'=>$friends,
'userrole'=>$userrole,
'posts'=>$posts,
'dob'=>$dob)
);
echo '</pre>';
Another approach would be to temporarily disable error reporting:
<?php
$v=ini_get("error_reporting");
error_reporting(0);
echo 'One';
echo $doh;//Use an undefined variable
echo ' Two';
error_reporting($v);
I'd advise against this approach though because it is just hiding the errors rather than fixing them and will also hide errors worthy of your attention.
And my personal favorite would be to take advantage of namespaces.
Usually you'd put these into separate files but I put them into a single snippet for your convenience:
<?php
namespace //This is the global namespace
{
$config=array('production'=>0);
}
namespace MyScript
{
//Initialize all variables for our script
//anything not defined here will be inherited from the global namespace
$username=NULL;
$userid=NULL;
$userrole=NULL;
$posts=NULL;
$dob=NULL;
$friends=NULL;
}
namespace MyScript\Main
{
//Define only two variables for our script
//Everything else will be inherited from the parent namespace if not defined
$username='Ultimater';
$userid=4;
echo '<pre>';
print_r(
array(
'userid'=>$userid,
'username'=>$username,
'friends'=>$friends,
'userrole'=>$userrole,
'posts'=>$posts,
'dob'=>$dob,
'config'=>$config)
);
echo '</pre>';
}
If your intention is this:
if(variable is not set)
set variable to NULL
then it's quite easy to implement, using a reference:
function init(&$var) {
if(!isset($var)) {
$var = NULL;
}
}
Testing:
<?php
error_reporting(E_ALL);
function init(&$var) {
if(!isset($var)) {
$var = NULL;
}
}
init($x);
var_dump($x);
Output:
NULL

PHP: newbie question - something like with/end with in php?

is there something like with/end with (like in asp) for php?
especially for class objects it would be nice - asp syntax is like:
with myWeb
.init "myweb"
response.write .html
end with
thanks
No, there is no such thing in PHP : you have to write the full name of classes / objects / variables / whatever when you want to use them.
No, AFAIK.
Do you really find this syntax useful ?
No, but there is an alternative syntax for control structures that may interest you.
not sure im right but tryed my best to translate your example :/
<?php function write_block(){
echo '.html';
}
die(write_block());
?>
It's not exactly what you wanted, but you can do something similar with PHP references:
<?php
class A {
public $bar1 = 1;
public $bar2 = 2;
public $bar3 = 3;
}
class B {
public $foo;
}
class C {
public $foobar;
}
$myC = new C;
$myC->foobar = new B;
$myC->foobar->foo = new A;
print $myC->foobar->foo->bar1;
print $myC->foobar->foo->bar2;
print $myC->foobar->foo->bar3;
//Simpler with 'With...End With syntax:
//which might look something like:
//
// with ($myC->foobar->foo) //Note this is not valid PHP
// {
// print ->bar1; //Note this is not valid PHP
// print ->bar2; //Note this is not valid PHP
// print ->bar3; //Note this is not valid PHP
// }
//
//Fortunately, you can sort of do this using an object reference:
//
$obj =& $myC->foobar->foo;
print $obj->bar1;
print $obj->bar2;
print $obj->bar3;
unset ($obj);
?>

run function block in context of global namespace in PHP

So the senario is that I want to have a custom function for requiring libraries. Something like:
define('E_ROOT', str_replace('//','/',dirname(__FILE__)));
/* ... */
function e_load($fn, $allowReloading = FALSE) {
$inc = E_ROOT.'/path/here/'.$fn.'.php';
if($allowReloading)
require $inc; // !!!
else
require_once $inc; // !!!
}
The problem being that require and require_once will load the files into the namespace of the function, which doesn't help for libraries of functions, classes, et cetera. So is there a way to do this?
(Something avoiding require and require_once altogether is fine, as long as it doesn't use eval since it's banned on so many hosts.)
Thanks!
Technically include() is meant to act as though you're inserting the text of included script at that point in your PHP. Thus:
includeMe.php:
<?php
$test = "Hello, World!";
?>
includeIt.php:
<?php
include('includeMe.php');
echo $test;
?>
Should be the exact same as:
<?php
/* INSERTED FROM includeMe.php */
$test = "Hello, World!";
/* END INSERTED PORTION */
echo $test;
?>
Realizing this, the idea of making a function for dynamically including files makes about as much sense (and is about as easy to do) as having dynamic code all-together. It's possible, but it will involve a lot of meta-variables.
I'd look into Variable Variables in PHP as well as the get_defined_vars function for bringing variables into the global scope. This could be done with something like:
<?php
define('E_ROOT', str_replace('//','/',dirname(__FILE__)));
/* ... */
function e_load($fn, $allowReloading = FALSE) {
$prev_defined_vars = get_defined_vars();
$inc = E_ROOT.'/path/here/'.$fn.'.php';
if($allowReloading)
require $inc; // !!!
else
require_once $inc; // !!!
$now_defined_vars = get_defined_vars();
$new_vars = array_diff($now_defined_vars, $prev_defined_vars);
for($i = 0; $i < count($new_vars); $i++){
// Pull new variables into the global scope
global $$newvars[$i];
}
}
?>
It may be more convenient to just use require() and require_once() in place of e_load()
Note that functions and constants should always be in the global scope, so no matter where they are defined they should be callable from anywhere in your code.
The one exception to this is functions defined within a class. These are only callable within the namespace of the class.
EDIT:
I just tested this myself. Functions are declared in the global scope. I ran the following code:
<?php
function test(){
function test2(){
echo "Test2 was called!";
}
}
//test2(); <-- failed
test();
test2(); // <-- succeeded this time
?>
So the function was only defined after test() had been run, but the function was then callable from outside of test(). Therefore the only thing you should need to pull into the global scope are your variables, via the script I provided earlier.
require_once E_ROOT.$libName.'.php';
KISS
Instead of doing this...
$test = "Hello, World!";
... you could consider doing this ...
$GLOBALS[ 'test' ] = "Hello, World!";
Which is safe and consistent in both local function context, and global include context. Probably not harmful to visually remind the reader that you are expecting $test to become global. If you have a large number of globals being dragged in by your libraries maybe there's justification for wrapping it in a class (then you have the benefit of spl_autoload_register which kind of does what you are doing anyhow).

Categories