Global variable from included file in static function - php

I have index.php with included file strings.php for translating phrases. In strings.php is included file based on user language: $lang.php. This $lang.php file is automatically generated from $lang.ini and contains single array:
<?php $translation = array (
'USER_PROFILE' => 'Uživatelský profil',
'MESSAGES' => 'Zprávy',
'NOTIFICATIONS' => 'Oznámení',
'SETTINGS' => 'Nastavení',
...
There is a class Strings with static function and globally assigned array $translation from $lang.php in strings.php:
include_once('cache/'.$lang.'.php');
class Strings {
static public function translate($string) {
global $translation;
...
}
}
But $translation in translate() function returns null in this case. If I include $lang.php in index.php it suddenly works, but if I call Strings::translate() function in other file, $translation again returns null. I don't understand this behavior. (Sorry for english)

Because the way the file $lang.php is included, the variable $translation lands as a local variable in a function and not as a global variable as method Strings::translate() expects it.
After we discussed in chat and I understood the problem, I can suggest two solutions:
Solution 1 (the quick workaround)
Change file $lang.php:
<?php global $translation = array (
'USER_PROFILE' => 'Uživatelský profil',
...
This way the variable $translation is created in the global context and everything works as expected.
Solution 2 (a better design)
Limit the scope of the variable $translation.
File $lang.php:
<?php return array (
'USER_PROFILE' => 'Uživatelský profil',
...
This way no variable is create (neither local nor global) and this removes the source of confusion.
File strings.php:
class Strings {
static $translation;
static private function initialize() {
global $lang;
static::$translation = include_once('cache/'.$lang.'.php');
}
static public function translate($string) {
if (! isset(static::$translation)) {
static::initialize();
}
// use static::$translation instead of global $translation
}
}
Solution 3 (the correct design)
An even better design (the correct one, in fact) is to make method initialize() public, change $lang as its parameter and call it from your code as soon as you determined the value of $lang.
File strings.php:
class Strings {
static $translation;
// Call this method once, as soon as you determined what
// language you need to use
static public function initialize($lang) {
static::$translation = include_once('cache/'.$lang.'.php');
}
static public function translate($string) {
// use static::$translation instead of global $translation
}
}

Related

Cannot Access Global Variable inside function INSIDE public function PHP

Good day. I'm trying to execute a function. i declare a global variable to get data (variable) outside the function, and the function i put inside a public function of a Class.
class Test {
public function execute(){
$data = "Apple";
function sayHello() {
global $data;
echo "DATA => ". $data;
}
sayHello();
}
}
$test = new Test;
$test->execute();
The expected result:
DATA => Apple
The real result:
DATA =>
the global variable is not getting the variable outside the function. Why it happened? Thank you for the help.
$data is not a global variable. It's inside another function, inside a class. A global variable sits outside any function or class.
But anyway your use case is unusual - there's rarely a need to nest functions like you've done. A more conventional, logical and usable implementation of these functions would potentially look like this:
class Test {
public function execute(){
$data = "Apple";
$this->sayHello($data);
}
private function sayHello($data) {
echo "DATA => ". $data;
}
}
$test = new Test;
$test->execute();
Working demo: http://sandbox.onlinephpfunctions.com/code/e91b98bb15fcfa71b1c6cbbc305b5a93df678e8b
(This is just one option, but it's a reasonable one, although since this is clearly a reduced, abstract example, it's hard to be sure what your real scenario would actually require or be best served by.)

Call a session inside a function with object oriented php

I'm new to oop and some lines of my code are only approximate, to indicate what I want to achieve.
I want to create a session with php within a function within a class and call it in another function.
class My_beautiful_class
{
public function index()
{
$_SESSION['ciao'] = 'ciao';
var_dump($_SESSION);
}
public function anotherfunction()
{
$this->index();
var_dump($_SESSION);
}
}
I just want to understand a concept: in this way, my code will work but, on the other end, it will execute everything it will find in my function index, in my other function anotherfunction. So, if I call two variable with the same name, I could have a problem.
I guess that in theory, I could handle the problem in another way which is that I could create a variable call sessionone for example and send it some values in with my index function:
class My_beautiful_class
{
public sessionone = [];
public function index()
{
$_SESSION['ciao'] = 'ciao';
$this->sessionone = $_SESSION['ciao'];
}
public function anotherfunction()
{
$this->sessionone;
var_dump($_SESSION);
}
}
, but I was wondering if there any way to for example call only one variable that lives in one function with my first approach.
Something like: (My code is wrong on purpose, it is only to indicate what I want to achieve)
public function index()
{
$_SESSION['ciao'] = 'ciao';
}
public function anotherfunction()
{
$this->index( $_SESSION['ciao'] );
}
}
The $_SESSION variable are what is called a Superglobal in PHP: http://php.net/manual/en/language.variables.superglobals.php This gives them a few unique traits.
First, Superglobals are accessible anywhere in your application regardless of scope. Setting the value of a superglobal key in one function will make the value accessible anywhere else in your application that you want to reference it.
Say for example we want to make a class to manage our session. That class may look something like this.
class SessionManager
{
public function __construct()
{
session_start(); //We must start the session before using it.
}
//This will set a value in the session.
public function setValue($key, $value)
{
$_SESSION[$key] = $value;
}
//This will return a value from the session
public function getValue($key)
{
return $_SESSION[$key];
}
public function printValue($key)
{
print($_SESSION[$key]);
}
}
Once we have a class to manage it a few things happen. We can use this new class to add info to the session and also to retrieve it.
Consider the following code:
$session = new SessionManager();
$session->setValue('Car', 'Honda');
echo $session->getValue('Car'); // This prints the word "Honda" to the screen.
echo $_SESSION['Car']; //This also prints the word "Honda" to the screen.
$session->printValue('Car'); //Again, "Honda" is printed to the screen.
Because of a session being a superglobal, once you set a value on the session it will be assessable anywhere in your application, either in or outside of the class itself.
You must call session_start() at the beginning of your class.
You can also start the session at the beginning of your code if you include your class like this sample
Remember that you can call the session_start only one time

How to define/declare a variable in a class such that its accessible in another files in PHP?

I need a variable which remains accessible across all the PHP files am using, i.e, I should be able to read it and change its value.
I tried to declare a class in a file with variable x:
In file1.php
public class sample{
public static $curruser = '0';
public function getValue() {
return self::$curruser;
}
public function setValue($val){
self::$curruser = $val;
}
}
Its being set in file2.php by calling sample::setValue($val). This page has a redirect to file3.php
I need to access this variable file3.php:
include 'file1.php';
print sample::getValue();
This gives me 0 instead of the value I set in file2.php.
Clearly, my understanding of static variables in PHP is a little shaky. Is there a proper way to do set and access the variable across files?
Try to use session or some sort of caching mechanism if you want data to persist between requests.
i recommend defining a constant like this:
define('CONSTANT_NAME' ,$value);
and access the value like this:
echo CONSTANT_NAME;
or using static function and static values and static functions like this:
public static function setValue($val){
self::$curruser = $val;
}
public static function getValue() {
return self::$curruser;
}

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'.

Passing variables to an included file

I have a template class which goes like this:
class Template{
public $pageTitle = "";
public function __construct($pageTitle){
$this->pageTitle = $pageTitle;
}
public function display(){
include "/includes/head.php";
include "/includes/body.php";
}
}
Now, I'm used to Java's workings but I don't understand why I'm getting an undefined variable ($pageTitle) error. The included files need to be able to access that variable. I know it's going to be very simple but I actually haven't found out why.
What do I need to do to allow includes to see this variable?
The includes will also have to use $this->pageTitle. Effectively, the include makes them part of the method body.
The included file lives in the same scope as your object. So you need to call:
$this->pageTitle
If you don't want to do the whole $this->, you can do something like the following... The extract function will extract the array $this->data into variables with names respective to the key/index of each item. So now you will be able to do echo $pageTitle;
class Template{
public $data = Array();
public function __construct($pageTitle){
$this->data['pageTitle'] = $pageTitle;
}
public function display(){
extract($this->data);
include "/includes/head.php";
include "/includes/body.php";
}
}
Scope is a little different in PHP than in java.
For your specific case you need
$this->pageTitle
To access a variable declared outside the class, you'll need to make it global
global $myVar;

Categories