Transient data type in php - php

Is there any data type in php that works like #transient of JPA(Java)?
Something like:
#transient
private $my_var;

Not really, but you can define your own serialization method and include or exclude whatever you want.
Example from the documentation: http://php.net/serializable
<?php
class obj implements Serializable {
private $data;
public function __construct() {
$this->data = "My private data";
}
public function serialize() {
return serialize($this->data);
}
public function unserialize($data) {
$this->data = unserialize($data);
}
public function getData() {
return $this->data;
}
}
$obj = new obj;
$ser = serialize($obj);
var_dump($ser);
$newobj = unserialize($ser);
var_dump($newobj->getData());
?>

Related

How to Execute/Trigger a method before an ArrayObject is accessed with a certain Key

I have a php ArrayObject
class myObject extends ArrayObject
{
public function __construct()
parent::__construct(array(), ArrayObject::ARRAY_AS_PROPS);
// populate
$this->populateArray();
{
private function populateArray() {
$this['hello'] = null;
$this['hello2'] = null;
$this['hello3'] = null;
}
}
Now when I access the hello element in this way
$myArray = new myObject();
$value = $myArray['hello'];
I would like to trigger a method in the myObject that assigns to $myArray another object before being read.
My medhod should look like this.
private function method($value) {
$this[$value] = new class2();
}
Is there a way to achieve this ?
You can overwritte offsetGet function like this:
public function offsetGet($index) {
$this->someMethod();
return parent::offsetGet($index);
}
private function someMethod()
{
echo "triggered";
}
Then when you run
$x = new myObject;
echo $x['hello'];
Will output
triggered
In someMethod() you can do whatever you want.

Dependency injection an object without all of its methods

so a class:
class ToBeUsed
{
private $a;
public function setSomething($a)
{
$this->a = $a;
}
public function getSomething()
{
return $this->a;
}
}
its beign created and updated:
$obj = new ToBeUsed();
$obj->setSomething('a');
and passed to another object
class UseIt
{
/**
* #var ToBeUsed
*/
private $obj;
public function __construct(ToBeUsed $obj)
{
$this->obj = $obj;
}
public function work()
{
$this->obj->getSomething();
$this->obj->setSomething(); //// !!!!! THIS IS BAD!
}
}
now a classic DI example, except that the passed object should be "dulled" - only some methods are allowed to use. E.g. getSomething() is allowed to use, but setSomething() is not. What pattern / practice can get away with it? There used to be friend classes is C but its Php...
class ToBeUsed
{
private $a;
public function setSomething($a)
{
$dbg = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS,2);
if(count($dbg) > 1){
return;
}
$this->a = $a;
}
public function getSomething()
{
return $this->a;
}
}
class UseIt
{
/**
* #var ToBeUsed
*/
private $obj;
public function __construct(ToBeUsed $obj)
{
$this->obj = $obj;
}
public function work()
{
echo $this->obj->getSomething().PHP_EOL; // a
$this->obj->setSomething('b'); // this does nothing
echo $this->obj->getSomething().PHP_EOL; // a
}
}
$obj = new ToBeUsed();
$obj->setSomething('a');
$obj2 = new UseIt($obj);
$obj2->work();
Alternatively, you can perform more complex checks on debug_backtrace() output.
I would probably do something with Interfaces, it doesn't prevent a method form being used. But "they" (whoever they is) would be using it outside of the Interface for $obj.
Like this:
class ToBeUsed implements ToBeUsedInterface
{
private $a;
public function getSomething()
{
return $this->a;
}
public function setSomething($a)
{
$this->a = $a;
}
}
interface ToBeUsedInterface{
public function getSomething();
}
class UseIt
{
/**
* #var ToBeUsed
*/
private $obj;
public function __construct(ToBeUsedInterface $obj)
{
$this->obj = $obj;
}
public function work()
{
$this->obj->getSomething();
$this->obj->setSomething(); //This now exists outside of the interface for $obj
}
}
In terms of IDE's this would prevent the methods from auto-completing as well.
The only other thing I can think of, ( besides the other answer ) would be to set the method to protected and then use ReflectionMethod to change the viability, when you want to use it.
Another Option, is Using Reflection
class ToBeUsed
{
private $a;
public function getSomething()
{
return $this->a;
}
protected function setSomething($a)
{
$this->a = $a;
}
}
$ToBeUsed = new ToBeUsed();
$ReflectionMethod = new ReflectionMethod($ToBeUsed, 'setSomething');
$ReflectionMethod->setAccessible(true);
$ReflectionMethod->invoke($ToBeUsed, 'foo');
echo $ToBeUsed->getSomething();
Outputs:
foo
You can see it live here
And Obviously sense it's protected under normal conditions, it could not be used inside UseIt. If I was going to use this for any amount of code, I would extend or wrap the Reflection class. Just to make the call a bit more concise, like this:
class MyReflector
{
public static function invoke($class, $method, ...$args)
{
$ReflectionMethod = new ReflectionMethod($class, $method);
$ReflectionMethod->setAccessible(true);
$ReflectionMethod->invokeArgs($class, $args);
}
}
$ToBeUsed = new ToBeUsed();
MyReflector::invoke($ToBeUsed,'setSomething', 'foo');
Please note I got all fancy with the variadic ...$arg which is for PHP 5.6+ it just lets you do
MyReflector::invoke($ToBeUsed,'setSomething', 'foo', 'bar');
And $args would be ['foo','bar'] in the first example it's just ['foo'] which can be used for invokeArgs for the second argument which takes an array of arguments to pass on to the actual method.

passing variables from a protected function to a public function inside the same class in php

I have a class and two functions inside it as follows:
class MyClassName
{
protected function myFunction1()
{
// some code here
return $something;
}
public function myFunction2()
{
// some code here
return $somethingElse;
}
}
What I need to do is define a variable in myFunction1() and then use it in myFunction2(). What is the best practice to do that?
class MyClassName
{
public $var = 0;
protected function myFunction1()
{
// some code here
$this->var = ...;
return $something;
}
public function myFunction2()
{
// some code here
echo $this->var;
return $somethingElse;
}
}
Actually vars should be defined out of the function and then set a value. Then can be modified over all the script, by doing this->var
Make it a class property
class MyClassName
{
private $property;
public function __construct() {
$this->myFunction1();
}
protected function myFunction1()
{
// some code here
$this->property = 'an apple';
}
public function myFunction2()
{
// some code here
return $this->property;
}
}
Now test it:
$my_class = new MyClassName();
$something = $my_class->myFunction2();
echo $something;

PHP array is null after passing to function

So I have a problem I have an array that is passes to setData function
after that I call getE that suppose to return the array but instead I'm getting Null what am I doing wrong?
<?php
class Se {
public $data1;
public function setData(array $data){
if (empty($data)) {
throw new InvalidArgumentException('The name of an employee cannot be empty.');
}
$data1 = $data;
$data1 = array_values($data1);
var_dump($data1);
}
public function getE(){
return $data1[0];
}
}
$tmpaaa= array('3333','222');
$ttt = new Se();
$ttt->setData($tmpaaa);
echo $ttt->getE();
So my revised code looks like this now
class Se {
public $data1;
public function setData(array $data)
{
if (empty($data))
{
throw new InvalidArgumentException('The name of an employee cannot be empty.');
}
$this->data1 = $data;
}
public function getE()
{
return $this->$data1[0];
}
};
$tmpaaa= array('3','2');
$ttt = new Se();
$ttt->setData($tmpaaa);
echo $ttt->getE();
?>
In order to access class instance properties from within the class, you need to prefix the variable name with $this. See http://php.net/manual/language.oop5.properties.php
To fix your problem, change this in setData
$data1 = $data;
$data1 = array_values($data1);
var_dump($data1);
to this
$this->data1 = array_values($data);
var_dump($this->data1);
and getE to
public function getE(){
return $this->data1[0];
}
Update
As it appears the $data1 property is required in Se, I'd set it in the constructor, eg
public function __construct(array $data) {
$this->setData($data);
}
and instantiate it with
$ttt = new Se($tmpaaa);
echo $ttt->getE();
It is also recommended not closing the php tag in a class file, this prevents space issues.
<?php
class Se {
public $data1;
public function setData(array $data)
{
if (empty($data))
{
throw new InvalidArgumentException('The name of an employee cannot be empty.');
}
$this->data1 = array_values($data); //you error was here, no need to to assign $data twice so I deleted top line.
}
public function getE()
{
return $this->data1[0];
}
}
$tmpaaa = array('3333','222');
$ttt = new Se();
$ttt->setData($tmpaaa);
echo $ttt->getE();

PHP Object+Collections to JSON Using json_encode

In PHP, I have a product object that contains a collection of attributes. json_encode produces this:
{"id":"123","name":"abc","attributes":{"attributes":[{"key":"sku","value":"xyz"}]}}
"attributes" listed twice is redundant. What's the best way of structuring object collections so that the json is clean?
class Product {
public $id;
public $name;
public $attributes;
public function __construct()
{
$this->attributes = new Attributes();
}
public function get($id)
{
$this->id = "123";
$this->name = "abc";
$attribute = new Attribute("sku", "xyz");
$this->attributes->add($attribute);
}
}
class Attributes
{
public $attributes;
public function __construct()
{
$this->attributes = array();
}
public function add($attribute)
{
array_push($this->attributes, $attribute);
}
}
class Attribute
{
public $key;
public $value;
public function __construct($key, $value)
{
$this->set($key, $value);
}
}
I would just use an associative array.
class Product {
...
public $attributes=array();
...
public function get($id)
{
...
$this->attributes["sku"]="xyz";
$this->attributes["foo"]="bar";
}
}
json_encode() should produce something like this:
{"id":"123","name":"abc","attributes":{"sku":"xyz","foo":"bar"}}
OR using variable variables:
class Attributes
{
public function add($key,$value)
{
$this->{$key}=$value;
}
public function drop($key)
{
unset($this->{$key});
}
}
$a=new Attributes();
$a->add('sku','xyz');
$a->add('foo','bar');
echo json_encode($a).'<br>';
$a->drop('sku');
echo json_encode($a).'<br>';
Output:
{"sku":"xyz","foo":"bar"}
{"foo":"bar"}
You can give your classes a custom json encoding format by implementing JsonSerializable.
In your case you'll just need to have Attributes implement that and give it a jsonSerialize method which returns $this->attributes.

Categories