accessing objects data in an array - php

If someone has some help/advice about how to tackle this problem I'd really appreciate it. I've created a metasearch engine that for all intensive purposes works ok, but my code is pretty breakable! The following code is a sample var_dump of the array of objects - searchEngineArray. I want to store the results of each search engine in an array, but it needs to be in some kind of generic loop that (A). won't break if one search engine doesn't return results and (B). can easily accommodate additional search engines.
object(BingSearch)[1]
private 'formatted_query' => string 'england' (length=7)
public 'search_results' =>
array
0 =>
array
'title' => string 'England - Wikipedia, the free encyclopedia' (length=42)
'url' => string 'http://en.wikipedia.org/wiki/England' (length=36)
'score' => int 30
1 =>
array
'title' => string 'BBC News - England' (length=18)
'url' => string 'http://www.bbc.co.uk/news/england/' (length=34)
'score' => int 28
2 =>
array
'title' => string 'The FA - The website for the English football association, The FA ...' (length=69)
'url' => string 'http://www.thefa.com/' (length=21)
'score' => int 26
object(BlekkoSearch)[2]
private 'formatted_query' => string 'england' (length=7)
public 'search_results' =>
array
0 =>
array
'title' => string '<strong>England</strong> - Wikipedia' (length=36)
'url' => string 'http://en.wikipedia.org/wiki/England' (length=36)
'score' => int 25
1 =>
array
'title' => string 'The official site of Visit <strong>England</strong> - The <strong>England</strong> Tourist Board' (length=96)
'url' => string 'http://www.enjoyengland.com/' (length=28)
'score' => int 23
2 =>
array
'title' => string 'Arts Council <strong>England</strong> - Arts Council' (length=52)
'url' => string 'http://www.artscouncil.org.uk/' (length=30)
'score' => int 21
object(EntirewebSearch)[3]
private 'formatted_query' => string 'england' (length=7)
public 'search_results' =>
array
0 =>
array
'title' => string 'Arts Council England | Arts Council' (length=35)
'url' => string 'http://www.artscouncil.org.uk/' (length=30)
'score' => int 20
1 =>
array
'title' => string 'Sport England ' (length=14)
'url' => string 'http://www.sportengland.org/' (length=28)
'score' => int 18
2 =>
array
'title' => string 'Bank of England ' (length=16)
'url' => string 'http://www.bankofengland.co.uk/' (length=31)
'score' => int 16
I have it working to an extent, but its just not good code really. Heres how it works at the moment, has anyone got any ideas on how to create a more generic way of storing the information?
public function storeResults($searchEnginesArray)
{
//The following is very bad
//$blekko_Array = "";
//$bing_Array = "";
//$entireweb_Array = "";
for($x=0; $x<sizeof($searchEnginesArray); $x++)
{
var_dump($searchEnginesArray[$x]);
/*switch ($searchEnginesArray[$x]->getEngineName()) {
case "Bing":
$bing_Array = $searchEnginesArray[$x]->getResults();
break;
case "Blekko":
$blekko_Array = $searchEnginesArray[$x]->getResults();
break;
case "Entireweb":
$entireweb_Array = $searchEnginesArray[$x]->getResults();
break;
default:
echo "Error: Unexpected Search Engine : ".$searchEnginesArray[$x]->getEngineName(). " Expects [Bing/Blekko/Entireweb]";
} */
}

<?
public function storeResults($searchEnginesArray) {
for($i=0;$i<count($searchEnginesArray);$i++) {
$result = $searchEnginesArray[$i]->getResults();
// Ignore engines with empty results
if( !empty($result) ) {
$results[ $searchEnginesArray[$i]->getEngineName() ] = $result;
}
}
// create an array for every engine, are you sure it's needed?
extract($results, EXTR_SKIP);
}
?>

Related

MYSQL PHP Array grouping

Having trouble wrapping my head around this conceptually. Still new to this. Basically I have this return from my database :
array (size=456)
0 =>
object(stdClass)[358]
public 'id' => string '2432' (length=4)
public 'symbol' => string '.AMLP' (length=14)
public 'last' => string '0.01' (length=4)
public 'volume' => string '3690' (length=4)
public 'the_date' => string '2019-09-13' (length=10)
public 'the_screener' => string '1' (length=1)
public 'notes' => string 'notes here' (length=149)
1 =>
object(stdClass)[726]
public 'id' => string '2417' (length=4)
public 'symbol' => string '.ARCC' (length=14)
public 'last' => string '2.25' (length=4)
public 'volume' => string '1633' (length=4)
public 'the_date' => string '2019-09-13' (length=10)
public 'the_screener' => string '1' (length=1)
public 'notes' => string 'notes' (length=60)
2 =>
object(stdClass)[726]
public 'id' => string '2447' (length=4)
public 'symbol' => string '.ARCC' (length=14)
public 'last' => string '2.25' (length=4)
public 'volume' => string '1633' (length=4)
public 'the_date' => string '2019-09-12' (length=10)
public 'the_screener' => string '1' (length=1)
public 'notes' => string 'notes here 3' (length=60)
3 =>
What I'm trying to do with PHP is create an object/array that I can work with that displays these items like
AMLP 1 found on dates 2019-09-13
ARCC 2 found on dates 2019-09-13, 2019-09-12
In the end I would display these in a table, but conceptually this is what I'm trying to do.
I've tried creating an array in my foreach I use to display this information in a table, but I was thinking about it and it's probably better to just use the same query data and break it down separately.
So I'd like to create an array like :
Array
(
[1] => Array
(
[id] => 1
[symbol] => ARCC
[dates] => Array
(
[3] => Array
(
2019-09-13
2019-09-12
)
)
)
)
Consider your array is $arrDates. If you want to access properties like object properties
$arrFinal = [];
foreach ($arrDates as $intKey => $obj){
$strSymbol = getSubSymbol($obj->symbol);
if(!isset($arrFinal[$strSymbol])) {
$arrFinal[$strSymbol] = [ 'id' => $obj->id, 'symbol' => $obj->symbol];
}
$arrFinal[$strSymbol]['dates'][] = $obj->the_date;
}
// Now loop throuh arrFinal and do print the statements you want.
foreach($arrFinal as $strSubSymbol => $arrData){
echo $strSubSymbol . ' '. count($arrData['dates']) . ' found on dates ' . implode(',', $arrData['dates']). PHP_EOL;
}
Function to get the desired subpart of symbol
function getSubSymbol($symbol_original){
$symbol = preg_split('/(?=\d)/', $symbol_original, 2); //get everything up until first number or the date in the string in this case.
$symbol_here = substr($symbol[0], 1);
return $symbol_here;
}

Doctrine hydrated array result

I want to get Doctrine to return a hydrated array with the values being the id for the key, then all values inside an array of results (i.e. if there are multiple items with same ID, then return ID with multiple results in array).
This is the current function I do:
public static function getMedia($em, $entity, $id = NULL)
{
$dql = 'SELECT m.id, m.url, m.nb, m.lang
FROM iMT\Entity\Media m INDEX BY m.id JOIN iMT\Entity\\' . $entity . ' r WITH m.id = r.id';
if($id) {
$dql .= " WHERE r.id = ?1";
}
$q = $em->createQuery($dql);
if($id) {
$q->setParameter(1, $id);
}
return $q->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
}
Which returns:
array (size=44)
479600 =>
array (size=4)
'id' => int 479600
'url' => string 'pois/479600/Nonna.JPG' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
479615 =>
array (size=4)
'id' => int 479615
'url' => string 'pois/479615/Tramways.jpg' (length=51)
'nb' => null
'lang' => string 'fr' (length=2)
479580 =>
array (size=4)
'id' => int 479580
'url' => string 'pois/479580/ATLAS.jpg' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
479581 =>
array (size=4)
'id' => int 479581
'url' => string 'pois/479581/P'tit_sushi.jpg' (length=54)
'nb' => null
'lang' => string 'fr' (length=2)
However, I need the output to be:
array (size=44)
479600 =>
array (size=2)
array (size=4)
'id' => int 479600
'url' => string 'pois/479600/Nonna.JPG' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
array (size=4)
'id' => int 479600
'url' => string 'pois/479600/OtherPic.JPG' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
Would I need to create my own AbstractQuery::HYDRATE_ARRAY or is there something available that does what I need?
I'm using the result by checking if it contains a key that matches the ID of the current item (e.g. if(isset($data[$item])) // where $item = 479600 then output images), maybe there's a better way to check for the results?
EDIT
I've updated my function to return:
$result = $q->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
$data = array();
$count = count($result);
for($i = 0; $i < $count; $i++) {
if(!isset($data[$result[$i]['id']])) {
$data[$result[$i]['id']] = array(
$result[$i]
);
} else {
$data[$result[$i]['id']][] = $result[$i];
}
}
return $data;
Which returns something more to what I want:
array (size=44)
479600 =>
array (size=1)
0 =>
array (size=4)
'id' => int 479600
'url' => string 'pois/479600/Nonna.JPG' (length=48)
'nb' => null
'lang' => string 'fr' (length=2)
479577 =>
array (size=2)
0 =>
array (size=4)
'id' => int 479577
'url' => string 'pois/479577/AOMC.JPG' (length=47)
'nb' => null
'lang' => string 'fr' (length=2)
1 =>
array (size=4)
'id' => int 479577
'url' => string 'pois/479577/Buffet AOMC.jpg' (length=54)
'nb' => null
'lang' => string 'fr' (length=2)
Can this be improved? Is there any Doctrine functions that can help, or should I leave my for() loop?
The problem with using INDEX BY together with a JOIN is that the result that doctrine gives you might not contain all data that's fetched from the database.
In your case the database might return multiple rows containing the same value for m.id (because of the JOIN). But each subsequent row containing the same value for m.id will overwrite the previous one (because of the INDEX BY m.id).
Doctrine does not come with a hydrator that can solve this problem out of the box. You shall indeed need to implement your own. Read more about creating custom hydration modes.
Alternative
Another solution would be to not use INDEX BY in this case.
You could write a repository method that translates the result given by Doctrine to the array you want to have. Other parts of your application can then call that repository method.
This is probably easier than creating a custom hydration mode.
Update
The translation can look like this:
$data = array();
foreach ($q->getArrayResult() as $row) {
if (!isset($data[$row['id']])) {
$data[$row['id']] = array();
}
$data[$row['id']][] = $row;
}
return $data;

Double foreach getting only one

Hi how can I retrieve only 'fname' from this
array (size=1)
0 =>
array (size=6)
'tcldbid' => int 7
'tname' =>
object(TeamSpeak3\Helper\String)[252]
protected 'string' => string 'TEST' (length=4)
protected 'position' => int 0
'fcldbid' => int 2
'fname' =>
object(TeamSpeak3\Helper\String)[251]
protected 'string' => string 'Pinky' (length=5)
protected 'position' => int 0
'message' =>
object(TeamSpeak3\Helper\String)[256]
protected 'string' => string 'aaaaaa' (length=6)
protected 'position' => int 0
'timestamp' => int 1395092502
I am using foreach in laravel 4.1 blade
#foreach($p as $l)
#foreach($l as $key => $value)
{{$key . " " . $value}}</br>
#endforeach
#endforeach
This foreach is working but I am getting all data when I want to get fname or message only. Can anyone help me with that? I newbie who started learning php so example would be nice :)
No need to loop, you can just access the correct array element:
$fname = $p[0]['fname'];
$message = $p[0]['message'];

Building a form dynamically with Codeigniter and Active Record queries

Model
function get_prices()
{
$table_by_product = 'printer_businesscards'; //replace with URI Segment
//Get all the columns in the table set by the page URI of $table_by_product variable
$get_all_col_names = $this->db->list_fields($table_by_product);
//Loop through the column names. All names starting with 'O_' are optional fields for the
//current product. Get all Distinct values and create a radio button list in form.
foreach ($get_all_col_names as $key => $value) {
//get all o_types for the product by column name
if ($all_O_types = preg_match('/O_/', $value))
{
$O_types = array($value);
foreach ($O_types as $O) {
//echo $O;
$this->db->select($O);
$this->db->distinct();
$qO = $this->db->get($table_by_product);
$qO_Array = $qO->result_object();
}
}
//Get all x_types for the product by column name. All 'X_' types are specific product options.
//Create a dropdown menu with all DISTINCT product options.
if ($all_X_types = preg_match('/X_/', $value))
{
$X_types = array($value);
foreach ($X_types as $X) {
//echo $X;
$this->db->select($X);
$this->db->distinct();
$qX = $this->db->get($table_by_product);
$qX_Array = $qX->result_object();
}
}
}
return array($qX_Array,$qO_Array);
}
}
So each product has different options but all products options are prefixed by "X_" or "O_". I need to get the DISTINCT values of each COLUMN of "X_" and "O_" and in any VIEW I need to build a form with these values. Here is a look at the array:
array (size=3)
0 =>
object(stdClass)[19]
public 'X_SIZE' => string '1.75x3' (length=6)
1 =>
object(stdClass)[20]
public 'X_SIZE' => string '1.75x3.5(slim)' (length=14)
2 =>
object(stdClass)[21]
public 'X_SIZE' => string '2x3' (length=3)
array (size=3)
0 =>
object(stdClass)[17]
public 'X_PAPER' => string '14ptGlossCoatedCoverwithUV(C2S)' (length=31)
1 =>
object(stdClass)[18]
public 'X_PAPER' => string '14ptPremiumUncoatedCover' (length=24)
2 =>
object(stdClass)[24]
public 'X_PAPER' => string '16ptDullCoverwithMatteFinish' (length=28)
array (size=2)
0 =>
object(stdClass)[23]
public 'X_COLOR' => string '1000' (length=4)
1 =>
object(stdClass)[22]
public 'X_COLOR' => string '1002' (length=4)
array (size=4)
0 =>
object(stdClass)[20]
public 'X_QTY' => string '100' (length=3)
1 =>
object(stdClass)[21]
public 'X_QTY' => string '250' (length=3)
2 =>
object(stdClass)[17]
public 'X_QTY' => string '500' (length=3)
3 =>
object(stdClass)[19]
public 'X_QTY' => string '1000' (length=4)
array (size=3)
0 =>
object(stdClass)[25]
public 'O_RC' => string 'YES' (length=3)
1 =>
object(stdClass)[26]
public 'O_RC' => string 'NO' (length=2)
2 =>
object(stdClass)[27]
public 'O_RC' => string 'NA' (length=2)
My current MODEL is only returning X_QTY and O_RC to my view.
What am I doing incorrectly?
You are only returning the last result object of each; ie, you are setting
$qO_Array = $qO->result_object();
to a variable, and it should be:
$qO_Array[] = $qO->result_object();
to get all of them
BTW - do you have a specific reason for calling result_object() instead of the usual result() or result_array()? It's not necessarily wrong, but I wonder if you are doing it intentionally?

PHP Fatal error, trying to request method inside model multiple times

The error message
[23-Mar-2010 08:36:16] PHP Fatal
error: Cannot redeclare humanize()
(previously declared in
/Users/tmclssns/Sites/nadar/nadar/trunk/webapp/application/filer/models/Filer/Aggregate.php:133)
in
/Users/tmclssns/Sites/nadar/nadar/trunk/webapp/application/filer/models/Filer/Aggregate.php
on line 133
I have a "Filer" model which contains several methods to generate graphs. Each method in there related to generating graphs has the suffix "Graph" in the method name. As we have some performance issues, I try to render the graphs in advance (using cron) instead of rendering them on each request. The code below is what I came up with:
public function generategraphsAction()
{
$this->_helper->viewRenderer->setNoRender();
$config = Zend_Registry::get('config');
$id = $this->_getParam('filerid');
$filer = new Filer($id);
$filer_methods = get_class_methods($filer);
foreach ($filer_methods as $filer_method) {
if (preg_match('/^(.*)Graph$/i', $filer_method, $matches)) {
$path = $config->imaging_caching_dir . "/$id/{$matches[1]}.png";
$filer->$matches[0]($path);
}
}
// var_dump(get_class_methods($filer)); die;
}
The result from the var_dump(), when uncommented, is:
array
0 => string '__construct' (length=11)
1 => string 'find_by_name' (length=12)
2 => string 'getPartner' (length=10)
3 => string 'getSlots' (length=8)
4 => string 'getGroups' (length=9)
5 => string 'grouplist' (length=9)
6 => string 'getAggregates' (length=13)
7 => string 'getVolumes' (length=10)
8 => string 'getAggregateVolumes' (length=19)
9 => string 'getShelves' (length=10)
10 => string 'getAutoSupportHistory' (length=21)
11 => string 'getAutoSupportMail' (length=18)
12 => string 'getOrphans' (length=10)
13 => string 'getAll' (length=6)
14 => string 'getDiskRevOverview' (length=18)
15 => string 'getDiskTypeOverview' (length=19)
16 => string 'getDiskTypeSizeFunctionOverview' (length=31)
17 => string 'getLicenses' (length=11)
18 => string 'removeGroup' (length=11)
19 => string 'addGroup' (length=8)
20 => string 'hasGroup' (length=8)
21 => string 'aggdefaultGraph' (length=15)
22 => string 'aggbarGraph' (length=11)
23 => string 'voldefaultGraph' (length=15)
24 => string 'volbarGraph' (length=11)
25 => string 'replicationGraph' (length=16)
26 => string 'getReplicationData' (length=18)
27 => string 'humanize' (length=8)
28 => string 'getFiler' (length=8)
29 => string 'getOptions' (length=10)
30 => string 'getCifsInfo' (length=11)
31 => string 'getCifsStats' (length=12)
32 => string '__get' (length=5)
33 => string 'tr' (length=2)
34 => string 'trs' (length=3)
35 => string 'fieldList' (length=9)
The generategraphsAction() method finds the 'Graph' methods correctly:
array
0 => string 'aggdefaultGraph' (length=15)
1 => string 'aggdefault' (length=10)
array
0 => string 'aggbarGraph' (length=11)
1 => string 'aggbar' (length=6)
array
0 => string 'voldefaultGraph' (length=15)
1 => string 'voldefault' (length=10)
array
0 => string 'volbarGraph' (length=11)
1 => string 'volbar' (length=6)
array
0 => string 'replicationGraph' (length=16)
1 => string 'replication' (length=11)
However when the first graph is generated, it generates the above listed PHP fatal error. Anyone can come up with a solution to this? I tried to pass by reference or switch a few things around (like re declare the Filer model, $current_filer = new Filer($id); and unset() it again after the request, but resulted in the same error) without much success.
The referenced method "humanize" isn't used for anything I'm doing at the moment, but belongs to the Model because it's used in several other places. Of course, removing the method is not really an option right now, and the model contains several other methods as well so I assume if I just move the humanize method around, it will generate an error on the next one.
For reference, the humanize() method:
public function humanize ($kbytes, $unit = null) {
// KiloByte, Megabyte, GigaByte, TeraByte, PetaByte, ExaByte, ZettaByte, YottaByte
$units = array('KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
if (null !== $units) {
$i = array_search(substr($unit, -2), $units);
if (! $i) {
$i = floor((strlen($kbytes) - 1) / 3);
}
} else {
$i = floor((strlen($kbytes) - 1) / 3);
}
$newSize = round($kbytes / pow(1024, $i), 2);
return $newSize . $units[$i];
}
Thanks in advance for the help offered.
I expect your parenthesise are wrong and your function humanize declaration is inside a while loop hence the redeclaration.
Unless of course you are including the file that defines this function twice somewhere?
public static function sums ($aggregates) {
function humanize(&$item, $key) {
$item = Filer::humanize($item);
}
$sums = array('size_total' => 0, 'size_usable' => 0, 'size_snapshot_reserve' => 0,
'size_snapshot_used' => 0, 'size_snapshot_free' => 0,
'size_active_fs_used' => 0, 'size_active_fs_free' => 0,
'size_active_fs_reserved' => 0);
foreach ($aggregates as $aggregate) {
if ($aggregate->state !== 'online') continue;
$sums['size_total'] += $aggregate->size_total;
$sums['size_usable'] += $aggregate->size_usable;
$sums['size_snapshot_reserve'] += $aggregate->size_snapshot_reserve;
$sums['size_snapshot_used'] += $aggregate->size_snapshot_used;
$sums['size_snapshot_free'] += $aggregate->size_snapshot_free;
$sums['size_active_fs_used'] += $aggregate->size_active_fs_used;
$sums['size_active_fs_free'] += $aggregate->size_active_fs_free;
$sums['size_active_fs_reserved'] += $aggregate->size_active_fs_reserved;
}
$humanSums = $sums;
array_walk($humanSums, 'humanize');
return array($sums, $humanSums);
}
The function inside function is the culprit.
Problem fixed.
Adding if(!function_exists('humanize')) block around the method declaration solved it.

Categories