I have a class that takes care of all the user-related data.
In one of my methods i want to access $_SESSION / $_GET, $_POST, any $_...
via a dynamic var like following (in _unset method):
class Userdata
{
...
const knownSources = ['post', 'get', 'cookie', 'session', 'files'];
private $post = [];
private $get = [];
private $cookie = [];
private $session = [];
private $files = [];
...
private function __construct()
{
$this->post = $this->secureVars($_POST);
$this->get = $this->secureVars($_GET);
$this->cookie = $this->secureVars($_COOKIE);
...
}
public static function getInstance(){...}
public static function secureVars($inputVar, $asObject = true, $acceptHTML = false){...}
public static function _unset($dataSource, $key)
{
$self = self::getInstance();
if (in_array(strtolower($dataSource), self::knownSources))
{
// Here I want to unset the variable in $_SESSION[$key] for instance, but 'SESSION' can be whichever of knownSources array.
print_r([
${'_SESSION'},
${'_' . 'SESSION'},
${'_' . strtoupper($dataSource)}
]);
...
}
}
}
Any idea why ${'_SESSION'} works but not ${'_' . 'SESSION'}?
And how to perform my goal: ${'_' . strtoupper($dataSource)}?
Thanks for your help!
[EDIT]
AFTER SUGGESTIONS, I came to this:
switch($dataSource)
{
case 'session':
$target = $_SESSION;
break;
case 'post':
$target = $_POST;
break;
case 'get':
$target = $_GET;
break;
case 'cookie':
$target = $_COOKIE;
break;
case 'files':
$target = $_FILES;
break;
}
unset($self->$dataSource->$key);
unset($target[$key]);
[EDIT]
AFTER REALISING IT STILL WON'T WORK, I - sadly - opt for:
switch($dataSource)
{
case 'session':
unset($_SESSION[$key]);
break;
case 'post':
unset($_POST[$key]);
break;
case 'get':
unset($_GET[$key]);
break;
case 'cookie':
unset($_COOKIE[$key]);
break;
case 'files':
unset($_FILES[$key]);
break;
}
unset($self->$dataSource->$key);
Any smarter suggestion much appreciated :)
Try this:
//Url
//?dangerous=yes&safe=keep
class MyClass {
public static function _unset($datasource, $key) {
global $$datasource;
unset(${$datasource}[$key]);
}
}
MyClass::_unset('_GET', 'dangerous');
//Test
print_r($_GET);
You are missing the global keyword.
Related
I try so hard to create this method with prepare, bind, and execute inside the class. But I guess I don't have enough knowledge about it whatever I do I couldn't make it work. I'm looking google for hours. I know that below code is wrong about binding but Can someone show me the correct way to do binding inside this method?
class User {
protected static $db_table = "users";
protected static $db_table_fields = array('username', 'password', 'first_name', 'last_name');
public $id;
public $username;
public $password;
public $first_name;
public $last_name;
protected function properties() {
$properties = array();
foreach (static::$db_table_fields as $db_field) {
if (property_exists($this, $db_field)) {
$properties[$db_field] = $this->$db_field;
}
}
return $properties;
}
protected function clean_properties() {
global $database;
$clean_properties = array();
foreach ($this->properties() as $key => $value) {
$clean_properties[$key] = $value;
}
return $clean_properties;
}
public function create($params= []){
global $database;
$properties = $this->clean_properties();
$fields = ":" . implode("',:'", static::$db_table_fields);
$sql= "INSERT INTO " .static::$db_table . "(" . implode(",", array_keys($properties)) . ")
VALUES('". $fields ."')";
$stmt = $database->prepare($sql);
foreach ($fields as $field => &$params) {
$stmt->bindValue($field, $params);
}
if ($stmt->execute()) {
$this->id = $database->InsertId();
return true;
} else {
return false;
}
}
So I made my code like this for binding. I don't know if it is the correct way. I know I keep changing stuff. I guess it is the best way to learn to try different stuff.
//$param = array('x'=>$x, 'y'=>$y);
public function bind($param = [], $type=NULL){
foreach($param as $key=>&$value){
if (is_null($type)) {
switch (true) {
case is_int($value):
$type = PDO::PARAM_INT;
break;
case is_bool($value):
$type = PDO::PARAM_BOOL;
break;
case is_null($value):
$type = PDO::PARAM_NULL;
break;
default:
$type = PDO::PARAM_STR;
}
}
$this->stmt->bindValue(':'.$key,$value);
}
return $this->stmt;
}
I am trying to get the script below on __set() to update the protected var.
I want this variable to be available to everyone, not just for one instance of the class object.
So far I can only get it to work for one instance, not globally.
class SessionClass
{
protected $ssnuid = 11;
protected $paccid = 11;
protected $authkey = 11;
public function __set($name, $value){
switch ($name) {
case 'ssnuid':
$this->$ssnuid = $value;
echo $ssnuid;
break;
case 'paccid':
$this->$paccid = $value;
echo $paccid;
break;
case 'authkey':
$this->$authkey = $value;
echo $authkey;
break;
}
}
public function __get($name){
return $this->name;
}
// END CLASS
} $session = new SessionClass;
$session->ssnuid = 20;
echo $session->ssnuid;
How can I achieve this?
*Newb here so please be kind. Thanks.
I didn't see any topic like this so I posted a new one.
First of all, I'm sorry about my bad English.
I want an public function who can storage in a global variable a value from database, and with that value the php script select the website templates. Can you help me?
private $page_title = null;
private $body_title = null;
private $body_content = null;
private $template = null;
private $settings = array();
private $file_template = 'content';
private $path = 'templates/';
private $parse_page = false;
global $template2;
public function GetHASH()
{
return $this->hash;
}
function Tema()
{
global $db,$user_class;
if($user_class->authorized)
{
$row = $db->sql("SELECT * FROM `ucp_users` WHERE `user_hash` = '".$this->GetHASH()."'");
$array = $db->get_array($row);
$template2 = $array['template'];
}
else
{
$template2 = '1';
}
return $template2;
}
function __construct() {
switch($template2) {
default:
{
$template_name = 'dsa/';
$template2 = 1;
}
break;
case 0: $template_name = 'lsrp/';
break;
case 1: $template_name = 'dsa/';
break;
}
$this->path = $this->path.''.$template_name;
}
Thank you.
When you instantiate your class, the constructor is called, at this time your tema method has not been invoked yet since it cannot be called without an instance. One solution would be to call your tema method in your constructor like this :
function __construct() {
$template2 = this->tema();
switch($template2) {
default:
{
$template_name = 'dsa/';
$template2 = 1;
}
break;
case 0: $template_name = 'lsrp/';
break;
case 1: $template_name = 'dsa/';
break;
}
$this->path = $this->path.''.$template_name;
}
I am passing a variable by reference to a class method with the intention that it will be set to a member of that same class (based on a selector to the function). Although this doesn't appear to violate the rules of PHP's deprecated call-time pass-by-reference, I must be missing something, because it doesn't work.
I've dumbed down my code to illustrate the issue:
<?php
class Database
{
static $USER_TABLE = 1;
static $INVOICE_TABLE = 2;
static $PRODUCT_TABLE = 3;
var $users;
var $invoices;
var $products;
function __construct()
{
$this->users []= array ('id'=>0, 'first_name'=>'John', 'last_name'=>'Doe');
$this->products []= array('id'=>0, 'user_id'=>'0', 'printer'=>'HP','computer'=>'Toshiba');
$this->invoices []= array('id'=>0, 'user_id'=>'0', 'total_items'=>2, 'total_cost'=>700);
}
function getTable($table_name, &$table)
{
switch ($table_name)
{
case Database::$USER_TABLE: $table = $this->users; break;
case Database::$INVOICE_TABLE: $table = $this->invoices; break;
case Database::$PRODUCT_TABLE: $table = $this->products; break;
}
}
function addEntry($table_name, $info_array)
{
$this->getTable($table_name, $table); // THIS FAILS! WHY?
//$table = &$this->users; // THIS WORKS
if ($table !== null)
{
$id = 0;
if (count($table))
$id = ((int)$table[count($table)-1]['id'])+1;
$entry['id'] = $id;
foreach ($info_array as $k => $v)
{
$entry [$k]= $v;
}
$table []= $entry;
}
}
}
$db = new Database;
$db->addEntry(Database::$USER_TABLE, array('first_name'=>'Jane', 'last_name'=>'Plain'));
var_dump($db);
?>
The alternative is just to take the switch case out of getTable(...) and paste that to the top of all of my functions that would have called it, but that type of code duplication is not desirable.
Any insight is appreciated!
It'd be a lot easier just to have your getTable actually return a table:
function getTable($table_name)
{
switch ($table_name)
{
case Database::$USER_TABLE: return $this->users; break;
case Database::$INVOICE_TABLE: return $this->invoices; break;
case Database::$PRODUCT_TABLE: return $this->products; break;
}
}
And then just call the following:
$table = $this->getTable($table_name);
I've got a small input helper class.
I read a lot that static classes are not the best to use. But I still haven't grasp why I shouldn't use static classes. I'm not that advanced yet, so maybe I will figure it out later on.
The reason I made it static is that it's not an object that's unique every time it's being called in my script.
Is it a good thing that I made the class static?
class Input {
public static function exists($type = 'post') {
switch($type) {
case 'post':
return (!empty($_POST)) ? true : false;
break;
case 'get':
return (!empty($_GET)) ? true : false;
break;
default:
return false;
break;
}
}
public static function get($input, $source = 'post') {
if($source == 'post' && isset($_POST[$input])) {
return $_POST[$input];
} else if($source == 'get' && isset($_GET[$input])) {
return $_GET[$input];
}
return false;
}
}
EDIT: Updated code
class Input {
private $_get,
$_post;
public function __construct($get, $post) {
$this->_get = $get;
$this->_post = $post;
}
public function exists($type = 'POST') {
switch($type) {
case 'POST':
return (!empty($this->_post)) ? true : false;
break;
case 'GET':
return (!empty($this->_get)) ? true : false;
break;
default:
return false;
break;
}
}
public function get($input, $source = 'POST') {
if($source == 'POST' && isset($this->_post[$input])) {
return $this->_post[$input];
} elseif($source == 'GET' && isset($this->_get[$input])) {
return $this->_get[$input];
}
throw new Exception('Undefined index: ' . $input);
}
}
Just because you have only one of something doesn't mean it has to be static. Especially in regard to Unit tests, static classes are hard to deal with.
Your class Input is bound to $_GET and $_POST. This means you can not use it in Unit tests.
If instead your class looked like this:
$input = new Input($_GET, $_POST);
ie. you give it the global dependencies, now Input can be tested because you can mock the values of $_GET and $_POST.
If you don't want a static class, you could do something like this :
class Input {
private $array;
function __construct($array) {
$this->array = $array;
}
public function exists() {
return isset($this->array);
}
public function get($input) {
if($this->exists() && isset($this->array[$input])) {
return $this->array[$input];
}
return false;
}
}
$get = new Input($_GET);
$value = $get->get('key');
$post = new Input($_POST);
$value = $post->get('key');