PHP function variables - php

I have a function called
chewbacca() {
include('external.php');
echo $lang[1];
...
}
The file external.php contains all the $lang array. However, since I have to execute the function thousands of times, I would like to include only once the file. If I include_once('external.php'); before the function, how can I use the $lang array variables in my function without having to write "global" before each use?

Maybe passing it as an argument?
<?php
include 'external.php';
function chewbacca($lang_array){
echo $lang_array[1];
//...
}
Edit:
You could do the following too:
On external.php:
<?php
return array(
'foo',
'foobar',
'bar',
);
On index.php:
<?php
function chewbacca($lang_array){
echo $lang_array[1];
//...
}
$foo = include 'external.php';
chewbacca($foo);
Edit2:
Of course now you can use include_once, but I would recommend require_once because you won't have the array if the include fails and the script should stop with an error.

Unless I'm misunderstanding what you're after, you don't need to write global before each use, you just have to use it at the start of the function.
include('external.php');
chewbacca() {
global $lang;
echo $lang[1];
...
}

Simply said, you can't...
You have several ways to do this:
Way #1
global $lang;
include('external.php')
function chewbacca(){
global $lang;
echo $lang[1];
}
Way #2
function chewbacca(){
include('external.php')
echo $lang[1];
}
Way #3
function chewbacca(){
static $lang;
if(!is_array($lang)){ include('external.php'); }
echo $lang[1];
}
Way #4
include('external.php')
function chewbacca($lang){
echo $lang[1];
}
chewbacca($lang);
Good luck
PS: Another way would be to use a CLASS a load the strings in the class when it gets created (inside the constructor) and access the language strings from $this->lang...

Static class also is a solution.
class AppConfiguration {
static $languages = array(
'en' => 'English'
);
}
function functionName($param) {
$lang = AppConfiguration::$languages;
}
require_once that class in document and that's it.

If I understood you correctly, try and pass it to a local scope before using it; that way you'll only need to use the global scope once inside the function.

Related

What is the best way to acces language variables in a function?

Basically, I've included my language file in my page, in that language file are arrays like $lang['ERROR']['TITLE'], so my question is: what is the best way to acces those variables in functions?
You could use one of two methods depending on what you want:
1) Declare a global variable:
<?php
$GLOBALS['lang'] = $lang;
function test () {
echo $GLOBALS['lang']['ERROR']['TITLE'];
}
test();
?>
This makes it able to be used inside any function.
2) Pass it to the function:
function test ($var) {
echo $var;
}
test ($lang['ERROR']['TITLE']);
This only allows for it inside the one specific function.
You can try something like this:
<?php
$lang = ...;
function test () {
global $lang;
echo $lang['ERROR']['TITLE'];
}
test();
?>
The global-keyword is needed, to tell php that it should look for this variable in the global-scope. Otherwise, $lang is undefined.
You need to use the global keyword at the top of your function to access a variable defined outside the function. Eg:
function test() {
global $lang;
echo $lang['ERROR']['TITLE'];
}

PHP - architecture, issue with variables scope

I'm writing now an app, which is supposed to be as simple as possible. My controllers implement the render($Layout) method which just does the following:
public function render($Layout) {
$this->Layout = $Layout;
include( ... .php)
}
I don't really understand the following problem: in my controller, I define a variable:
public function somethingAction() {
$someVariable = "something";
$this->render('someLayout');
}
in the php view file (same I have included in the render function) I try to echo the variable, but there is nothing. However, if I declare my action method like this:
public function somethingAction() {
global $someVariable;
$someVariable = "something";
$this->render('someLayout');
}
and in my view like this:
global $someVariable;
echo $someVariable;
it does work. Still it is annoying to write the word global each time.
How can I do this? I'd rather not use the $_GLOBAL arrays. In Cake PHP, for example, there is a method like $this->set('varName', $value). Then I can just access the variable in the view as $varName. How is it done?
From the PHP Manual on include:
When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.
When you do
public function somethingAction() {
$someVariable = "something";
$this->render('someLayout');
}
the $someVariable variable is limited to the somethingAction() scope. Calling your render() method will not magically make the variable available in render(), because the render() method has it's own variable scope. A possible solution would be to do
public function somethingAction() {
$this->render(
'someLayout',
array(
'someVariable' => 'something'
)
);
}
and then change render() to
public function render($Layout, array $viewData) {
$this->Layout = $Layout;
include( ... .php)
}
You will then have access to $viewData in the included file, given that you are not trying to use it in some other function or method, e.g. if your included file looks like this:
<h1><?php echo $viewData['someVariable']; ?></h1>
it will work, but if it is looks like this:
function foo() {
return $viewData['someVariable'];
}
echo foo();
it will not work, because foo() has it's own variable scope.
However, a controller's sole responsibility is to handle input. Rendering is the responsibility of the View. Thus, your controller should not have a render() method at all. Consider moving the method to your View class and then do
public function somethingAction() {
$view = new View('someLayout');
$view->setData('someVariable', 'something');
$view->render();
}
The render() method of your View object could then be implemented like this:
class View
…
$private $viewData = array();
public function setData($key, $value)
{
$this->viewData[$key] = $data;
}
public function render()
{
extract($this->viewData, EXTR_SKIP);
include sprintf('/path/to/layouts/%s.php', $this->layout);
}
The extract function will import the values of an array in the current scope using their keys as the name. This will allow you to use data in the viewData as $someVariable instead of $this->viewData['someVariable']. Make sure you understand the security implications of extract before using it though.
Note that this is just one possible alternative to your current way of doing things. You could also move out the View completely from the controller.
Using global you're implicitly using the $_GLOBALS array.
A not recommended example, because globals are never a good thing:
function something() {
global $var;
$var = 'data';
}
// now these lines are the same result:
echo $_GLOBALS['var'];
global $var; echo $var;
Why don't you use simply the $this->set function?
public function render($Layout) {
$this->Layout = $Layout;
include( ... .php)
}
public function somethingAction() {
$this->set('someVariable', "something");
$this->render('someLayout');
}
// in a framework's managed view:
echo $someVariable;
I'm sorry not to know your framework in detail, but that makes perfectly sense.
Actually how it's done: There is a native extract function, that loads an associative array into the current symbol table:
array( 'var0' => 'val0', 'var1' => 'val1')
becomes
echo $var0; // val0
echo $var1; // val1
That's most likely 'what happens'.

how can i include php file in php class

i have php with an array i.e
$var = array(
"var" => "var value",
"var2" => "var value1"
);
and have another file with a class i.e
class class1{
function fnc1(){
echo $var['var2'];
//rest of function here
}
}
now how can i get $var['var'] in class file in function fnc1()
You can pass it as an argument, or use the global keyword to put it in the current scope.
However, using global is discouraged, try passing it as an argument.
Pass it as an argument?
class class1{
function fnc1($var) {
echo $var['var2'];
}
}
And in your other file call this class method with your array as an argument.
From: http://php.net/manual/en/function.include.php
When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.
So you could do
class class1
{
function fnc1()
{
include 'thefile.php'
echo $var['var2'];
//rest of function here
}
}
but like others pointed out before, you dont want to do that, because it introduces a dependency on the filesystem in your class. If your method requires those variables to work, then inject them as method arguments or pass them into the constructor and make them a property (if you need them more often). This is called Dependency Injection and it will make your code much more maintainable in the long run, e.g. do
class class1
{
private $data;
public function __construct(array $var)
{
$this->data = $var;
}
function fnc1()
{
echo $this->data['var2'];
//rest of function here
}
}
and then do
$obj = new class1($var);
echo $obj->fnc1();
or require the data to be passed into the method on invocation
class class1
{
function fnc1(array $var)
{
echo $var['var2'];
//rest of function here
}
}
and then
$obj = new class1;
$obj->fnc1($var);
You might use global $var in your included file, but it's really a bad practice, as another script, before your included file, might redefine the value/type of $var.
Example :
class class1{
function fnc1(){
global $var;
echo $var['var2'];
//rest of function here
}
}
A better solution, is to pass your $var as a parameter to your fnc1(), even to your class1::__construct()
#Vindia: I'd prefer the argumant-style too, but would recommend either using type hint or a simple check to avoid warnings when accessing *non_array*['var2']:
// acccepts array only. Errors be handled outside
function fnc1(Array $var) {
echo $var['var2'];
}
// accepts any type:
function fnc1(Array $var) {
if (is_array($var)) {
echo $var['var2'];
}
}
class class1{
function fnc1(){
include 'otherFile.php';
echo $var['var2'];
//rest of function here
}
}

alias to include

i have alias to include() in my functions.php file:
function render_template($template)
{
include($template);
}
and simple template.html :
Hello, <?php echo $name ?>
But unfortunately, alias function gave me this output:
require 'functions.php';
$name = "world";
include('template.html'); // Hello, world
render_template('template.html'); // PHP Notice:Undefined variable: name
why is that? and how i can fix this?
thanks.
You have two more options to make it work around the scope issue. (Using global would require localising a long list of vars. Also it's not actually clear if your $name resides in the global scope anyway and always.)
First you could just turn your render_template() function into a name-resolver:
function template($t) {
return $t; // maybe add a directory later on
}
Using it like this:
$name = "world";
include(template('template.html'));
Which is nicer to read and has obvious syntactical meaning.
The more quirky alternative is capturing the local variables for render_template:
$name = "world";
render_template('template.html', get_defined_vars());
Where render_template would require this addition:
function render_template($template, $vars)
{
extract($vars); // in lieu of global $var1,$var2,$var3,...
include($template);
}
So that's more cumbersome than using a name-resolver.
The variable $name is not visible at the point where include is called (inside function render_template). One way to fix it would be:
function render_template($template)
{
global $name;
include($template);
}
Its a Scope Problem, you can set the variable to global, or encapsulate the whole thing a little bit more, for example like that:
class view{
private $_data;
public function __construct(){
$this->_data = new stdClass();
}
public function __get($name){
return $this->_data->{$name};
}
public function __set($name,$value){
$this->_data->{$name} = $value;
}
public function render($template){
$data = $this->_data;
include($template);
}
}
$view = new view;
$view->name = "world";
$view->render('template.html');
template.html :
Hello <?php print $data->name; ?>
If $name is in the global scope then you can get around it by declaring the variable global with the function. But a better solution would be to re-architect the code to require passing the relevant variable value into the function.
This is expected.
Look here.
You would be interested in the following quote, "If the include occurs inside a function within the calling file, then all of the code contained in the called file will behave as though it had been defined inside that function. So, it will follow the variable scope of that function. An exception to this rule are magic constants which are evaluated by the parser before the include occurs".

create superglobal variables in php?

is there a way to create my own custom superglobal variables like $_POST and $_GET?
Static class variables can be referenced globally, e.g.:
class myGlobals {
static $myVariable;
}
function a() {
print myGlobals::$myVariable;
}
Yes, it is possible, but not with the so-called "core" PHP functionalities. You have to install an extension called runkit7:
Installation
After that, you can set your custom superglobals in php.ini as documented here:
ini.runkit.superglobal
I think you already have it - every variable you create in global space can be accessed using the $GLOBALS superglobal like this:
// in global space
$myVar = "hello";
// inside a function
function foo() {
echo $GLOBALS['myVar'];
}
Class Registry {
private $vars = array();
public function __set($index, $value){$this->vars[$index] = $value;}
public function __get($index){return $this->vars[$index];}
}
$registry = new Registry;
function _REGISTRY(){
global $registry;
return $registry;
}
_REGISTRY()->sampleArray=array(1,2,'red','white');
//_REGISTRY()->someOtherClassName = new className;
//_REGISTRY()->someOtherClassName->dosomething();
class sampleClass {
public function sampleMethod(){
print_r(_REGISTRY()->sampleArray); echo '<br/>';
_REGISTRY()->sampleVar='value';
echo _REGISTRY()->sampleVar.'<br/>';
}
}
$whatever = new sampleClass;
$whatever->sampleMethod();
One other way to get around this issue is to use a static class method or variable.
For example:
class myGlobals {
public static $myVariable;
}
Then, in your functions you can simply refer to your global variable like this:
function Test()
{
echo myGlobals::$myVariable;
}
Not as clean as some other languages, but at least you don't have to keep declaring it global all the time.
No
There are only built-in superglobals listed in this manual
Not really. though you can just abuse the ones that are there if you don't mind the ugliness of it.
You can also use the Environment variables of the server, and access these in PHP
This is a good way to maybe store global database access if you own and exclusively use the server.
possible workaround with $GLOBALS:
file.php:
$GLOBALS['xyz'] = "hello";
any_included_file.php:
echo $GLOBALS['xyz'];
One solution is to create your superglobal variable in a separate php file and then auto load that file with every php call using the auto_prepend_file directive.
something like this should work after restarting your php server (your ini file location might be different):
/usr/local/etc/php/conf.d/load-my-custom-superglobals.ini
auto_prepend_file=/var/www/html/superglobals.php
/var/www/html/superglobals.php
<?php
$_GLOBALS['_MY_SUPER_GLOBAL'] = 'example';
/var/www/html/index.php
<?php
echo $_MY_SUPER_GLOBAL;
Actually, there is no direct way to define your own superglobal variables; But it's a trick that I always do to access simpler to my useful variables!
class _ {
public static $VAR1;
public static $VAR2;
public static $VAR3;
}
Then I want to use:
function Test() {
echo \_::$VAR2;
}
Notice: Don't forget to use \ before, If you want to use it everywhere you have a namespace too...
Enjoy...

Categories