Vlada Katlinskaya
Vlada Katlinskaya

Reputation: 1033

Passing an argument to callback function working on an array

I'm using an external class (Zebra_cURL) to execute multiple HTTP GET requests. It worked in the following way:

$items = array(
    0=>array('url' => 'url0'),
    1=>array('url' => 'url1'),
    2=>array('url' => 'url2'),
    3=>array('url' => 'url3'),
);
$curl = new Zebra_cURL();
$curl->get(array_column($urls,'url'),'scan_item',$moreimfo);

function scan_item($result,$moreimfo){
    $items[$key]['size'] = strlen($result->body);
}

So my callback should fill up my $items array with more info for each url (in my case - size of the page). So there is a missing $key variable.

This class supports extra parameters in the callbacks ($moreimfo in my case). BUT as I understand the data passing to each callback will be always the same.

$result object containing the original url info ($result->info['url']). So I COULD use it to find needed array element. However this looks too inefficient in case the size of an array will be big enough.

I think that I should find how to pass an array member key information for EACH callback execution. Is it possible without modifying the original class?

Upvotes: 1

Views: 549

Answers (2)

VolkerK
VolkerK

Reputation: 96159

If you use the url as key in the $items array the solution could be something like

<?php
$items = [
  'url0'=>array('url' => 'url0'),
  'url1'=>array('url' => 'url1'),
  'url2'=>array('url' => 'url2'),
  'url3'=>array('url' => 'url3'),
];
$curl = new Zebra_cURL();
$curl->get(
    array_keys($items),
    function($result) use (&$items) {
        $key = $result->info['url'];
        $items[$key]['size'] = strlen($result->body);
    }
);

using an anymous function that "Imports" the $items array via reference.

Upvotes: 2

tillz
tillz

Reputation: 2108

While it doesn't solve the original problem of passing a reference to the according array element to the callback, the following should be very fast (as noted in the comments, PHP Arrays are implemented using a hashtable).

$items = array(
    0=>array('url' => 'url0'),
    1=>array('url' => 'url1'),
    2=>array('url' => 'url2'),
    3=>array('url' => 'url3'),
);

$lookup=array();
foreach($lookup as $k=>$v) {
    $lookup[$v['url']]=$k;
}

$curl = new Zebra_cURL();
$curl->get(array_column($urls,'url'),'scan_item',$moreimfo);

function scan_item($result,$moreimfo){
    global $lookup,$items;
    $items[$lookup[$result->info['url']]]['size'] = strlen($result->body);
}

Probably you may consider using an OOP-approach, with the callback as a method, then the global-izing of the arrays shouldn't be necessary if you use $this->anyMember

Upvotes: 1

Related Questions