what's wrong with my php code with recursive method? - php

Here is my php code, the test method not giving wanted output, and the other weird thing is var_dump('a') print 3 times;
my wanted output is array('qtggccc','qtff23sdf');
public function main()
{
$serverIds = array('ff23sdf','ggccc');
$res = $this->test($serverIds);
var_dump($res);
}
public function test($serverIds,$imgArray = array())
{
if(count($serverIds) > 0){
$media_id = array_pop($serverIds);
$imgUrl= $this->hh($media_id);
array_push($imgArray,$imgUrl);
var_dump($serverIds);
var_dump($imgArray);
$this->test($serverIds,$imgArray);
}
var_dump('a');
return $imgArray;
}
public function hh($m)
{
return 'qt'.$m;
}

Try this:
class MyClass{
private $imgArray = array();
public function main(){
$serverIds = array('ff23sdf','ggccc');
$res = $this->test($serverIds);
print_r($this->imgArray);
}
public function test($serverIds){
if(count($serverIds) > 0){
$media_id = end($serverIds);
$imgUrl= $this->hh($media_id);
array_push($this->imgArray,$imgUrl);
//remove last element
array_pop($serverIds);
$this->test($serverIds);
}
return;
}
public function hh($m){
return 'qt'.$m;
}
}
$obj = new MyClass();
echo '<pre>';
$obj->main();

Why use recursion? You are using a complicated solution for a simple problem.
public function main()
{
$serverIds = array('ff23sdf','ggccc');
$res = array();
//These three lines replace an entire recursive function, making the code easier and saving a chunk of memory once you start using real arrays
foreach ($serverIds as $media_id){
array_unshift($res, $this->hh($media_id));
}
var_dump($res);
}
public function hh($m)
{
return 'qt'.$m;
}

Related

How to use a array in a class which keeps it values and is acessable from outside the class

I am using php 7.4.9 and have a class which reads information from a file. These informations should be all the time availabe from outside the class and it also should possible to modify that array, so that this class can write back these information on request.
I have looked for a while but could not fined a useful solution.
I got the functions working, but the array loose the values from call to call.
Edit 2020/12/12
This is the uses structure of my code
<?php
.......
function show(){
$id3 = ID3::create();
$mp3 = &ID3::$mp3Array;
if($mode == "manual"){
if($file == ""){
return "";
}
$fName = $dir . "/" . $file;
$id3->open($fName);
.......
}else if($mode == "save"){
$fName = $dir . "/" . $file;
$id3->save($fName);
return "Save done!";
}
} // end of show
class ID3{
public static $mp3Array = array();
public static function create(): self {
static $object;
$object = $object ?? new self();
return $object;
}
function open($fName){
$mp3 = self::$mp3Array;
. // $mp3 will be filled
.........
}
function save($fName) {
$mp3 = &ID3::§mp3Array;
error_log("TagSave: ".var_export($mp3, true),0); // is always empty
foreach($mp3 as $key => $value){
........
}
}
} //end of class>
?>
If I try to save the modified array, it is always empty, if show is called again!
I have also implemented the #Logifire proposal 'create'. I got a valid pointer but the arrayis still empty.
Maybe I should point out, that it is web page. The html code sends information (form) back to the php program.
I figured out, that use of global $id3 = NULL; does not work, because the php grogramm will be always called and set the variable again to NULL each time.
I have also implemented the following code on the beginning
<?php
error_log("PHP call",0);
$id3count = 0;
if(array_key_exists("Test_id3",$GLOBALS)){
error_log("GLOBALS[Test_id3] exist!",0);
}else{
error_log("GLOBALS[Test_id3] does not exist!",0);
$GLOBALS['Test_id3'] = "NEW";
}
The $GLOBAL['Test_id3'] never exist, if the programm will be called!
I got the functions working, but the array loose the values from call to call.
As I understand you, your setup is not a long running app, you can not keep state between requests (calls).
But if you are aware of that, the issue may be you have a new instance of the class each time you call it within the same request flow, you may use a singleton if this is the case. I suggest using accessors in your class.
class MyDataList {
private array $my_array = [];
private function __construct()
{
}
public static function create(): self {
static $object;
$object = $object ?? new self();
return $object;
}
public function setArray(array $new_array): void {
$this->my_array = $new_array;
// open, write, close file..
}
public function getArray(): array {
return $this->my_array;
}
}
$my_data_list = MyDataList::create();
Based on your edited question (2020/12/12), I extended the example code:
class MyDataList {
private array $my_array = [];
private $file_path = '';
private function __construct()
{
}
public static function create(string $file_path): self {
static $object;
if ($object === null) {
$object = new self();
$stringified = file_get_contents($file_path) ?: '';
$array = json_decode($stringified, true) ?: [];
$object->file_path = $file_path;
$object->my_array = $array;
}
return $object;
}
public function setArray(array $new_array): void {
$this->my_array = $new_array;
$stringified = json_encode($new_array);
file_put_contents($this->file_path, $stringified);
}
public function getArray(): array {
return $this->my_array;
}
}
$my_data_list = MyDataList::create('/path/to/file');
Note: Be aware, you need to apply error handling
Comment answers:
Is the filepath connected to the array?
Well, you will write your data as JSON to a file each time you "modify" the array via the setArray()
Does it means, that the array is stored into a file and read out each time I try to connect again?
For each request you call create() it will instantiate the internal state of the array based on the stored data in the file. ATM. The file_get_contents call may have been wrapped and only called if the $object was not instantiated. (Now updated in the example)
So I have to call setArray($array); to save the data. I was looking for a soluting to keep the data without an management to save and read the array. Is this not possible with PHP?
Maybe you want to use a session variable to store your data? But it is individual per user and not long lived data - Link: https://www.php.net/manual/en/reserved.variables.session.php
In a standard PHP setup you can not have data/state between requests, but there are solution like Swoole which makes PHP a long running app: https://www.php.net/manual/en/book.swoole.php
I need a possibility to modify the array directly.
Is it a reference to the array you want? https://3v4l.org/OsBC6
class MyDataList {
private array $my_array = [];
private function __construct()
{
}
public static function create(): self {
static $object;
$object = $object ?? new self();
return $object;
}
public function setArray(array &$new_array): void {
$this->my_array = &$new_array;
}
public function getArray(): array {
return $this->my_array;
}
}
There is no easy way to do with PHP!
Finally I use the proposal from Logifire, but had to modified it to fullfill my requirements.
I needed more than 1 array.
One array can ibclude binary data values, which json can't handle. So I have to use base64 for the binary data values.
Here my code:
public array $mp3Array = array();
public array $findArray = array();
private $file_dir = "";
public static function create(string $fileDir): self {
static $object;
if ($object === null) {
$object = new self();
$stringified1 = file_get_contents($fileDir."/mp3Array.obj") ?: '';
$array1 = json_decode($stringified1, true) ?: [];
$stringified2 = file_get_contents($fileDir."/findArray.obj") ?: '';
$array2 = json_decode($stringified2, true) ?: [];
$object->file_dir = $fileDir;
$object->mp3Array = $object->arrayDecode($array1);
$object->findArray = $array2;
}
return $object;
}
private function arrayEncode($arr){
$tmp = [];
foreach($arr as $key => $val){
if(is_array($val)){
$tmp[$key] = $this->arrayEncode($val);
}else if ($key == "data"){
$tmp[$key] = base64_encode($val);
}else{
$tmp[$key] = $val;
}
}
return $tmp;
}
private function arrayDecode($arr){
$tmp = [];
foreach($arr as $key => $val){
if(is_array($val)){
$tmp[$key] = $this->arrayDecode($val);
}else if ($key == "data"){
$tmp[$key] = base64_decode($val);
}else{
$tmp[$key] = $val;
}
}
return $tmp;
}
public function setMp3(array $new_array): void {
$this->mp3Array = $new_array;
$stringified = json_encode($new_array);
file_put_contents($this->file_dir."/mp3Array.obj", $stringified);
}
public function saveMp3(): void {
$base64 = $this->arrayEncode($this->mp3Array);
$stringified = json_encode($base64);
file_put_contents($this->file_dir."/mp3Array.obj", $stringified);
}
public function setFind(array $new_array): void {
$this->findArray = $new_array;
$stringified = json_encode($new_array);
file_put_contents($this->file_dir."/findArray.obj", $stringified);
}
public function saveFind(): void {
$stringified = json_encode( $this->findArray);
file_put_contents($this->file_dir."/findArray.obj", $stringified);
}

PHP Multiple thread remove duplicated

I want to create a class that can remove duplicate items but uses pthreads I have an array with some duplicated lines and put them into a thread each line and here is my code.
header("Content-type: text/plain");
class Arr {
public $my_variable = array();
public function add($value) {
$this->my_variable[$value] = 1;
return $this->my_variable;
}
public function check($value)
{
if(isset($this->my_variable[$value])){
return true;
} else {
return false;
}
}
}
class workerThread extends Thread
{
public $arr;
public function __construct($i){
$this->i = str_replace("\r","",$i);
$this->i = str_replace("\n","",$this->i);
$this->arr = new Arr();
}
public function run()
{
if($this->arr->check($this->i)!==true)
{
$add = $this->arr->add($this->i);
echo date('H:i:s') . ' - '. $this->i . " - (".count($add).")\r\n";
}
}
}
$mailExp = array(
'talunays#gmail.com',
'talunays#gmail.com',
'talunays#gmail.com',
'talunays#gmail.com',
'talunays#gmail.com'
);
$total = count($mailExp);
for($i=0;$i<$total-1;$i++)
{
$workers[$i]=new workerThread($mailExp[$i]);
$workers[$i]->start();
}
But it doesn't work, duplicate lines still there and cannot be removed...
You should use construct only to set your private $this variables.
Make the logic inside the run function and use array_unique.
Let the workers come back with join() and retrieve the unduplicated arrays at this point.

PHP Optional Function Parameter Set to Reference to Existing Object

I don't even know if this is possible but I'm trying to set an optional value to an existing object.
Here is a simplified version of the code I'm trying.
<?php
class configObject {
private $dataContainer = array();
public function set($dataKey, $dataValue) {
$this->dataContainer[$dataKey] = $dataValue;
return TRUE;
}
public function get($dataKey) {
return $this->dataContainer($dataKey);
}
$this->set('someValue', 'foobar');
} //End configObject Class
function getPaginationHTML($c = &$_config) {
$someOption = $c->get('someValue');
// Do other stuff
return $html;
}
$_config = new configObject();
$html = getPaginationHTML();
?>
I'm getting the error:
syntax error, unexpected '&' in
Any help is appreciated, again I'm not sure if it's even possible to do what I'm trying to do so sorry for being a noob.
Thanks
example with the decorator pattern:
class ConfigObject {
private $dataContainer = array();
public function set($dataKey, $dataValue) {
$this->dataContainer[$dataKey] = $dataValue;
return true;
}
public function get($dataKey) {
return $this->dataContainer[$dataKey];
}
}
class ConfigObjectDecorator {
private $_decorated;
public function __construct($pDecorated) {
$this->_decorated = $pDecorated;
}
public function getPaginationHTML($dataKey) {
$someOption = $this->get($dataKey);
// Do other stuff
$html = '<p>' . $someOption . '</p>';
return $html;
}
public function set($dataKey, $dataValue) {
return $this->_decorated->set($dataKey, $dataValue);
}
public function get($dataKey) {
return $this->_decorated->get($dataKey);
}
}
class ConfigFactory {
public static function create () {
$config = new ConfigObject();
return new ConfigObjectDecorator($config);
}
}
$config = ConfigFactory::create();
if ($config->set('mykey', 'myvalue'))
echo $config->getPaginationHTML('mykey');
Note that can easily rewrite ConfigFactory::create() to add a parameter to deals with other types of decoration (or none).

Proper array(&$this) syntax with arguments

Take the following code example:
<?php
class A {
public function aa() {
$output = (array(&$this, 'ab'), $post_id);
return $output;
}
public function ab( $post_id ) {
//do stuff
}
}
?>
What's the correct way to call method ab that contains additional arguments like $post_id?
I know that the $output line doesn't work, but that's the line I'm stuck on.
Thanks.
Just this way:
$output = $this->ab($post_id);
Try this . May be this will help.
<?php
class A {
public function aa() {
$args = func_get_args();
$output = call_user_func_array(array($this,'ab'),$args);
// But this way the "ab" function have to be private
// Or you can simply do $output = $this->ab($post_id)
return $output;
}
public function ab( $post_id ) {
//do stuff
}
}
$a = new A();
$a->aa(162);
?>

How to use this function within a PHP class?

class io_dz {
/**
* Compress
*/
public static function Set($Data) {
if ($Data) {
$Out = addslashes(gzcompress(serialize($Data), 9));
} else {
$Out = FALSE;
}
return $Out;
}
/**
* Decompress
*/
public static function Get($Data) {
if ($Data) {
$Out = unserialize(gzuncompress(stripslashes($Data)));
} else {
$Out = FALSE;
}
return $Out;
}
}
it's a simple compress before serialize function. How would I call this function and use it on $data
I currently have:
$dataCompressor = new $io_dz();
$cdata = $dataCompressor->Set($data);
But it doesn't seem to work, any help would be appreciated!
Thank you!
You declared the method as static, you don't need to instanciate the object to access them.
Try only:
$cdata = io_dz::Set($data);
If you need more information about static method/attribute, you can check the PHP Manual that has quite a few easy to understand examples: http://php.net/manual/en/language.oop5.static.php
$cdata = $dataCompressor::Set($data);
You need :: because you made them static. If they weren't static and were only public functions it would be ->

Categories