Variable Scope in PHP MVC Frameworks like CakePHP - php

I am building a PHP MVC framework like Ruby on Rails but with PHP for learning. The link just in case you want to see it is https://github.com/carlinoo/vinum
I was trying to see the source code of CakePHP as it is very similar to mine. When in aa action in a controller, after the logic of that action/method, it calls the view, a different file that has access to those variables. I cant seem to understand how that works.
How does it call the view after the logic is finished? In CakePHP there’s something called autoRender that if set to true, it renders the appropriate view. How can you do that without calling a function to render the view?
Also, I have a variable scope problem. Let me explain:
function func1() {
$var = 1;
render();
}
function render() {
require_once(‘file.php’);
}
// This is file.php
<?php
echo $var;
?>
$var one does not exist because of the scope, and i don’t want to declare the variables as global. How do big PHP Frameworks do this? And how does the autoRender actually work? Thank you

This is the "easy" way
function func1() {
$var = 1;
render(‘file.php’, get_defined_vars());
}
function render($file, $vars = []) {
extract($vars);
require $file; //pass the filename in for reuse
}
But it's really messy, and prone to variable name collisions.
This function returns a multidimensional array containing a list of all defined variables, be them environment, server or user-defined variables, within the scope that get_defined_vars() is called.
http://php.net/manual/en/function.get-defined-vars.php
Import variables from an array into the current symbol table.
http://php.net/manual/en/function.extract.php
I would manually build an array of variables, pass that to render($vars) and then use extract().
function func1() {
$vars = ['var1' => 1];
render(‘file.php’, $vars);
}
Also I would use require instead of require_once otherwise if you need to render the same template multiple times it wont work, think like in the case of a post or something you can loop on and call render multiple times. For example
you may have a "controller" named posts.php
render('header.php');
render('menu.php');
foreach($posts as $post){
render('post.php', $post);
}
render('footer.php');
The main Idea behind a template is to eliminate structural PHP mixed into the HTML. So you would want, smaller chunks of HTML that you can reuse multiple times. And mostly keep it to echoing variables in the tempate/view
Lastly, I would take what I put above as "theoretical" code, I can't really test this very well, but that's the basic concept.
UPDATE
Here is a quick Psudo-ish Code example of what CakePHP does ( obviously its way more complex then i can do in an answer on here ).
Its mainly the difference between using procedural and object oriented coding.
class Controller{
protected $data;
public function index(){
$this->color = 'pink';
$this->render('view.php');
}
///magic method
public function __set( $key, $value){
$this->data[$key] = $value;
}
/*
you can do the same thing with a normal method
public function set( $key, $value){
$this->data[$key] = $value;
}
but instead of doign $this->color = 'pink';
you would do $this->set('color', 'pink');
*/
public function render($file){
/*
obviously I can easily access $this->data['color']
from within the scope of the same class.
*/
extract($this->data);
include $file;
/*
or any number of other things
like
$contents = file_get_contents($file);
foreach( $this->data as $key => $value )
$contents = str_replace('{'.$key.'}', value , $contents);
echo $contents;
for tags like {color} etc.
*/
}
}
Right here is every method they are using.
https://api.cakephp.org/3.5/class-Cake.Controller.Controller.html
And here is the source code for their controller,
https://api.cakephp.org/3.5/source-class-Cake.Controller.Controller.html#583-622
Honestly I wouldn't recommend using the magic metods like __set __get etc. because it Makes the code
harder to read
harder to maintain
more prone to error
less efficient, performance wise.
For example
$this->set('data', 'foo');
Is safe, but using
$this->data = 'foo';
Will wipe out that data array property, because in my example the data gets put into a class property named data as an array, so calling $this->data = foo; accesses the already existing property and overwrites it. Which then means you have to do all kinds of checks and other things to make sure nothing gets overwritten, and anytime you add any properties you have to deal with that kind of stuff. And if you miss something you may not find it for months and then one day, you set data in a controller and it all falls apart.
For reference.
http://php.net/manual/en/language.oop5.magic.php
Anyway

Related

how to nest a function inside an another function in php [duplicate]

In JavaScript nested functions are very useful: closures, private methods and what have you..
What are nested PHP functions for? Does anyone use them and what for?
Here's a small investigation I did
<?php
function outer( $msg ) {
function inner( $msg ) {
echo 'inner: '.$msg.' ';
}
echo 'outer: '.$msg.' ';
inner( $msg );
}
inner( 'test1' ); // Fatal error: Call to undefined function inner()
outer( 'test2' ); // outer: test2 inner: test2
inner( 'test3' ); // inner: test3
outer( 'test4' ); // Fatal error: Cannot redeclare inner()
If you are using PHP 5.3 you can get more JavaScript-like behaviour with an anonymous function:
<?php
function outer() {
$inner=function() {
echo "test\n";
};
$inner();
}
outer();
outer();
inner(); //PHP Fatal error: Call to undefined function inner()
$inner(); //PHP Fatal error: Function name must be a string
?>
Output:
test
test
There is none basically. I've always treated this as a side effect of the parser.
Eran Galperin is mistaken in thinking that these functions are somehow private. They are simply undeclared until outer() is run. They are also not privately scoped; they do pollute the global scope, albeit delayed. And as a callback, the outer callback could still only be called once. I still don't see how it's helpful to apply it on an array, which very likely calls the alias more than once.
The only 'real world' example I could dig up is this, which can only run once, and could be rewritten cleaner, IMO.
The only use I can think of, is for modules to call a [name]_include method, which sets several nested methods in the global space, combined with
if (!function_exists ('somefunc')) {
function somefunc() { }
}
checks.
PHP's OOP would obviously be a better choice :)
[Rewritten according to the comment by #PierredeLESPINAY.]
It's not just a side-effect at all, but actually a very useful feature for dynamically modifying the logic of your program. It's from the procedural PHP days, but can come in handy with OO architectures too, if you want to provide alternative implementations for certain standalone functions in the most straightforward way possible. (While OO is the better choice most of the time, it's an option, not a mandate, and some simple tasks don't need the extra cruft.)
For example, if you dynamically/conditionally load plugins from your framework, and want to make the life of the plugin authors super easy, you can provide default implementations for some critical functions the plugin didn't override:
<?php // Some framework module
function provide_defaults()
{
// Make sure a critical function exists:
if (!function_exists("tedious_plugin_callback"))
{
function tedious_plugin_callback()
{
// Complex code no plugin author ever bothers to customize... ;)
}
}
}
Functions defined within functions I can't see much use for but conditionally defined functions I can. For example:
if ($language == 'en') {
function cmp($a, $b) { /* sort by English word order */ }
} else if ($language == 'de') {
function cmp($a, $b) { /* sort by German word order; yes it's different */ }
} // etc
And then all your code needs to do is use the 'cmp' function in things like usort() calls so you don't litter language checks all over your code. Now I haven't done this but I can see arguments for doing it.
All the above being said, one might simply create a nested function to replace some localized, repetitive code within a function (that will only be used inside the parent function). An anonymous function is a perfect example of this.
Some might say just create private methods (or smaller code blocks) in a class, but that is muddying the waters when an ultra-specific task (which is exclusive to the parent) needs to be modularized, but not necessarily available to the rest of a class. The good news is if it turns out that you do need that function somewhere else, the fix is rather elementary (move the definition to a more central location).
Generally speaking, using JavaScript as the standard by which to evaluate other C based programming languages is a bad idea. JavaScript is definitely its own animal when compared to PHP, Python, Perl, C, C++, and Java. Of course, there are lots of general similarities, but the nitty, gritty details (reference JavaScript: The Definitive Guide, 6th Edition, Chapters 1-12), when paid attention to, make core JavaScript unique, beautiful, different, simple, and complex all at the same time. That's my two cents.
Just to be clear, I'm not saying nested functions are private. Just that nesting can help avoid clutter when something trivial needs to be modularized (and is only needed by the parent function).
All of my php is OO, but I do see a use for nested functions, particularly when your function is recursive and not necessarily an object. That is to say, it does not get called outside of the function it is nested in, but is recursive and subsequently needs to be a function.
There's little point in making a new method for the express use of a single other method. To me that's clumsy code and sort-of not the point of OO. If you're never going to call that function anywhere else, nest it.
In webservice calling we found it a much lower overhead (memory and speed) dynamically including in a nested fashion, individual functions over libraries full of 1000s of functions. The typical call stack might be between 5-10 calls deep only requiring linking a dozen 1-2kb files dynamically was better than including megabytes. This was done just by creating a small util function wrapping requires. The included functions become nested within the functions above the call stack. Consider it in contrast to classes full of 100s of functions that weren't required upon every webservice call but could also have used the inbuilt lazy loading features of php.
if you are in php 7 then see this:
This implementation will give you a clear idea about nested function.
Suppose we have three functions(too(), boo() and zoo()) nested in function foo().
boo() and zoo() have same named nested function xoo(). Now in this code I have commented out the rules of nested functions clearly.
function foo(){
echo 'foo() is called'.'<br>';
function too(){
echo 'foo()->too() is called'.'<br>';
}
function boo(){
echo 'foo()->boo() is called'.'<br>';
function xoo(){
echo 'foo()->boo()->xoo() is called'.'<br>';
}
function moo(){
echo 'foo()->boo()->moo() is called'.'<br>';
}
}
function zoo(){
echo 'foo()->zoo() is called'.'<br>';
function xoo(){ //same name as used in boo()->xoo();
echo 'zoo()->xoo() is called'.'<br>';
}
#we can use same name for nested function more than once
#but we can not call more than one of the parent function
}
}
/****************************************************************
* TO CALL A INNER FUNCTION YOU MUST CALL OUTER FUNCTIONS FIRST *
****************************************************************/
#xoo();//error: as we have to declare foo() first as xoo() is nested in foo()
function test1(){
echo '<b>test1:</b><br>';
foo(); //call foo()
too();
boo();
too(); // we can can a function twice
moo(); // moo() can be called as we have already called boo() and foo()
xoo(); // xoo() can be called as we have already called boo() and foo()
#zoo(); re-declaration error
//we cannont call zoo() because we have already called boo() and both of them have same named nested function xoo()
}
function test2(){
echo '<b>test2:</b><br>';
foo(); //call foo()
too();
#moo();
//we can not call moo() as the parent function boo() is not yet called
zoo();
xoo();
#boo(); re-declaration error
//we cannont call boo() because we have already called zoo() and both of them have same named nested function xoo()
}
Now if we call test1() the output will be this:
test1:
foo() is called
foo()->too() is called
foo()->boo() is called
foo()->too() is called
foo()->boo()->moo() is called
foo()->boo()->xoo() is called
if we call test2() the output will be this:
test2:
foo() is called
foo()->too() is called
foo()->zoo() is called
zoo()->xoo() is called
But we cannot call both text1() and test2() at same time to avoid re-declaration error
For those that suggest that there is no practical use of nested functions. Yes they have use and this is an example.
Imagine that I have a file called my_file.php which is used to get an ajax result out of. But what if there are times that you don't want to get the result through ajax but you want to include it twice in the same page without conflicts?
Lets say ajax file my_file.php :
<?php
// my_file.php used for ajax
$ajax_json_in = 10;
function calculations($a, $b)
{ $result = $a + $b;
return $result;
}
$new_result = $ajax_json_in * calculations(1, 2);
$ajax_json_out = $new_result;
?>
Below example includes the above file twice without conflict. You may not want to ajax call it, because there are cases that you need to include it straight in the HTML.
<?php
// include the above file my_file.php instead of ajaxing it
function result1
{
$ajax_json_in = 20;
include("my_file.php");
return $ajax_json_out;
}
function result2
{
$ajax_json_in = 20;
include("my_file.php");
return $ajax_json_out;
}
?>
Including the file makes the file's functions nested. The file is used both for ajax calls and inline includes !!!
So there is use in real life of nested functions.
Have a nice day.
I know this is an old post but fwiw I use nested functions to give a neat and tidy approach to a recursive call when I only need the functionality locally - e.g. for building hierarchical objects etc (obviously you need to be careful the parent function is only called once):
function main() {
// Some code
function addChildren ($parentVar) {
// Do something
if ($needsGrandChildren) addChildren ($childVar);
}
addChildren ($mainVar); // This call must be below nested func
// Some more code
}
A point of note in php compared with JS for instance is that the call to the nested function needs to be made after, i.e. below, the function declaration (compared with JS where the function call can be anywhere within the parent function
I have only really used this characteristic when it was useful to execute a small recursive function inside a primary, more categorical function, but didn't want to move it to a different file because it was fundamental to the behavior of a primary process. I realize there are other "best practice" ways of doing this, but I want to make sure my devs see that function every time they look at my parser, it's likely what they should modify anyway...
Nested functions are useful in Memoization (caching function results to improve performance).
<?php
function foo($arg1, $arg2) {
$cacheKey = "foo($arg1, $arg2)";
if (! getCachedValue($cacheKey)) {
function _foo($arg1, $arg2) {
// whatever
return $result;
}
$result = _foo($arg1, $arg2);
setCachedValue($cacheKey, $result);
}
return getCachedValue($cacheKey);
}
?>
Nested functions are useful if you want the nested function to utilize a variable that was declared within the parent function.
<?php
ParentFunc();
function ParentFunc()
{
$var = 5;
function NestedFunc()
{
global $var;
$var = $var + 5;
return $var;
};
echo NestedFunc()."<br>";
echo NestedFunc()."<br>";
echo NestedFunc()."<br>";
}
?>

Using clousers to handle templates in PHP

There is like a million Template Engine for PHP (Blade, Twig, Smarty, Mustache, ...), and i just hate the idea of creating a new syntax and compiler to write PHP inside HTML! I think it's just not smart (but this isn't what i am here to discuss :) ), what is wrong with writing PHP+HTML the usual way - not for logic - you know, all the variables and loops and defines you wanna use without this {{% %}} or that {:: ::} ! At least for performance sake!
Now, i am using Laravel these days , and it's awesome; it offers (besides Blade and any other 3rd party engine) a plain PHP templates system that uses ob_start/include/ob_get_clean and eval. I was very happy to know that i can avoid learning a new syntax to write PHP inside HTML.
Here is what i am suggesting; what about instead of using ob_* functions with include, we use Closures ? Here is a simple class i put together just to make a point:
class Templates{
static public $templates = array();
static public function create($name, $code){
self::$templates[$name] = $code;
}
static public function run($name, $data){
if(!isset(self::$templates[$name]) || !is_callable(self::$templates[$name])) return false;
return call_user_func(self::$templates[$name], $data);
}
}
And here is how to use it:
Templates::create('test', function($data){
return 'Hi '.$data['name'].' ! ';
});
for($i =0; $i < 10; $i++){
print Templates::run('test', array('name' => 'Jhon'));
}
I think this way is much better, since i wont need to do any output buffering or use eval. And to "separate concerns" here, we can put the Templates::create code in a separate file to keep things clean, in fact this way things can become more simple and elegant; we can make another method to load the template file:
static public function load($name){
self::create($name, include($name.'.php'));
}
And the content of the template file will be as simple as this:
return function($data){
return 'Hi '.$data['name'].' ! ';
};
What do you think of this ? Is there any problems with the approach or the performance of such use of Closures ?
I do not think there are any problems besides that if you put all closure functions into array, that would possibly mean that functions are kinda doing basically the same stuff.
What I mean by this:
In your example you have your functions accepting only 1 parameter. So, not to create a mess all functions you create would accept the same set of parameters and return the same type of data.
However when declared apart, functions may be supposed to do something different and unique.
Why such a solution is suitable: when using some engines, there may be a lot of different functions declared already. To resolve the conflict, they can be "hidden" inside arrays.
Also, some people even say that anonymous functions can be generally better in case of performance. But we have to test that first: to call a function you:
Call a static function run
Check a function for existence
Check a function for callability
And then use call_user_func which returns the return of your function. So, 3x return.
Update
My recomendations for you code:
Make all possible checks only when creating a function. That will greatly buff performance.
static public function create($name, $code){
if (!isset(self::$templates[$name])){
if (is_callable($code)){
self::$templates[$name] = $code ;
} else {
//func is not callable, Throw an exception.
}
} else {
//function already exists. Throw an exception.
}
}
That way you just can have 2x increase in performance:
static public function run($name, $data){
if (isset(self::$templates[$name])){
self::$templates[$name]($data); //Just make a straight call
} else {
//throw new Exception(0, "The func is not defined") ;
}
}

Confused about __get and __set in MVC framework design

I've been reading up on how exactly MVC frameworks work and the design pattern itself. I can understand most parts and see how it all fits together, but on a lot of examples I've seen something like this:
class Registry
{
private $vars = array();
public function __set($index, $value)
{
$this->vars[$index] = $value;
}
public function __get($index)
{
return $this->vars[$index];
}
}
In a lot of tutorials it's called the "registry". It is usually instantiated in the init file and is part of calling a core class(route handler, templating etc.), for example rendering a view in your controller like this $this->registry->template->render('view');.
Reading the code 'word' for word I can see what it does, $this->vars[$index] = $value, takes the index from the vars[] array and makes it equal to $value. So, if we did:
__set(1, 'firstname');
// So now
$vars[1] = 'firstname';
__get(1); // Returns 'firstname'
Please correct me if I'm wrong here.
Faintly I can see the benefits and how useful this is, but I can't yet grasp the bigger picture. I can't tie it to the rest of the components and it seems to be a large part.
I can't wrap my head around as to what its purpose is.
This is more of a design discussion than something more concise like a code debug. So..
This tells you why its a good idea
This tells you why it is not
And this tells you about the registry getters and setters
__get() and __set() are so called magic methods. The benefit of them is, that you don't have to call them, they will be called by the PHP interpreter itself. This happens if you try to access non accessible properties of an object. This is called property overloading.
Try this:
class Test {
private $foo;
public function __set($name, $value) {
echo "assgning $name => $value";
}
}
$t = new Test();
$t->foo = 'bar';

Advantage of passing by reference opposed to using global?

im looking at the MVC pattern, and I can see in one example on phppatterns they're passing the model by reference - any benefit of doing this over a global var? Am I missing something obvious?
class MyView extends View {
var $model;
function __construct(&$model){
$this->model =& $model;
}
function productTable($rownum=1) {
$rowsperpage='20';
$this->model->listProducts($rownum,$rowsperpage);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}
}
Any reason why you would do this as apposed to using a global variable? i.e.
class MyView extends View {
global $model;
function __construct(){ }
function productTable($rownum=1) {
$rowsperpage='20';
$model->listProducts($rownum,$rowsperpage);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}
The problem with global variables is that:
They assume that there is only one implementation of model and view.
They assume that there is only one instance of the model and view (you could have several of each in your application).
They hide the interdependency between components; your view is very strongly affected by the model, but not having to explicitly pass a model into your view makes this implicit.
For other reasons why globals and singletons are "evil" (i.e. just really a poor design decision that you should never make), read avoid global variables, environment variables, and singletons.
Yes -- the advantage is that you could change the implementation of the model without having to modify the View.
I'd suggest to use another tutorial, the one you're using is a bit outdated, and isn't PHP 5. That said, you really shouldn't use global variables, that's never the solution!
But I don't really get why you should even wanna pass it by reference, in PHP 5 it's already passed by reference:
class foo {
public $a;
public function __construct($a) {
$this->a = $a;
}
}
$a = new foo(10);
$b = $a;
$a->a = 20;
echo $a->a.' => '.$b->a; // 20 => 20
If you have multiple (similar) model instances, on which you possibly would like to apply the same view, you would need to explicitly pass the model instance. A global variable assumes there could be only one model instance, and thus creates an artificial limitation.
In general not using global variables is better to help you control the scope of your variables.
I won't mention about why that is a bad thing, because it has been already discussed. One thing that I think you should know is that the code provided there is PHP 4 compatible. In PHP 5 by default objects are sent by reference.

Temporary Variable

I have a function that retrieves some data from the database, formats it as HTML and then stores this HTML into a variable, $output. The problem is that $output cannot be echoed on the screen now, only later, after other functions run. Also this data must be retrieved at this stage, not later.
So how can I call this $output variable in another function, after output to the screen has started?
You could define $output in the main script, and import it into a function:
function output()
{
global $output;
This will probably work for your situation at hand. However, it is considered bad practice to use the global variable space with stuff like this, and rightly so. (Believe me, I've done it for years. :)
There are some other approaches that are better for long-term code quality and maintainability.
Global config array
You could either keep one global array for all global settings. Do this somewhere in your main script:
$config = array();
$config["output"] = "<html>.......</htmL>";
$config["user_language"] = "en";
.....
you import the configuration array into the function like so:
function output()
{ global $config;
echo $config["output"];
Registry pattern
if you want to do some reading, you could use something more advanced like the Registry Pattern. The snippet shown here looks a nice example for a registry. The Zend Framework also has a class for this.
But things like a Registry are really, really advanced, and probably not necessary for you at this point. I would suggest using one central config array. Should the need for something more complex arise, the config array is easy to find and replace.
Context: Are global variables in PHP considered bad practice?
welcome to using returns, and passing parameters:
DO NOT USE global , it breaks encapsulation, one of the cornerstones of object oriented programming, and can lead to incredibly hard to maintain code.
<?php
function doSomethingInDb(){
$value = db_result(); //something from the database, this is psuedo code
return $value
}
function displaySomethingFromDb($input){
echo($input); //or some other way of displaying
}
//calulate results
$output = doSomethinginDb();
//do other stuff...
//output the result when you need it...
displaySomethingFromDb($output);
You have to pass the variable via a function argument, or define it as global inside the function.
$output = '<p>macilaci</p>';
function doesathing($output)
{
echo $output;
}
OR
function doesathing()
{
global $output;
echo $output;
}
don't put the data in a variable inside the function which retrieves it.
function retrieve(...)
{
... fetch from db
return $rv;
}
function other() {...}
function still($data)
{
...
echo $data;
}
$output = retrieve(...);
other();
still($output);
Rather than just putting this snippet into a global variable, IMHO a better solution is to use a templating system to construct the elements of the page.
NB I'm not suggesting you immediately rush out and start downloading Smarty - although there are benefits and drawbacks to completely seperating logic and presentation, there are only benefits in taking a modular approach to your screen layout.
C.
Put the following line at the start of the function that defines $output:
global $output;
Put the same line at the start of any function that will make use of it.
(This will not work, or will interfere with other variables, if there is already a variable called $output in the global scope.)
Use Session
For example:
session_start();
$query = '...........';
$result = mysql_query($query);
$_SESSION['mysqlResult'] = $result;
Now you can use it from any page at any time by simply calling like this
$myresult = $_SESSION['mysqlResult'];

Categories