Is it bad practice to use use a foreach to make an array of all post data vs defining exactly what posts you are accepting?
class Foo {
function __construct()
{
foreach($_POST as $key => $var)
{
$this->post[] = $key = $var;
}
}
function bar()
{
echo $this->post['postdata'];
}
}
vs;
class Foo {
function __construct()
{
$this->post = array(
"postdata" => $_POST['postdata']
);
}
function bar()
{
echo $this->post['postdata'];
}
}
There is no great harm in automatically processing all of POSTed fields, as long as that processing is limited to storing in a hash. Matter of fact, it can make fore a significantly easier to maintain code.
The moment you start doing something (especially system related) with that data, you need to validate.
The only really bad practice I can find in this code is use of a global state/data. Your objects should never relay on a outside data. It's better to pass this data to the object as a method argument:
__construct(array $post) {
foreach (...) {
}
}
new Abc($_POST);
And returning to your question... More strict validators are usually better, however it always depends on what you're trying to achieve. You could define a list of expected elements and throw an exception when some extra element is being found.
Related
It seems some people hate global variables, but if you can explain how to code without them, I'm all ears.
Otherwise, I have a few options and I'm curious which is the best long-term. Consider that I have a variable that won't change for the duration. It's a static global. I can use:
$_SESSION['var'] = constantval;
define('var', constantval);
var = constantval;
and the one I'm really curious about:
function my_constants($which)
{
switch ($which) {
case 'var':
return 'constantval';
}
}
In that last one, the goal is to keep variable out of global scope to save memory at the sacrifice of some processor cost. Is the memory saved worth the cycles? Is there a noteworthy difference between the various other types of global declaration?
Global variables are not considered a bad practice because of memory usage or processor cost. It's because of the problems that allowing any part of your program to modify them may cause. With the time, it becomes hard to understand which parts of the program read or write to your global variables.
Alternatives to globals (singetons).
It will give you a fine grained access control:
E.g.:
class ConfigParamSingelton {
private var $value;
private static $mInstance = null;
public function getValue() {
return $this->value;
}
public function getInstance() {
if(self::$mInstance == null) {
self::$mInstance = new ConfigParamSingelton();
}
return self::$mInstance;
}
So now you can either:
protected function setValue($val) { // is immuteable by clients of the object
$this->value = $val;
}
or
public function setValue($val) {// is muteable
$this->value = $val;
}
Well, this are singletons. You don't need globals in this case.
Can I have two methods sharing the same name, but with different arguments?
One would be public static and would take 2 arguments, the other one just public and takes only one argument
example
class product{
protected
$product_id;
public function __construct($product_id){
$this->product_id = $product_id;
}
public static function getPrice($product_id, $currency){
...
}
public function getPrice($currency){
...
}
}
No. PHP does not support classic overloading. (It does implement something else that is called overloading.)
You can get the same result by using func_get_args() and it's related functions though:
function ech()
{
$a = func_get_args();
for( $t=0;$t<count($a); $t++ )
{
echo $a[$t];
}
}
I'm just giving you the super lazy option:
function __call($name, $args) {
$name = $name . "_" . implode("_", array_map("gettype", $args)));
return call_user_func_array(array($this, $name), $args);
}
That would for example invoke the real function name getPrice_string_array for two parameters of that type. That's sort of what languages with real method signature overloading support would do behind the scenes.
Even lazier would be just counting the arguments:
function __callStatic($name, $args) {
$name = $name . "_" . count($args);
return call_user_func_array(array($this, $name), $args);
}
That would invoke getPrice_1 for 1 argument, or getPrice_2 for, you guessed it, two arguments. This might already suffice for most use cases. Of course you can combine both alternatives, or make it more clever by search for all alternative real method names.
If you want to keep your API pretty and user-friendly implementing such elaborate workarounds is acceptable. Very much so.
PHP currently doesn't support overloading in known way, but you can still achieve your goal by using magic methods.
From PHP5 manual: overloading.
You could, kind of...
I consider it very much "hack" solutions, but you could make a single function and assign a standard value, that wouldn't otherwise be okay to use, to the parameters as needed. Then if you do not pass the function a certain parameter, it will be set to fx "-1".
public function getPrice($product_id = "-1", $currency) {
if($product_id = "-1") {
//do something
}else {
//do something
}
}
Or if you really need one method to be static, you can make a method that evaluates which method to call and call that instead of your getPrice:
public function whichGetPrice($product_id = "-1", $currency) {
if($product !== "-1") {
getStaticPrice($product_id, $currency);
}else {
getPrice($currency);
}
}
Like I said, very much "hack" solutions. It's not exactly pretty, nor a way people would expect you to do it. So I wouldn't necessarily recommend it, but it can help you do what you want.
I'm looking to create a sort of HashMap class in PHP. For the sake of being able to build upon PHP's associative array functionality, I have a hash function, which should be able to take any variable (primitive or object) and turn it into a string for use as an array key.
For this hash function, I am thinking of using serialize(), but I noticed that PHP calls __sleep() on an object when that function is called. I'm assuming this could be problematic. Am I right?
If so, what can I use to get a hash of either a primitive data type or of an object? I did look at spl_object_hash(), but its results seem less than unique, as it uses reference locations, which appear to be reused?
Any thoughts? Thanks
Update: If anyone's interested, this is (roughly speaking) what I ended up with. The Collection interface can be ignored. Any improvements welcome, of course. Oh, and there isn't a remove method yet.
<?php
include_once 'Collection.php';
class HashMap implements Collection {
private $data;
private $hashes;
public static function createEmpty() {
return new HashMap();
}
public function __construct() {
$this->data = new \SplObjectStorage();
$this->hashes = array();
}
public function add($key, $value) {
// var_dump($this->hash($key));
$this->data->offsetSet($this->hash($key), $value);
}
private function hash($key) {
if (!is_object($key)) {
if (isset($this->hashes[$key])) {
return $this->hashes[$key];
} else {
$obj = new PrimitiveAsObject(serialize($key));
return ($this->hashes[$key] = $obj);
}
} else {
return $key;
}
}
public function get($key) {
$key = $this->hash($key);
if ($this->data->contains($key)) {
return $this->data->offsetGet($key);
} else {
return null;
}
}
}
class PrimitiveAsObject {
private $val;
public function __construct($v) {
$this->val = $v;
}
}
You've mentioned that you're trying to use objects as keys in a hash, to store additional data.
The standard-in-PHP-5.3 SPL Object Storage class was designed for this use case, though it's kind of funky to use. It can behave as an array, thankfully.
Now, it can only be used to store actual objects, not primitives. This may pose a problem for your use case, but it's probably the best thing you've got for storage of objects as keys.
Objects as keys: SplObjectStorage
You can hash with md5
http://php.net/manual/en/function.md5.php
But of course you need a reliable and unique toString for objects involved.
I'm not sure if this is a trivial questions but in a PHP class:
MyClass:
class MyClass {
public $var1;
public $var2;
constructor() { ... }
public method1 () {
// Dynamically create an instance variable
$this->var3 = "test"; // Public....?
}
}
Main:
$test = new MyClass();
$test->method1();
echo $test->var3; // Would return "test"
Does this work?? How would I get this to work? Ps. I wrote this quickly so please disregard any errors I made with setting up the class or calling methods!
EDIT
What about making these instance variables that I create private??
EDIT 2
Thanks all for responding - Everyone is right - I should have just tested it out myself, but I had an exam the next morning and had this thought while studying that I wanted to check to see if it worked. People keep suggesting that its bad OOP - maybe but it does allow for some elegant code. Let me explain it a bit and see if you still think so. Here's what I came up with:
//PHP User Model:
class User {
constructor() { ... }
public static find($uid) {
$db->connect(); // Connect to the database
$sql = "SELECT STATEMENT ...WHERE id=$uid LIMIT 1;";
$result = $db->query($sql); // Returns an associative array
$user = new User();
foreach ($result as $key=>$value)
$user->$$key = $value; //Creates a public variable of the key and sets it to value
$db->disconnect();
}
}
//PHP Controller:
function findUser($id) {
$User = User::find($id);
echo $User->name;
echo $User->phone;
//etc...
}
I could have just put it in an associative array but I can never correctly name that array something meaningful (ie. $user->data['name'] ... ugly.) Either way you have to know what is in the database so I do not really understand what the argument is that its confusing, especially since you can just var dump objects for debugging.
Why dont you just write the code and see for yourself?
<?php
class Foo
{
public function __construct()
{
$this->bar = 'baz';
}
}
$foo = new Foo;
echo $foo->bar; // outputs 'baz'
and
var_dump($foo);
gives
object(Foo)#1 (1) {
["bar"] => string(3) "baz"
}
but
$r = new ReflectionObject($foo);
$p = $r->getProperty('bar');
var_dump($p->isPublic());
will throw an Exception about 'bar' being unknown, while
$r = new ReflectionObject($foo);
$p = $r->getProperties();
var_dump($p[0]->isPublic());
will return true.
Now, should you do this type of assignment? Answer is no. This is not good OOP design. Remember, OOP is about encapsulation. So, if bar is describing some public property of the class, make it explicit and declare it in your class as public $bar. If it is supposed to be private declare it as private $bar. Better yet, dont use public properties at all and make them protected and provide access to them only through getters and setters. That will make the interface much more clearer and cleaner as it conveys what interaction is supposed to be possible with an object instance.
Assigning properties on the fly here and there across your code, will make maintaining your code a nightmare. Just imagine somewhere along the lifecylce of Foo someone does this:
$foo = new Foo;
$foo->monkey = 'ugh';
echo $foo->monkey; // outputs 'ugh'
Now, from looking at the class definition above, there is absolutely no way, a developer can see there is now a monkey patched into Foo. This will make debugging a pain, especially if code like this is frequent and distributed across multiple files.
Yes that will indeed work. Auto-created instance variables are given public visibility.
yes that works as you'd hope/expect.
I you wanted to make private variables on the fly you could use php magic functions to emulate this, e.g
MyClass
<?php
class MyClass {
public $var1;
public $var2;
private $data = array();
public function __get($key) {
// for clarity you could throw an exception if isset($this->data[$key])
// returns false as it is entirely possible for null to be a valid return value
return isset($this->data[$key]) ? return $this->data[$key] : null;
}
public function __set($key, $value) {
$this->data[$key] = $value;
}
}
?>
Main
<?php
$test = new MyClass();
$test->myVar = 'myVar is technically private, i suppose';
echo $this->myVar; // 'myVar is technically private
?>
Although these dynamically created variables are technically private, they are infact publicly accessible... i cannot image the purpose for wanting to dynamically create private instance variables. I would question your design.
Did you try it?
It is possible but you might get strict errors. If you dynamically need to create these variables, you are probably doing something wrong.
You should either change this into a function:
function var($no) { .. }
or use __get (http://ca.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members)
In JavaScript, you can use Lazy Function Definitions to optimize the 2nd - Nth call to a function by performing the expensive one-time operations only on the first call to the function.
I'd like to do the same sort of thing in PHP 5, but redefining a function is not allowed, nor is overloading a function.
Effectively what I'd like to do is like the following, only optimized so the 2nd - Nth calls (say 25-100) don't need to re-check if they are the first call.
$called = false;
function foo($param_1){
global $called;
if($called == false){
doExpensiveStuff($param_1);
$called = true;
}
echo '<b>'.$param_1.'</b>';
}
PS I've thought about using an include_once() or require_once() as the first line in the function to execute the external code just once, but I've heard that these too are expensive.
Any Ideas? or is there a better way to tackle this?
Use a local static var:
function foo() {
static $called = false;
if ($called == false) {
$called = true;
expensive_stuff();
}
}
Avoid using a global for this. It clutters the global namespace and makes the function less encapsulated. If other places besides the innards of the function need to know if it's been called, then it'd be worth it to put this function inside a class like Alan Storm indicated.
Have you actually profiled this code? I'm doubtful that an extra boolean test is going to have any measurable impact on page rendering time.
you can do conditional function definiton.
if( !function_exists('baz') )
{
function baz( $args ){
echo $args;
}
}
But at present, a function becomes a brick when defined.
You can use create_function, but I would suggest you DONT because it is slow, uses lots of memory, doesn't get free()'d untill php exits, and is a security hole as big as eval().
Wait till PHP5.3, where we have "closures" http://wiki.php.net/rfc/closures
Then you'll be permitted to do
if( !isset( $baz ) )
{
$baz = function( $args )
{
echo $args;
}
}
$baz('hello');
$baz = function( $args )
{
echo $args + "world";
}
$baz('hello');
Upon further reading, this is the effect you want.
$fname = 'f_first';
function f_first( $even )
{
global $fname;
doExpensiveStuff();
$fname = 'f_others';
$fname( $even );
/* code */
}
function f_others( $odd )
{
print "<b>".$odd."</b>";
}
foreach( $blah as $i=>$v )
{
$fname($v);
}
It'll do what you want, but the call might be a bit more expensive than a normal function call.
In PHP5.3 This should be valid too:
$func = function( $x ) use ( $func )
{
doexpensive();
$func = function( $y )
{
print "<b>".$y."</b>";
}
$func($x);
}
foreach( range(1..200) as $i=>$v )
{
$func( $v );
}
( Personally, I think of course that all these neat tricks are going to be epically slower than your earlier comparison of 2 positive bits. ;) )
If you're really concerned about getting the best speed everywhere
$data = // some array structure
doslowthing();
foreach( $data as $i => $v )
{
// code here
}
You may not be able to do that however, but you've not given enough scope to clarify. If you can do that however, then well, simple answers are often the best :)
Please don't use include() or include_once(), unless you don't care if the include() fails. If you're including code, then you care. Always use require_once().
If you do wind up finding that an extra boolean test is going to be too expensive, you can set a variable to the name of a function and call it:
$func = "foo";
function foo()
{
global $func;
$func = "bar";
echo "expensive stuff";
};
function bar()
{
echo "do nothing, i guess";
};
for($i=0; $i<5; $i++)
{
$func();
}
Give that a shot
PHP doesn't have lexical scope, so you can't do what you want with a function. However, PHP has classes, which conceptually works in exactly the same way for this purpose.
In javascript, you would do:
var cache = null;
function doStuff() {
if (cache == null) {
cache = doExpensiveStuff();
}
return cache;
}
With classes (In PHP), you would do:
class StuffDoer {
function doStuff() {
if ($this->cache == null) {
$this->cache = $this->doExpensiveStuff();
}
return $this->cache;
}
}
Yes, class-based oop is more verbose than functional programming, but performance-wise they should be about similar.
All that aside, PHP 5.3 will probably get lexical scope/closure support, so when that comes out you can write in a more fluent functional-programming style. See the PHP rfc-wiki for a detailed description of this feature.
How about using local static variables?
function doStuff($param1) {
static $called = false;
if (!$called) {
doExpensiveStuff($param1);
$called = true;
}
// do the rest
}
If you need to do expensive stuff only once for given parameter value, you could use an array buffer:
function doStuff($param1) {
static $buffer = array();
if (!array_key_exists($param1, $buffer)) {
doExpensiveStuff($param1);
$buffer[$param1] = true;
}
// do the rest
}
Local static variables are persistent across function calls. They remember the value after return.
Any reason you're commited to a functional style pattern? Despite having anonymous functions and plans for closure, PHP really isn't a functional language. It seems like a class and object would be the better solution here.
Class SomeClass{
protected $whatever_called;
function __construct(){
$this->called = false;
}
public function whatever(){
if(!$this->whatever_called){
//expensive stuff
$this->whatever_called = true;
}
//rest of the function
}
}
If you wanted to get fancy you could use the magic methods to avoid having to predefine the called booleans. If you don't want to instantiate an object, go static.