I want to force $_SESSION behave like object using custom session handler. Code as follows,
$_SESSION = [
'user' => [
'id' => '7',
'name' => 'James',
'lastname' => 'Bond',
'login' => '007',
'pass' => 'qwe7fyqw9mhev8qhr',
],
'kill' => [
'Mr_Muscle' => [
'status' => 'alive',
],
'Joe_Black' => [
'status' => 'dead',
]
],
];
$session = new Session();
echo $session->user->name;
$session->kill->Mr_muscle->status = 'dead';
$session->save();
I did it almost but I get warning:
Warning: Creating default object from empty value in /var/www/project/mvc/bootstrap.php on line 80
when I'm trying to create new value, in this case:
$session->kill->Dr_Quinn->status = 'dead';
Value will be created but I don't want to hide this warning, I want to do away with it.
class Session
{
public function __construct()
{
foreach ($_SESSION as $key => $value)
{
$this->{$key} = $value;
}
}
public function __set($name, $value)
{
$this->$name = $this->arrayToObject($value);
}
private function arrayToObject($array) {
if (!is_array($array)) {
return $array;
}
$object = new stdClass();
if (is_array($array) && count($array) > 0) {
foreach ($array as $name=>$value) {
$name = strtolower(trim($name));
if (!empty($name)) {
$object->$name = $this->arrayToObject($value);
}
}
return $object;
}
else {
return FALSE;
}
}
public function save()
{
$_SESSION = json_decode(json_encode(get_object_vars($this)), true);
}
How to fix it?
Just do
if (!isset($session->kill->Mr_muscle))
$session->kill->Mr_muscle = new stdClass();
$session->kill->Mr_muscle->status = 'dead';
to avoid this warning.
Related
what I want to do is to print the data with foreach, but whatever I have done, it prints the last element and not the other one,
where am i going wrong?
I want "PartyIdentification" to return up to each element.
I don't understand if I'm making a mistake in get and sets. Is there a short solution? I want to print more than one property.
the result of my output
i want to do
$aa = array(
0 => ['ID' => ['val' => '4000068418', 'attrs' => ['schemeID="VKN"']]],
1 => ['ID' => ['val' => '12345678901', 'attrs' => ['schemeID="TICARETSICILNO"']]],
2 => ['ID' => ['val' => '132546555', 'attrs' => ['schemeID="MERSISNO"']]]
);
$invoice_AccountSupplierParty_Party = new \Pvs\eFaturaUBL\Party();
$invoice_AccountSupplierParty_Party->PartyIdentification = InvoiceBuilder::getasd($aa);
public static function getasd(array $data)
{
$asd = new Olusturma();
$date = array();
foreach ($data as $datum) {
$asd->getID($data);
}
return $asd->getResult();
}
namespace App\Support\Invoice;
class Olusturma
{
public $contactDetails = array();
public function __construct()
{
$this->contactDetails = new \Erkan\eFaturaUBL\PartyIdentification();
}
public function setOlusturma(): Olusturma
{
return $this;
}
public function getID($data)
{
foreach ($data as $row => $innerArray) {
foreach ($innerArray as $innerRow => $value) {
$this->setID($value);
}
}
return $this;
}
public function setID($data): Olusturma
{
$this->contactDetails->ID = $data;
return $this;
}
public function getResult(): \Erkan\eFaturaUBL\PartyIdentification
{
return $this->contactDetails;
}
I have an array of elements with the same structure each.
Here's an example :
<?php
$arr =
[
[
"el_name" => "abcd",
"el_data" => "raw_dataè_15264df156g18df",
],
[
"el_name" => "efgh",
"el_data" => "raw_data_sd25g",
],
[
"el_name" => "ijkl",
"el_data" => "raw_data_dfdfgn48",
],
[
"el_name" => "mnop",
"el_data" => "raw_data_²545",
],
];
$new_el = [
"el_name" => "efgh",
"el_data" => "raw_data_sd25g",
];
I want to add $new_el only if it's not already present in $arr. It'd be handy if php had a array_element_exists() function ;-)
For the sake of the question I tried this:
$exists = false;
foreach($arr as $el) {
$equal=true;
foreach(array_keys($el) as $key) {
if(isset($new_el[$key]) && $new_el[$key] === $el[$key]) {
null;
//equality
} else {
$equal = false;
}
}
if($equal === true) {
$exists = true;
break;
}
}
if($exists === true ) {
echo '$new_el already exists in $arr' . PHP_EOL;
} else {
echo '$new_el doesn\'t still exists in $arr' . PHP_EOL;
$arr[] = $new_el;
}
Do you think there are more efficient, 'simpler' ways ?...
You are probably looking for in_array() function.
in_array($new_el, $arr);
returns true.
function array_element_exists($new_el,$arr){
$found = array_filter($arr, function($arr) use ($new_el) {
return $arr['el_name'] === $new_el['el_name'] &&
$arr['el_data'] === $new_el['el_data'];
});
return $found;
}
$exsist = ["el_name" => "efgh","el_data" => "raw_data_sd25g"];
$notExsist = ["el_name" => "newName","el_data" => "newData",];
//will not be added since it is already exist
if (!array_element_exists($exsist,$arr)) {
$arr[] = $exsist;
}
//will be added because it is new and not exist in `$arr`
if (!array_element_exists($notExsist,$arr)) {
$arr[] = $notExsist;
}
I need the output in following format:
<ns1:CustomerDetails>
<_cd:Name>My Name</_cd:Name>
<_pd:PersonalDetails>
<_bio:Age>20</_bio:Age>
</_pd:PersonalDetails>
<_cd:SomeVar>Var Value</_cd:SomeVar>
</ns1:CustomerDetails>
I can create an array in any format, For example:
$vars['ns1']['CustomerDetails']['_cd']['Name']="MY Name";
$vars['ns1']['CustomerDetails']['_pd']['PersonalDetails']['_bio']['Age']="20";
$vars['ns1']['CustomerDetails']['_cd']['SomeVars']="Var Value";
I have used the following code:
class ArrToXml{
static function parse($arr){
$dom = new DOMDocument('1.0');
self::recursiveParser($dom,$arr,$dom);
return $dom->saveXML();
}
private static function recursiveParser(&$root, $arr, &$dom){
foreach($arr as $key => $item){
if(is_array($item) && !is_numeric($key)){
$node = $dom->createElement($key);
self::recursiveParser($node,$item,$dom);
$root->appendChild($node);
}elseif(is_array($item) && is_numeric($key)){
self::recursiveParser($root,$item,$dom);
}else{
$node = $dom->createElement($key, $item);
$root->appendChild($node);
}
}
}
}
$xmlRequest = ArrToXml::parse($requestArray);
... But I am not getting namespace values. What changes I should do in the code to get my desired values?
The data array does not allow to differentiate between the namespace indicators and the tag names. Both are just keys. One solution would be to use QCNames as keys:
$data = [
'c:CustomerDetails' => [
'cd:Name' => "MY Name",
'pd:PersonalDetails' => [
'bio:Age' => "20"
],
'cd:SomeVars' => "Var Value",
]
];
Additionally you would need namespace information for the indicators:
$xmlns = [
'c' => ['prefix' => 'ns1', 'uri' => 'urn:c'],
'cd' => ['prefix' => '_cd', 'uri' => 'urn:cd'],
'pd' => ['prefix' => '_pd', 'uri' => 'urn:pd'],
'bio' => ['prefix' => '_bio', 'uri' => 'urn:bio']
];
I suggest including a prefix to decouple the code.
Appending the data directly to the DOM is a better, less complex solution most of the time. I typically define an interface for this and implement it in the different data and serializer classes:
interface XMLAppendable {
public function appendTo(DOMNode $parentNode);
}
A mapper for the data array could implement the interface as well. It would need the data
array and information about the namespaces.
class ArrayAppender implements XMLAppendable {
private $_data;
private $_xmlns;
public function __construct(array $data, array $xmlns = []) {
$this->_data = $data;
$this->_xmlns = $xmlns;
}
public function appendTo(DOMNode $parentNode) {
$this->appendArrayTo($parentNode, $this->_data);
}
private function appendArrayTo(DOMNode $parentNode, array $data) {
$document = $parentNode instanceof DOMDocument
? $parentNode : $parentNode->ownerDocument;
foreach ($data as $key => $value) {
if (FALSE !== strpos($key, ':')) {
[$prefix, $tagName] = explode(':', $key);
if (isset($this->_xmlns[$prefix])) {
$namespace = $this->_xmlns[$prefix];
} else {
throw new UnexpectedValueException(
'Can not find namespace for '.$prefix
);
}
} else {
$namespace = ['prefix' => '', 'uri' => ''];
$tagName = $key;
}
$parentNode->appendChild(
$child = $document->createElementNS(
$namespace['uri'],
$namespace['prefix'] ? $namespace['prefix'].':'.$tagName : $tagName
)
);
if (is_array($value)) {
$this->appendArrayTo($child, $value);
} else {
$child->textContent = (string)$value;
}
}
}
}
Usage demo:
$document = new DOMDocument();
$arrayToXML = new ArrayAppender($data, $xmlns);
$arrayToXML->appendTo($document);
$document->formatOutput = TRUE;
echo $document->saveXML();
Output:
<?xml version="1.0"?>
<ns1:CustomerDetails xmlns:ns1="urn:c">
<_cd:Name xmlns:_cd="urn:cd">MY Name</_cd:Name>
<_pd:PersonalDetails xmlns:_pd="urn:pd">
<_bio:Age xmlns:_bio="urn:bio">20</_bio:Age>
</_pd:PersonalDetails>
<_cd:SomeVars xmlns:_cd="urn:cd">Var Value</_cd:SomeVars>
</ns1:CustomerDetails>
In laravel 8 app with laravelcollective/html 6.2 and php7.4 I need to fill selection input with method in model :
private static $userStatusLabelValueArray = ['N' => 'New(Waiting activation)', 'A' => 'Active', 'I' => 'Inactive', 'B'=>'Banned'];
public static function getUserStatusValueArray($key_return = true): array
{
$resArray = [];
foreach (self::$userStatusLabelValueArray as $key => $value) {
echo '<pre>$key::'.print_r($key,true).'</pre>';
echo '<pre>$value::'.print_r($value,true).'</pre>';
if ($key_return) {
$resArray[] = ['key' => $key, 'label' => $value];
} else {
$resArray[$key] = $value;
}
}
return $resArray;
}
debugging I see that $key has valid string value but when $key_return is false I got array with
keys 0...3, not 'N', 'A' as I expected.
Which way is valid ?
Thanks!
I have code like this, that initialize config
$this->config = array(
'users' => array(
array('name' => 'admin',
'password' => $password
)
),
'tokens' => array(),
'sessions' => array(),
);
that I'm saving to a file using json_encode($this->config) and later I load it using
json_decode(file_get_contents('file.json'));
it create nested objects, I would like to have this nested object when I initialize and the config, is there a way to create this nested object other then this?
$this->config = json_decode(json_encode($this->config));
You can alternatively use this function
<?php
function arrayToObject($array) {
if(!is_array($array)) {
return $array;
}
$object = new stdClass();
if (is_array($array) && count($array) > 0) {
foreach ($array as $name=>$value) {
$name = strtolower(trim($name));
if (!empty($name)) {
$object->$name = arrayToObject($value);
}
}
return $object;
}
else {
return FALSE;
}
}
?>
I decide to use this function instead
function object($array) {
$object = new stdClass();
foreach ($array as $k => $v) {
$object->$k = $v;
}
return $object;
}
and explicitly call it for assoc arrays
$this->config = object(array(
'users' => array(
object(array(
'name' => 'admin',
'password' => $password
))
),
'tokens' => array(),
'sessions' => array(),
));
EDIT recursive code
function is_assoc($array) {
if (!is_array($array)) {
return false;
} else {
$keys = array_keys($array);
return !is_numeric($keys[0]);
}
}
function object($array) {
if (is_assoc($array)) {
$object = new stdClass();
foreach ($array as $k => $v) {
$object->$k = object($v);
}
return $object;
} else {
return $array;
}
}