I wrote a question earlier trying to get around using a controller in Kohana, but I gave in and rewrote the file. So now, the I have this php script inside a Kohana controller. The view that the controller is rendering is 'requiring' a php file so I can perform some third-party functions. I was having a major issues with it and got to debugging. The problem seems that functions inside the included file cannot access variables outside the function from within that same file. It seems that Kohana is clearing the globals somehow???
example:
//controller.php
require_once("ccfunctions.php");
//ccfunctions.php
$test = 'something';
function test(){
global $test;
echo $test;
}
test();
//This does not produce anything
Any thoughts on this one?
EDIT:
Actually, the above example doesn't work even from my view file that is being rendered. Forget the included file. I realize Kohana tries to enforce the MVC model, but this is ridiculous. Why cannot I not create a function and call a global variable from within my view file?
You need to specify global for variable in both cases:
//controller.php
require_once("ccfunctions.php");
//ccfunctions.php
global $test;
$test = 'something';
function test(){
global $test;
echo $test;
}
test();
//This does not produce anything
Btw, it is really weird practice and I believe there are workarounds for any case without using global
Don't use globals. Why use an OOP framework when you want to use globals?
Related
I am creating some widget for Word Press, but maybe this is standard PHP question, because it is related to some MVC pattern. I have some HTML that i need to output on page but that HTML is for now i inside function, i would like to transfer it to partial, because in the future there can be lots of more HTML, and if I make it like this it will be lots of spaghetti code.Here is what i have for now
class motractrucks extends WP_Widget{
function widget($args, $instance, $defaults){
echo '<p>'.$value1.'<p>';
echo '<p>'.$value2.'<p>';
echo '<p>'.$value3.'<p>';
echo '<p>'.$value4.'<p>';
echo '<p>'.$value5.'<p>';
echo '<p>'.$value6.'<p>';
}
}
This is just simple example, I have modified function easy that you can understand what i need, i was thinking to do something like, but how to pass values form inside function in that view?
class motractrucks extends WP_Widget{
function widget($args, $instance, $defaults){
include 'partials/userValues.php';
}
}
And pass all values to that partial, any good idea and best code practice will be nice.
The part of this question that specifically pertains to PHP is the variable scope. PHP functions have a local scope. So variables used inside those functions are considered to be local variables by default. Unless you explicitly import a variable from the global scope into the function's local scope via the global keyword, it's local. In your examples those variables are all undefined.
Also, using echo inside a function is never considered good practice, but I can't speak specifically to the WordPress aspect of your code as I'm not that familiar with WordPress.
Functions should take inputs as arguments and should return values as output. That's typically what you would consider good practice.
function foo($var1, $var2, $var3) {
return <<<HTML
<p>$var1</p>
<p>$var2</p>
<p>$var3</p>
HTML;
}
As far as including files for use in templates, that's usually fine in PHP. When you're doing those includes inside of a function it becomes easier to contain their scope, because include takes scope into account.
Let's say your partials/userValues.php file looks something like this...
<p><?=$var1?></p>
<p><?=$var2?></p>
<p><?=$var3?></p>
If you want to include it from your function you can. You can also use output buffering with functions like ob_start() and ob_get_clean() to write the output into a buffer and return that from the function instead of just printing directly to standard out.
function foo($var1, $var2, $var3) {
ob_start(); // start the output buffer first
include 'partials/userValues.php'; // include inherits the variable scope
$output = ob_get_clean(); // close the buffer and store it in $output
return $output; // return it to the caller
}
Is there any way I can define a variable such a way that I don't need to global $var1; in every function? Just define it in beginning and keep using where ever needed. I know $GLOBALS exist, but don't want to use it.
First let me try to explain why you shouldn't use globals because they are extremely hard to manage. Say a team member overrides an $ADMIN variable in a file to be 1, and then all code that references the $ADMIN variable will now have the value of 1.
globals are so PHP4, so you need to pick a better design pattern, especially if this is new code.
A way to do this without using the ugly global paradigm is to use a class container. This might be known as a "registry" to some people.
class Container {
public static $setting = "foo";
}
echo Container::$setting;
This makes it more clear where this variable is located, however it has the weakness of not being able to dynamically set properties, because in PHP you cannot do that statically.
If you don't mind creating an object, and setting dynamic variables that way, it would work.
You need to pass the variable as a parameter to that function to avoid using GLOBALS.
The Problematic Scenario (Works ! but avoid it at all costs)
<?php
$test = 1;
function test()
{
global $test;
echo $test; // <--- Prints 1
}
test();
The right way...
<?php
$test = 1;
function test($test)
{
echo $test; // <--- Prints 1
}
test($test); //<--- Pass the $test param here
This behaviour called as superglobal variable. But php has limited predefined list of them: Superglobals.
So you cannot add your own superglobal variable.
Variable scope
My suggestions from the most to less radical:
Edit source code of PHP and add your own superglobals.
Do not write code at all.
Do not use PHP (use different language with different variable scope policy).
Do not use functions (write plain script).
Use constants instead of variables.
Use function params instead of using globals.
Use static variables instead of globals. (\G::$variable)
I am using PHP 5.3.8 with CakePHP 2.1.1.
This is my view (the layout is empty, actually it only outputs the view itself)
<?php
// $present is not a view variable
$present = 'Hello World!';
class ApplicationsPDF
{
public function CreateApplicationTable()
{
global $present;
exit(var_dump($present));
}
}
$pdf = new ApplicationsPDF();
$pdf->CreateApplicationTable();
?>
The output is null instead of "Hello World!".
If I copy and paste this code into a single file (which I directly run from the browser), it perfectly works!
So it must be a CakePHP bug. Does anyone know it?
Try to declare the global keyword before the class definition:
global $present;
class ApplicationsPDF
{
public function CreateApplicationTable()
{
exit(var_dump($present));
}
}
It's not a PHP nor a CakePHP bug!
It's because CakePHP includes the view in its view class so the declared variables aren't really in the global scope and global has no effect.
From ADmad (source):
When you run the file by itself your assignment $testVar = 'Hello
World!' is in global context hence things work like you expected them
to. But when it is used as a view file, the file is included within a
View class function hence its no longer in global context and $testVar
is no longer a global var, hence your expectation is incorrect. Using
global variables in an OOP framework is a bad idea anyway.
To include raw JavaScript files into my pages, i've ended up using:
function include_js($jsfile, $basepath = JSPATH){
echo '<script type="text/javascript">';
include($basepath . $jsfile);
echo '</script>';
}
Works fine, and the PHP code inside these JS files is still executing fine, no problem here.
But here is some pseudo code of what i used before:
<script>
var hello = '<?php echo $id; ?>';
</script>
So, here's the problem:
Before, the PHP code used inside my JavaScript files was executed in the same context as the page's one.
Now, it's executed in the context of the include_js() function.
Thus, i don't have access to any of my page's variables anymore. I could fix it with a global $id;, but that was pseudo-code.
Actually, i have NO idea what variables i'll need to have access to.
Any idea how to solve that problem? If you have a better solution than what i'm actually doing inside include_js() to achieve the same goal without the problem i'm talking about, that would be as much appreciated!
You could import all global variables (but Superglobals) into the local scope of the function where you do the include. I don't think it's really a good solution (as it's a hammer) but as you write in your question you don't know which variables are used, so you could localize them like:
$varname = $GLOBALS['varname'];
As an alternative you could inspect the JS file and/or provide the list of variables for a file and add it to the include function as an array. See another answer for some code example.
You could also first pre-include (and throw away) the js file, gather the warnings about undefined variables, import them and then include for real. Some more include/discard/return/variable related chunks of code.
You can use global variables, but a more robust way is to write your own "constant databases". Something like:
class ConstantDB{
public static function set($key, $value){
}
public static function get($key){
}
}
It's just very convenient in many cases. For your particular situation, then you can use
ConstantDB::set("my_id", $id);
and inside the include_js, you can use
ConstantDB::get("my_id");
can I put a function in PHP inside a if structure? like this:
<?php
if(true){
function HelloWorld(){
echo "Hello World!!!";
}
HelloWorld();
}
?>
because I have tried and it works, but I don't know if it is correct or not. Thanks
This is perfectly legal - it simply defines the function within the if statement block. That said, quite why you'd want to do this is somewhat of a mystery.
It's also worth noting that this function will be available in the global scope (i.e.: outside of the if statement block), as...
All functions and classes in PHP have
the global scope - they can be called
outside a function even if they were
defined inside and vice versa.
See the PHP User-defined functions manual page for more information.
As middaparka says, this is perfectly legal, but in terms of using it, you might want to check if a function exists before declaring it:
if (!function_exists("foo"))
{
function foo()
{
return "bar";
}
}
function_exists documentation
It looks a bit strange, but yes it's legal
As of PHP 5.3 if you need a function with a limited scope (say for a callback) you can use anonymous functions / closures
I wanted to add an answer here, because there's a caveat that isn't addressed in the other answers.
Based on my testing in 5.3, it appears that functions that are defined inside if structures are defined at runtime, rather than at compile time like other functions.
For example, outside a conditional block, this:
foo();
function foo(){
echo 'foo!';
}
works fine because the function is defined at compile time, and executed at runtime. But calling the function before defining it while inside a condition block:
if(1){
foo(); // Call to undefined function!
function foo(){
echo 'foo!';
}
}
Will produce a call to undefined function error, at least as of version 5.3.
But defining the function in an if block before calling it is valid:
if(1){
function foo(){
echo 'foo!';
}
foo(); // No errors, since function is defined!
}
So there is a major gotcha to be aware of when defining functions inside a conditional: the function must be defined in the code before calling the function, since conditional functions don't seem to get defined at compile time.
The OP also asked about performance. If the conditional function is defined at runtime instead of compile time like most other functions, then this function will not benefit from performance boosters like OpCode caching, which depending on the circumstances, could slow down your application. For example, if your master php file looked like:
if($IsLoggedIn){
// include files/functions and bootstrap here...
}
Then the entire application might not benefit from OpCode caching at all.
Basically yes, according to the manual:
Any valid PHP code may appear inside a
function, even other functions and
class definitions.
Personally I haven't had a situation in which I'd actually do such a thing. Most of the time it would be easier to group your functions on a place where it actually can be found! ;-)