Class encapsulating $_SESSION - problem [duplicate] - php

This question already exists:
Closed 11 years ago.
Possible Duplicate:
Class encapsulating $_SESSION - problem
include/session.php:
/*
Use the static method getInstance to get the object.
*/
class Session
{
const SESSION_STARTED = TRUE;
const SESSION_NOT_STARTED = FALSE;
// The state of the session
private $sessionState = self::SESSION_NOT_STARTED;
// THE only instance of the class
private static $instance;
protected function __construct() { }
public function __destruct() {
session_write_close();
}
/**
* Returns THE instance of 'Session'.
* The session is automatically initialized if it wasn't.
*
* #return object
**/
public static function GetInstance()
{
if ( !isset(self::$instance))
{
self::$instance = new self;
}
self::$instance->startSession();
return self::$instance;
}
public function getID() {
return session_id();
}
/**
* (Re)starts the session.
*
* #return bool TRUE if the session has been initialized, else FALSE.
**/
public function startSession()
{
if ( $this->sessionState == self::SESSION_NOT_STARTED )
{
$this->sessionState = session_start();
}
return $this->sessionState;
}
/**
* Creates a new session.
**/
public function newSession() {
return session_regenerate_id(true);
}
/**
* Stores datas in the session.
* Example: $instance->foo = 'bar';
*
* #param name Name of the datas.
* #param value Your datas.
* #return void
**/
public function __set( $name , $value )
{
$_SESSION[$name] = $value;
}
/**
* Gets datas from the session.
* Example: echo $instance->foo;
*
* #param name Name of the datas to get.
* #return mixed Datas stored in session.
**/
public function __get( $name )
{
if ( isset($_SESSION[$name]))
{
$ret = $_SESSION[$name];
return $ret;
}
}
public function __isset( $name )
{
return isset($_SESSION[$name]);
}
public function __unset( $name )
{
unset( $_SESSION[$name] );
}
/**
* Destroys the current session.
*
* #return bool TRUE is session has been deleted, else FALSE.
**/
public function destroy()
{
session_start();
session_unset();
session_destroy();
}
}
?>
test.php:
<?php
require_once('include/session.php');
$session = Session::GetInstance();
$session->foo = 'bar';
$session->baz = array();
$session->baz['foo'] = 'bar';
$session->baz['derp'] = array();
$session->baz['derp']['php_sucks'] = 'this will never work';
var_dump($session->foo); echo '<br>';
var_dump($session->baz); echo '<br>';
var_dump($session->baz['foo']); echo '<br>';
var_dump($session->baz['derp']); echo '<br>';
var_dump($session->baz['derp']['php_sucks']); echo '<br>';
?>
output:
string(3) "bar"
array(0) { }
NULL
NULL
NULL
Why isn't the $session->baz array being filled?

When you call $session->baz['foo'], $session->baz returns a copy of the array that is in the session and then you add the 'foo' element to it. This copy is not the copy inside your class and is pretty much instantly discarded.
You'll need to change the way you handle having arrays in there, ie using some getters and setters (including the magic ones) or look into ways of getting the 'baz' element out by reference instead of copy.

Related

Initializing class properties

I need to initialize some properties in my class. I don't use constructor, only set methods.
<?php
namespace Task;
class Log {
private $_views = null;
private $_urls = null;
private $_traffic = null;
/**
* #param int $count
*/
public function setViewCount(int $count) {
$this->$_views = $count;
}
/**
* #return int
*/
public function getViewCount() {
return $this->$_views;
}
/**
* #param int $count
*/
public function setUrlCount(int $count) {
$this->$_urls = $count;
}
/**
* #return int
*/
public function getUrlCount() {
return $this->$_urls;
}
/**
* #param int $trafficData
*/
public function setTraffic(int $trafficData) {
$this->$_traffic = $trafficData;
}
/**
* #return int
*/
public function getTraffic() {
return $this->$_traffic;
}
}
?>
Then I try to set values to properties and save it to associative array.
<?php
require 'Log.php';
use Task;
$log = new Task\Log();
$log->setViewCount(44);
$log->setUrlCount(55);
$log->setTraffic(99999);
$res = array("views" => $log->getViewCount(), "urls" => $log->getUrlCount(), "traffic" => $log->getTraffic());
echo json_encode($res);
?>
After encoding to json I see that any element of array has last value I set to object. In this example last is 99999 for Traffic so I got {"views":99999,"urls":99999,"traffic":99999}. What's the reason of such behaviour and how can I get correct values in each element of array?
$this->$_views this accesses not the field named _views but a field with the name stored in variable $_views.
Since you have no such variable the name assumed empty, thus the same name for each of setters or getters.
In short: you need to remove $ after ->:
$this->_urls = $count;
etc.

json_encode empty with no error [duplicate]

This question already has answers here:
PHP class instance to JSON
(5 answers)
Closed 4 years ago.
I got an object. I need to turn into JSON for storage but when I try to encode it into JSON it returns an empty JSON object. When I tried to use json_last_error.
The code I used
echo $payload["sub"];
echo json_encode($user);
echo json_last_error_msg();
The result I get
"102573480781696194937{}No error".
The User class I'm trying to encode
<?php
/**
* Created by PhpStorm.
* User: Student
* Date: 13-4-2018
* Time: 10:40
*/
namespace php;
class User
{
private $isAdmin = false;
private $registeredFood = array();
private $googleID;
private $name;
private $notes = array();
private $email;
/**
* User constructor.
* #param $googleID
*/
public function __construct($googleID)
{
$this->googleID = $googleID;
}
/**
* #return mixed
*/
public function getGoogleID()
{
return $this->googleID;
}
/**
* #return bool
*/
public function isAdmin()
{
return $this->isAdmin;
}
/**
* #param bool $isAdmin
*/
public function setIsAdmin($isAdmin)
{
$this->isAdmin = $isAdmin;
}
/**
* #return array
*/
public function getRegisteredFood()
{
return $this->registeredFood;
}
/**
* #param array $registeredFood
*/
public function setRegisteredFood($registeredFood)
{
$this->registeredFood = $registeredFood;
}
/**
* #return mixed
*/
public function getName()
{
return $this->name;
}
/**
* #param mixed $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* #return array
*/
public function getNotes()
{
return $this->notes;
}
/**
* #param array $notes
*/
public function setNotes($notes)
{
$this->notes = $notes;
}
/**
* #return mixed
*/
public function getEmail()
{
return $this->email;
}
/**
* #param mixed $email
*/
public function setEmail($email)
{
$this->email = $email;
}
}
?>
I hope someone can help me
It is because your class's properties are private.
An example class with only private properties ...
php > class Foo { private $bar = 42; }
php > $obj = new Foo();
do not expose values:
php > echo json_encode($obj);
{}
But an example class with public properties ...
php > class Bar { public $foo = 42; }
php > $objBar = new Bar();
do it!
php > echo json_encode($objBar);
{"foo":42}
\JsonSerializable
PHP provide an'interafce \JsonSerializable that require a method jsonSerialize. This method is automatically called by json_encode().
class JsonClass implements JsonSerialize {
private $bar;
public function __construct($bar) {
$this->bar = $bar;
}
public function jsonSerialize() {
return [
'foo' => $this->bar,
];
}
}
I prefer this solution because is not good to expose publicly properties
serialization and unserialization ...
If you need to serialize and unserialize php object you can ...
php > class Classe { public $pub = "bar"; }
php > $obj = new Classe();
php > $serialized = serialize($obj);
php > $original = unserialize($serialized);
php > var_dump($original);
php shell code:1:
class Classe#2 (1) {
public $pub =>
string(3) "bar"
}
$serialized variable contains O:6:"Classe":1:{s:3:"pub";s:3:"bar";}. As you can see is not a json, but is a format that allow you to recreate original object using unserialize function.
You have a couple of options here.
Option 1: Make your class properties public
Like what sensorario mentioned, change the visibility of your properties so that it is accessible from outside the class, which is where you are calling json_encode.
Option 2: Introduce a method/function within the class to return the encoded JSON object
Have a toJson() function inside your User class.
Of course, there are way more options - such as extending User so that User is not "contaminated", etc.
But yup, the general problem is your private properties.

How to construct constants in yii

I am using Yii for my web application. In this I kept Constants class in model and extended
from CUserIdentity like..
class Constants extends CUserIdentity
{
CONST ACCOUTN_ONE = 1;
CONST ACCOUTN_TWO = 2;
CONST ACCOUTN_THREE = 3;
}
Here I can access constants like Constants::ACCOUTN_ONE and it will return correct result as 1
But when I start construct constants dynamically means..
$type = 'ONE';
$con = "Constants::ACCOUTN_".$type;
echo $con;
It will dispaly as Constants::ACCOUTN_ONE;
I am expecting here 1
Please correct me if any mistake..
$type = 'ONE';
$con = "Constants::ACCOUTN_".$type;
echo Constant($con);
$type = 'ONE'; // You created string
$con = "Constants::ACCOUTN_".$type; // Created other string
echo $con; // Printed it
You just printed string without evaluating it.
Yes, of couse it will dispaly as Constants::ACCOUTN_ONE;
You need to evaluate your code with eval()(bad), or use this scheme:
echo Constant($con);
I do this with
a class for it a while back:
/**
* Lots of pixie dust and other magic stuff.
*
* Set a global: Globals::key($vlaue); #return void
* Get a global: Globals::key(); #return mixed|null
* Isset of a global: Globals::isset($key); #return bool
*
* Debug to print out all the global that are set so far: Globals::debug(); #return array
*
*/
class Globals
{
private static $_propertyArray = array();
/**
* Pixie dust
*
* #param $method
* #param $args
* #return mixed|bool|null
* #throws MaxImmoException
*/
public static function __callStatic($method, $args)
{
if ($method == 'isset') {
return isset(self::$_propertyArray[$args[0]]);
} elseif ($method == 'debug') {
return self::$_propertyArray;
}
if (empty($args)) {
//getter
if (isset(self::$_propertyArray[$method])) {
return self::$_propertyArray[$method];
} else {
return null; //dont wonna trow errors when faking isset()
}
} elseif (count($args) == 1) {
//setter
self::$_propertyArray[$method] = $args[0];
} else {
throw new Exception("Too many arguments for property ({$method}).", 0);
}
}
}

How do I refer to a "this" class member in a function parameter?

I currently have a function where I'm trying to refer to the $id in the class but it doesn't work:
public function getCourseInfo($cid = $this->id, $all = false)
{
}
This is my class:
class Course
{
protected $course;
protected $id;
public function __construct($cid)
{
$id = $cid;
$this->course = $this->getCourseInfo($this->id);
}
public function getCourseInfo($cid = $this->id, $all = false)
{
}
}
You haven't established $this->id yet. :)
wrong
$id = $cid;
right
$this->id = $cid;
You're also missing a closing curly-brace on your class.
Everyone in this thread is giving correct answers but no one gave a full code sample hence I'll post my suggestion:
class Course
{
/**
* #var int
*/
protected $_courseId;
/**
* #var array
*/
protected $_course;
/**
* Class constructor
*
* #param int $courseId Course ID
* #return Course
*/
public function __construct($courseId)
{
$this->_courseId = (int) $courseId;
}
/**
* Get course information
*
* #param bool $all ...
* #return array
*/
public function getCourseInfo($all = false)
{
if ($this->_course === null) {
// use $this->_courseId as needed
$this->_course = ... // populate course info
}
return $this->_course;
}
}
As you'll notice I've omitted the course id parameter from getCourseInfo() simply because it's not needed if you instantiate the class with a course id.
Secondly, I don't think you should call getCourseInfo in the constructor because the information will only be needed at a later point. Also, I added "caching" to the function so that you don't fetch data twice.
Obviously there's a high chance that I could be wrong having not seen your code but I feel this is a better structure of the code.
You need to set the $id first in your constructor.
class Course
{
protected $course;
protected $id;
}
public function __construct($cid)
{
$this->id = $cid;
$this->course = $this->getCourseInfo($id);
}
Try this
public function getCourseInfo($cid = 'default', $all = false)
{
$cid = $cid == 'default' ? $this->id : $cid;
}
Or you need completey change your class
class Course
{
protected $course;
protected $id;
public function __construct($cid)
{
$this->id = $cid;
$this->course = $this->getCourseInfo();
}
public function getCourseInfo($course_id = 0, $all = false)
{
$course_id = !$course_id ? $this->id : $course_id;
//do Somthing with
//return var;
}
No, this isn't possible, as stated on the Function arguments manual page:
The default value must be a constant
expression, not (for example) a
variable, a class member or a function
call.
Instead you could either simply pass in null as the default and update this within your function...
class Course
{
protected $course;
protected $id;
public function __construct($cid)
{
$this->id = $cid;
$this->course = $this->getCourseInfo($this->id);
}
function getCourseInfo($cid = null, $all = false) {
$cid = isset($cid) ? $cid : $this->id;
....
}
}

Which is the best way to display 'flash messages' in kohana v3?

I would like to know the best way to display flash messages in Kohana v3?
Some tutorials or examples would be helpful.
Do you mean like Kohana 2.x's flash session variables?
The latest Kohana supports get_once() which is pretty similar to the old flash session variables.
$session = Session::instance();
$session->set('test', 'Hello, World!');
// The session variable is returned and removed.
$test = $session->get_once('test');
I think the get_once is a great function, but what if you want to keep the data actually separate from the regular data, here's a basic class that overloads "Session" so that you can use "codeigniter" style flashdata calls with any data-store.
<?php defined('SYSPATH') or die('No direct script access.');
abstract class Session extends Kohana_Session {
/**
* This calls the parent Kohana_Session constructor and processes
* new flashdata to flashdata, and flashdata to old flashdata
*
* #param array configuration
* #param string session id
* #return void
* #uses Kohana_Session::__construct
*/
public function __construct(array $config = NULL, $id = NULL)
{
parent::__construct($config,$id);
if(array_key_exists('___of',$this->_data)){
//Remove old Flash data
unset($this->_data['___of']);
}
if(array_key_exists('___flash',$this->_data)){
//Move current last requests flash data to old flash data
$this->_data['___of'] = $this->_data['___flash'];
unset($this->_data['___flash']);
}
if(array_key_exists('___nf',$this->_data)){
//Move Last Requests added data to the flash data
$this->_data['___flash'] = $this->_data['___nf'];
unset($this->_data['___nf']);
}
}
/**
* keeps a variable set in the sessions flashdata array.
*
* $session->set_flashdata('foo', 'bar');
*
* #param string variable name
* #param ...
* #return $this
*/
public function keep_flashdata($k)
{
$args = func_get_args();
if(array_key_exists('___of',$this->_data)){
foreach($args as $key){
if(array_key_exists($key,$this->_data['___of'])){
//So we were going to trash it...
$this->set_flashdata($k,$this->_data['___of'][$key],true);
}
}
}
$this->_data['___nf'][$key] = $value;
return $this;
}
/**
* Set a variable in the sessions flashdata array.
*
* $session->set_flashdata('foo', 'bar');
*
* #param string variable name
* #param mixed value
* #return $this
*/
public function set_flashdata($key, $value, $current=false)
{
if(!array_key_exists('___nf',$this->_data)){
$this->_data['___nf'] = array();
}
$this->_data['___nf'][$key] = $value;
if($current){
if(!array_key_exists('___flash',$this->_data)){
$this->_data['___flash'] = array();
}
$this->_data['flash'][$key] = $value;
}
return $this;
}
/**
* Set a variable by reference in the sessions flashdata array.
*
* $session->bind_flashdata('foo', $foo);
*
* #param string variable name
* #param mixed referenced value
* #return $this
*/
public function bind_flashdata($key, & $value)
{
if(!array_key_exists('___nf',$this->_data)){
$this->_data['___nf'] = array();
}
$this->_data['___nf'][$key] =& $value;
return $this;
}
/**
* Removes a variable in the session array.
*
* $session->delete_flashdata('foo');
*
* #param string variable name
* #param ...
* #return $this
*/
public function delete_flashdata($key)
{
$args = func_get_args();
if(array_key_exists('___nf',$this->_data)){
foreach ($args as $key)
{
if(array_key_exists($key,$this->_data['___nf'])){
unset($this->_data['___nf'][$key]);
}
}
}
return $this;
}
/**
* Get a variable from the sessions flashdata array.
*
* $foo = $session->get_flashdata('foo');
*
* #param string variable name
* #param mixed default value to return
* #return mixed
*/
public function get_flashdata($key, $default = NULL)
{
if(array_key_exists('___flash',$this->_data) && array_key_exists($key,$this->_data['___flash'])){
return $this->_data['___flash'][$key];
} else if(array_key_exists('___nf',$this->_data) && array_key_exists($key,$this->_data['___nf'])){
return $this->_data['___nf'][$key];
}
return $default;
}
/**
* Get and delete a variable from the session array.
*
* $bar = $session->get_once('bar');
*
* #param string variable name
* #param mixed default value to return
* #return mixed
*/
public function get_flashdata_once($key, $default = NULL)
{
$value = $this->get_flashdata($key, $default);
if(array_key_exists($key, $this->_data['___flash'])){
unset($this->_data['___flash'][$key]);
}
if(array_key_exists($key, $this->_data['___nf'])){
unset($this->_data['___nf'][$key]);
}
return $value;
}
}
?>
I realize there was an answer to this, and like i stated before, the get_once method is great and all, but i enjoy auto garbage collection much more.
If you have any improvements on this code, let me know, its been great to me so far.
Have a look at this module, it might be what you are looking for https://github.com/daveWid/message
I've written a really simple class for this once. Check it out below. Usage examples below
class Notice {
private static $session;
private static $initialized = false;
// current notices
private static $notices = array();
function __construct() {
}
static function init() {
self::$session = Session::instance();
self::$notices['current'] = json_decode(self::$session->get_once('flash'));
if(!is_array(self::$notices['current'])) self::$notices['current'] = array();
self::$initialized = true;
}
static function add($notice, $key=null) {
if(!self::$initialized) self::init();
if(!is_null($key)) {
self::$notices['new'][$key] = $notice;
} else {
self::$notices['new'][] = $notice;
}
self::$session->set('flash', json_encode(self::$notices['new']));
return true;
}
static function get($item = null) {
if(!self::$initialized) self::init();
if($item == null) {
return self::$notices['current'];
}
if(!array_key_exists($item, self::$notices['current']))
return null;
return self::$notices['current'][$item];
}
}
Examples (provided this class is saved as APPPATH . 'classes/notice.php'):
Notice::add('Something great has happened!');
Notice::add('Exciting! I\'ve got something to tell you!', 'message');
echo Notice::get('message'); // "Exciting! I've got ..."
foreach(Notice::get() as $message) {
echo $i++ . $message .'<br />';
}
EDIT: funny... for some reason this question popped up somewhere, didn't notice it was a really old one... sorry for that!
I am using https://github.com/synapsestudios/kohana-notices in my project and I am very happy with it.

Categories