Custom While in json array - php

Its My PHP Code:
$res_media=mysql_query("SELECT * FROM mv_media");
$media = array();
while($resualt_media = mysql_fetch_assoc($res_media)) {
$media[]= $resualt_media['title'];
}
echo $media;
And Its My output:
["Test","Test","Test","Test","Test"]
I want Change it to this format :
["Test"],["Test"],["Test"],["Test"],["Test"]
I changed My Code to this code :
$res_media=mysql_query("SELECT * FROM mv_media");
$media = array();
while($resualt_media = mysql_fetch_assoc($res_media)) {
$media[]= [$resualt_media['title']];
}
echo $media;
Now My OutPut :
[["Test","Test","Test","Test","Test"]]
But I need This custom output:
[["Test"],["Test"],["Test"],["Test"],["Test"],["ItsMyCustomChild"]]
I want add Custom Child with out database!

You can change $media[] = [<value>] to $media[][] = <value> and it will work, because then you'll create a new array inside an array.

I would suggest this approach:
<?php
$input = json_decode('["Test","Test","Test","Test","Test"]');
$output = [];
array_walk($input, function($element) use (&$output) {
$output[] = [$element];
});
var_dump(json_encode($output));
Alternatively this can be simplified to just:
<?php
$data = json_decode('["Test","Test","Test","Test","Test"]');
array_walk($data, function(&$element) {
$element = [$element];
});
var_dump(json_encode($data));
The created array structure obviously is:
Array
(
[0] => Array
(
[0] => Test
)
[1] => Array
(
[0] => Test
)
[2] => Array
(
[0] => Test
)
[3] => Array
(
[0] => Test
)
[4] => Array
(
[0] => Test
)
)
Which, if you again json_encode() it, results in the desired format:
string(46) "[["Test"],["Test"],["Test"],["Test"],["Test"]]"
The specific issue you are actually dealing with is not so much the creation of the desired structure, but that you are trying to modify the JSON string instead of the actual array you want to work with. That is why a call to json_decode() is used initially.

$res_media=mysql_query("SELECT * FROM mv_media");
$media = array();
while($resualt_media = mysql_fetch_assoc($res_media)) {
array_push($media,array($resualt_media['title']));
}
print_r $media;

You just need to change below line. and you will get your desired result.
$media[][]= $resualt_media['title'];
if you want to see what you get . you need to add json_encode() after the while.
like below
echo json_encode($media);

Related

PHP recursion with the results put into a single array

I am trying to program a web crawler but I have no idea, how to create a recursion for parsing a webpage and adding all the endresults into a final array.
I never worked with php before but I did alot of research on the internet and figured already out, how to parse the page I want to scrape.
Please note, that I have changed the $url value and the array result below to some values which I have randomly generated in my mind.
<?php
include_once "simple_html_dom.php"; //http://simplehtmldom.sourceforge.net/
$url = "https://www.scrapesite.com/pagetoscrape/index.html";
function parseLink($link) {
$html = file_get_html($link);
$html = $html->find("/html/body/script[2]/text", 0);
preg_match('/\{(?:[^{}]|(?R))*\}/', $html, $matches); //this regex extracts a json array
$json = json_decode($matches[0]);
$data = ($json->props->contents);
return $data;
}
function getFolders($basepath, $data) {
$data = $data->folders;
$result = array();
foreach ($data as $value) {
$result[] = array("folder", $basepath . "/" . $value->filename, $value->href);
}
return $result;
}
$data = getFolders("", parseLink($url));
print_r ($data);
?>
This script works fine and it outputs the following:
Array
(
[0] => Array
(
[0] => folder
[1] => /1
[2] => https://www.scrapesite.com/pagetoscrape/sjdfi327943sad/index.html
)
[1] => Array
(
[0] => folder
[1] => /2
[2] => https://www.scrapesite.com/pagetoscrape/345fdsjjsdfsdf/index.html
)
[2] => Array
(
[0] => folder
[1] => /3
[2] => https://www.scrapesite.com/pagetoscrape/46589dsjodsiods/index.html
)
[3] => Array
(
[0] => folder
[1] => /4
[2] => https://www.scrapesite.com/pagetoscrape/345897dujfosfsd/index.html
)
[4] => Array
(
[0] => folder
[1] => /5
[2] => https://www.scrapesite.com/pagetoscrape/9dsfghshdfsds3/index.html
)
)
Now, the script should execute the getFolders function for every item in the above array. This may return another array of folder which should get parsed too.
And then I want to create a final array where all the folders ABSOLUTE paths ($basepath . "/" . $value->filename) and href links are listed. I really appreciate every little hint.
I was able to find some example on the web but I can't figure out how to implement it here because I have almost no experience with programming languages in general.
Initialize an empty array and pass that as a reference to the getFolders() function. Keep putting the results of scraping inside this array. Also, you need to call getFolders() again inside the foreach loop of the getFolders(). Example below:
$finalResults = array();
getFolders("", parseLink($url), $finalResults);
Your getFolders() function signature will now look like below:
function getFolders($basepath, $data, &$finalResults) //notice the & before the $finalResults used for passing by reference
And, your foreach loop:
foreach ($data as $value) {
$finalResults[] = array("folder", $basepath . "/" . $value->filename, $value->href);
getFolders("", parseLink($value->href), $finalResults);
}
Above code is just an example. Change it according to your needs.

Getting object into array

I'm not so advanced in PHP, just basic I can understand. I was trying an API and it returns it as object, how do I convert it to array? I did searched through stackoverflow and found lots of solution, but none works for me. $array returns empty array. Here is my code:-
while (1) {
$line = '';
$w->pollMessage();
$msgs = $w->getMessages();
foreach ($msgs as $m) {
print_r($msgs);
$array = json_decode(json_encode($msgs), true);
print_r($array);
}
And here is the result I get print_r($msgs):
Array
(
[0] => ProtocolNode Object
(
[tag:ProtocolNode:private] => message
[attributeHash:ProtocolNode:private] => Array
(
[from] => amy
[type] => text
[id] => 3EB0E191F15B831D244E
[t] => 1462939886
[notify] => Nick
)
[children:ProtocolNode:private] => Array
(
[0] => ProtocolNode Object
(
[tag:ProtocolNode:private] => enc
[attributeHash:ProtocolNode:private] => Array
(
[v] => 2
[type] => msg
)
[children:ProtocolNode:private] =>
[data:ProtocolNode:private] => 3
)
[1] => ProtocolNode Object
(
[tag:ProtocolNode:private] => body
[attributeHash:ProtocolNode:private] =>
[children:ProtocolNode:private] =>
[data:ProtocolNode:private] => good
)
)
[data:ProtocolNode:private] =>
)
)
I don't see your problem. You already have an array and do not need to handle with json. If you don't like it as array, you can simply cast it to an object.
$myArray = (object) $myArray;
Requirements: Walk a multiway object tree and apply a callback to each node.
Working demonstration at eval.in
Explanation:
1) There are a lot of private properties and I am not sure 'casting to an array' will let get at them.
2) If you have the original class then you may want to usesome of the methods on it.
The approach I used is:
a) Provide a 'tree walk' that will visit all the nodes in the tree. I am not concerned about order of visiting. Just to visit then all.
b) Rather than provide specific code to process the node. I provide a 'callback' hook.
c) As I don't have the class I create a simple one that will give me easy access to the private properties.
The Tree Walk function:
function walkProtocolNodes(\ProtocolNode $currentNode, /* callable */ $processNode)
{
$processNode($currentNode);
foreach ($currentNode->children as $nextNode) {
walkProtocolNodes($nextNode, $processNode);
}
return;
}
Sample processNode function:
All it does is append the attributesHash to the output array (outputResults)...
$processNode = function (\ProtocolNode $node) use (&$outputResults) {
$outputResults[] = $node->attributeHash;
};
Run the tree walk:
walkProtocolNodes($node1, $processNode);
The 'protocolNode' class I used:
class ProtocolNode {
private $tag = 'message';
private $attributeHash = array();
private $children = array();
private $data = 'good';
public function __construct($attrs = array()) {
$this->attributeHash = $attrs;
}
public function addChild(\ProtocolNode $node) {
$this->children[] = $node;
}
public function __get($propertyName) {
return $this->$propertyName;
}
}
See the demonstration to see the output

Storing XML Document with XPath and PHP, tag info isn't storing in array like needed

So, I want to iterate through the XML by the attributes of and then print the tags from within the coordinating tag. This is the structure:
<emp salesid="1">
<report>07-14-2015_DPLOH_SalesID_1.pdf</report>
<report>07-17-2015_DPLOH_SalesID_1.pdf</report>
<report>07-14-2015_DTE_SalesID_1.pdf</report>
<report>07-14-2015_IDT_SalesID_1.pdf</report>
<report>07-14-2015_Kratos_SalesID_1.pdf</report>
<report>07-14-2015_Spark_SalesID_1.pdf</report>
</emp>
Here is the my code:
$xml = new SimpleXMLElement($xmlStr);
foreach($xml->xpath("//emp/report") as $node) {
//For all found nodes retrieve its ID from parent <emp> and store in $arr
$id = $node->xpath("../#salesid");
$id = (int)$id[0];
if(!isset($arr[$id])) {
$arr[$id] = array();
}
//Then we iterate through all nodes and store <report> in $arr
foreach($node as $report) {
$arr[$id][] = (string)$report;
}
}
echo "<pre>";
print_r($arr);
echo "</pre>";
However, this is what I get for output:
Array
(
[1] => Array
(
)
[10] => Array
(
)
... and it continues to iterate through all of the attributes of tags, but never fills the array with any information.
If anyone could help tell me what I'm missing, I would GREATLY appreciate it. I feel like I'm losing my mind over what seems like should be rather simple.
Thanks!
You're very close. The code isn't working because of the second for loop. The outer loop will iterate through all of the report elements. So, node is a report element. When you try to iterate through the children of report, there's nothing there.
Instead of the second (inner) loop, simply do this:
$arr[$id][] = (string)$node;
When I did, I got the following result:
<pre>
Array
(
[1] => Array
(
[0] => 07-14-2015_DPLOH_SalesID_1.pdf
[1] => 07-17-2015_DPLOH_SalesID_1.pdf
[2] => 07-14-2015_DTE_SalesID_1.pdf
[3] => 07-14-2015_IDT_SalesID_1.pdf
[4] => 07-14-2015_Kratos_SalesID_1.pdf
[5] => 07-14-2015_Spark_SalesID_1.pdf
)
)
I updated your script to work slightly differently:
$emp = new SimpleXMLElement($xmlStr);
$id = intval($emp['salesid']);
$arr = array(
$id => array(),
);
$lst = $emp->xpath('/emp/report');
while (list(, $text) = each($lst))
{
$arr[$id][] = (string) $text;
}
echo "<pre>";
print_r($arr);
echo "</pre>";
Cheers

How to not echo array if previous one's key has been echoed already

This is what I get after a print_r($myArray) (wrapped in pre) on my array.
Array
(
[0] => 203.143.197.254
[1] => not/available
)
Array
(
[0] => 40.190.125.166
[1] => articles/not/a/page
)
Array
(
[0] => 25.174.7.82
[1] => articles/not/a/page
)
How would I return or echo just the first two in this case (no regex), given the fact that I would like to only output each array whose [1] value has not been echoed before?
My list as far more entries and $myArray[1] is sometimes the same, I want to skip echoing the same thing.
I have tried array_unique but I can't get it to work as param 1 is expected to be an array.
print_r(array_unique($myArray));
This works. Didn't do a full copy paste job but hopefully you get the idea of the logic
$echoed = array();
foreach($array as $arr) {
if(!in_array($arr[1],$echoed)) {
echo $arr[1];
$echoed[] = $arr[1];
}
}
$echoedBefore = array();
print_r(array_filter($myArray, function($entry) {
global $echoedBefore;
$alreadyEchoed = in_array($entry[1], $echoedBefore);
if (!$alreadyEchoed) {
$echoedBefore[] = $entry[1];
}
return !$alreadyEchoed;
}));

PHP remove nested arrays

I have an array $templates that looks like this:
Array
(
[0] => Array
(
[displayName] => First Template
[fileName] => path_to_first_template
)
[1] => Array
(
[displayName] => Second Template
[fileName] => path_to_second_template
)
[2] => Array
(
[displayName] => Third template
[fileName] => path_to_third_template
)
)
And I want to make it to look like this:
Array
(
[path_to_first_template] => First Template
[path_to_second_template] => Second Template
[path_to_third_template] => Third Template
)
That is, I want the fileName of the nested arrays to be the new array's key and displayName to be its value.
Is there a pretty way to do this without having to loop through the array. I had no luck searching, as I didn't know exactly what to search for.
Here's a classic foreach in action:
$result = array();
foreach($array as $row) {
$result[$row['fileName']] = $row['displayName'];
};
Here's a "clever" way to do it:
$result = array();
array_walk($array, function($row) use (&$result) {
$result[$row['fileName']] = $row['displayName'];
});
As you can see, the second approach is not really better than the first one. The only advantage is that theoretically you can pile upon the second form because it is a single expression, but in practice it's a long enough expression already so you wouldn't want to do that.
Loop in your array and make a new one:
$newArray = array();
foreach($array as $val){
$newArray[$val['fileName']] = $val['displayName'];
}
print_r($newArray);
$ret = array()
foreach ($templates as $template) {
$ret[$template["fileName"]] = $template["displayName"];
}

Categories