extract data from array that begins with "http" only - php

I have an array $all_urls. If I do print_r($all_urls);, it will return the following data:
Array (
[0] => http://www.domain.com
[1] => https://www.domain.com
[2] => http://www.domain.com/my-account/
[3] => https://www.facebook.com/
[4] => /test
[5] => http://domain.com/wp-content/uploads/logos-5.jpg
[6] => 'http://domain.com/wp-content/themes/'
[7] => '//mattressandmore.com/wp-content/plugins'
)
I would like to extract and list the items that contain "http://" only.

Use this code to filter only the values that begin with http and return a new array:
array_filter($arr, function ($var) {
return stripos($var, 'http', -strlen($var)) !== FALSE;
});

Try to use array_walk function like this:
array_walk($all_urls, function(function(&$value, $index){
if (preg_match('/^http/', $value)) {
echo $index . " " . $value . "\n";
}
});
Also you can just iterate on array with foreach:
foreach($all_urls as $index => $value) {
if (preg_match('/^http/', $value)) {
echo $index . " " . $value . "\n";
}
}

Related

How to Work with Dynamic Multidimensional Array in PHP?

I have dynamic multidimensional array like this :
Array
(
[0] => index.php
[src] => Array
(
[src2] => Array
(
[src3] => Array
(
[0] => test_src3.php
)
[0] => Array
(
[0] => test_src2.php
)
)
[0] => test_src.php
)
[src_test] => Array
(
[New Folder] => Array
(
)
[src_test2] => Array
(
[New Folder] => Array
(
)
[src_test3] => Array
(
)
)
)
[1] => test.php
)
The number of dimensions might be change based on sub directories that found in a folder path inputted by user (this program is used by a person in their local).
How could i fetch those array elements so that the result would be like this :
array(
[0] => src/src2/src3
[1] => src_test/New Folder
[2] => src_test/src_test2/New Folder/
[3] => src_test/src_test2/src_test3
)
By the way i have a function to achieve this :
function getKeyPaths(array $tree, $glue = '/'){
$paths = array();
foreach ($tree as $key => &$mixed) {
if (is_array($mixed)) {
$results = getKeyPaths($mixed, $glue);
foreach ($results as $k => &$v) {
$paths[$key . $glue . $k] = $v;
}
unset($results);
} else {
$paths[$key] = $mixed;
}
}
return $paths;
}
the above function does not result like what i expected:
Array
(
[0] => index.php
[src/src2/src3/0] => test_src3.php
[src/src2/0/0] => test_src2.php
[src/0] => test_src.php
)
How do i achieve this ?
One approach :
function getKeyPaths(array $tree, $glue = '/', $return_array = true){
$paths = "";
foreach ($tree as $key => &$mixed) {
$path = $key . $glue;
if (is_array($mixed) && !is_int($key) ) {
$paths .= $path . getKeyPaths( $mixed, $glue, false);
if ($return_array) {
$paths .= "|";
}
}
}
if ($return_array) {
return explode("|", trim($paths, "|"));
}
return $paths;
}

Filter certain folders from array

I have and array with paths to files, but I need to filter out certain folders.
This is just an example but I want to remove files that are in this case in folders like 'thumbs', 'database' & 'test'.
I could not find an array filter for this.
[
[0] => uploads/projects/pathtofile.jpg,
[1] => uploads/projects/thumbs/pathtofile.jpg,
[3] => uploads/database/projects/pathtofile.jpg,
[4] => uploads/projects/thumbs/database/pathtofile.jpg,
[5] => uploads/thumbs/projects/test/pathtofile.jpg
]
You can use array_interset()
foreach($array as $key=> $ar){
if(count(array_intersect(explode('/',$ar),['thumbs', 'database','test']))>0){
unset($array[$key]);
}
}
Output:- https://eval.in/939916
I'd go with array_filter() and preg_match():
$filtered = array_filter($a, function($i) {
return preg_match('/(thumbs|database|test)/', $i) !== 1;
});
If your file path starts with / then this would work fine:
$blacklist = ['/thumb/', '/image/'];
$files = ['/dir/thumb/image.jpg', '/dir/image/thumb.jpg', '/dir/subdir/file.php'];
$filtered_files = array_filter($files, function($value) use($blacklist){
foreach($blacklist as $blk){
if(strpos($value, $blk) !== false){
return false;
}
}
return true;
});
print_r($filtered_files);
Output :
Array
(
[2] => /dir/subdir/file.php
)
What about using array_filter callable?
<?php
$a = array(
0 => 'uploads/projects/pathtofile.jpg',
1 => 'uploads/projects/thumbs/pathtofile.jpg',
3 => 'uploads/database/projects/pathtofile.jpg',
4 => 'uploads/projects/thumbs/database/pathtofile.jpg',
5 => 'uploads/thumbs/projects/test/pathtofile.jpg',
6 => 'uploads/thumb/projects/pathtofile.jpg'
);
$b = array_values(array_filter($a, function ($item) {
return !preg_match('/(\/thumbs\/|\/database\/|\/test\/)/', $item);
}));
echo '<pre>' . print_r($b, 1) . '</pre>';
Output:
Array
(
[0] => uploads/projects/pathtofile.jpg
[1] => uploads/thumb/projects/pathtofile.jpg
)

Loop through php multi level associative array

I am struggling to return values from all layers of a multidimensional array, e.g. value then all child elements. I've tried lots of loops but can't quite get it right. Please can someone help - I've been stuck for ages! Thank you.
The array is:
Array
(
[SiteRep] => Array
( [DV] => Array
(
[Location] => Array
(
[Period] => Array
(
[0] => Array
(
[value] => 2016-12-19Z
[Rep] => Array
(
[0] => Array
(
[D] => W
[F] => 1
[G] => 9
)
[1] => Array
(
[D] => W
[F] => 0
[G] => 7
)
)
)
[1] => Array
(
[value] => 2016-12-20Z
[Rep] => Array
(
[0] => Array
(
[D] => ENE
[F] => 4
[G] => 7
)
[1] => Array
(
[D] => E
[F] => 3
[G] => 9
)
so far my code is:
$i=0;
foreach ($json_decoded['SiteRep']['DV']['Location']['Period'][$i] as $key => $value) {
if (is_array($value)){
foreach ($value as $key2 => $value2){
if (is_array($value2)){
foreach ($value2 as $key3 => $value3) {
echo $key3 . " 3: " . $value3 . "<br>";
}
} else {
echo $key2 . " 2: " . $value2 . "<br>";
}
};
} else {
echo $key . " 1: " . $value . "<br>";
}
$i++;
};
I believe you are looking for recursion. A function that calls itself. It can be tricky but it is by far the most efficient way to navigate an array of indeterminate depth.
function printStuff($stuff)
{
echo $stuff['value']
if (isset($stuff['rep']))
{
printStuff($stuff['rep']);
}
}
If you want the values to pass down simply change echo to a return value:
function printStuff($stuff)
{
$temp = $stuff['value']
if (isset($stuff['rep']))
{
$temp .= printStuff($stuff['rep']);
}
return $temp;
}
Note: recursion can cause out of memory if not set up correctly similar to an infinite loop, as the recursive function call pushes the function call onto the call stack every time. Just make sure your function call has a subset of the parameter passed in.
If your array has the constantly number of layers, you may use foreach-function for the each layer. If your array has different number of layers every time - you should use the recursion, because it's the only solution in your situation.
Something like this:
array_walk_recursive($array, function($item, $key){
//your actions
});
I've continued drilling down and managed to get all the data I need by using...
foreach ($json_decoded['SiteRep']['DV']['Location']['Period'] as $key => $value) {
if (is_array($value)){
foreach ($value as $key2 => $value2){
if (is_array($value2)){
foreach ($value2 as $key3 => $value3) {
foreach ($value3 as $key4 => $value4) {
echo $key4 . ": " . $value4 . "<br>";
}
}
} else {
echo $key2 . ": " . $value2 . "<br>";
}
};
} else {
echo $key . ": " . $value . "<br>";
}
$i++;
};
This can map the array recursivly. Preserving they keys and structure.
You can however only return a new value and not change the key. But you will know which key you are looking at and if you just want to echo it you can do that to.
array_map_assoc_recursive('callback', $array)
function callback($key, $value) {
return "new" . $value;
}
function array_map_assoc_recursive($f, array $a) {
return array_column(array_map(function ($key, $value) use ($f) {
if (is_array($value)) {
return [$key, array_map_assoc_recursive($f, $value)];
} else {
return [$key, call_user_func($f, $key, $value)];
}
}, array_keys($a), $a), 1, 0);
}

Recursion of multi dimension array using 2nd array for checking keys and type values

I have a JSON array consisting of something like the following:
$json =
Array (
[authmode] => ad
[usertype] => sam
[user] => BobJones
[server] => Array (
[0] => Array (
[ip] => 1.2.3.4
[title] => sony
[id] => Array (
[0] => 1.2.840.1.1.1
[1] => 1.2.840.1.1.2
)
)
[1] => Array (
[ip] => 10.20.30.40
[title] => panasonic
[id] => Array (
[0] => 1.2.840.1.1.10
[1] => 1.2.840.1.1.11
[2] => 1.2.840.1.1.12
[3] => 1.2.840.1.1.13
)
)
)
[recipient] => Array (
[0] => john#smith.org
[1] => jsmith#smith.com
)
[date] => 2014-12-31
[options] => Array (
[0] => alpha
[1] => beta
[2] => gamma
)
)
Some elements of this array are required, others are optional. The required elements I hold in a separate array, containing their keys and their value types:
$req =
Array (
'authmode' => 'string',
'usertype' => 'string',
'user' => 'string'
'server' => 'array',
'ip' => 'string',
'title' => 'string'
'id' => 'array'
)
I have made a function that uses recursion to check for the required keys and ensures that their value types match those in the $req array
function bob($key, $val, $arr){
echo '<br>Checking ' . $key . ' with value of ' . $val . ' within ' . $arr;
// is key found in base array?
if(array_key_exists($key, $arr)){
if(gettype($arr[$key]) == $val){
echo '... gettype reports that ' . $arr . '[' . $key . '] is a ' . $val . ' and is correct';
return true;
}
}
echo '<br>' . $key . ' not in base array, sending back to itself...';
// check arrays within this array
foreach ($key as $ele){
if(is_array($ele)){
echo '<br>' . $ele . ' is an array ....';
if(bob($key, $val, $ele)){
return true;
}
}
}
return false;
}
Finally, the manner in which I call all of this is as follows:
foreach ($reqKeys as $key => $val){
if (!bob($key, $val, $json)){
echo '<p>Failed on ' . $key . ' being a ' . $val . '</p>';
}
}
The function works just fine on the base array, but as soon as I start inspecting any subarrays (the [server] array for example), the function returns an error on the ip not being a string, of which it clearly is.
The response I'm getting is:
Checking authmode with value of string within Array... gettype reports that Array[authmode] is a string and is correct
Checking usertype with value of string within Array... gettype reports that Array[usertype] is a string and is correct
Checking user with value of string within Array... gettype reports that Array[user] is a string and is correct
Checking server with value of array within Array... gettype reports that Array[server] is a array and is correct
Checking ip with value of string within Array
ip not in base array, sending back to itself...
Failed on ip being a string
Any thoughts or comments on a better way of doing things?
Since you want to do more complex comparisons than just type, you should use the strategy pattern and pass validation callbacks in $req.
$req will look like this:
$req = [
'authmode' => 'is_string',
'usertype' => 'is_string',
'user' => 'is_string',
'server' => function ($servers) {
// check is `server` is an array
if (!is_array($servers)) {
return false;
}
foreach ($servers as $server) {
// check conditions for each server.id, server.ip and server.title
if (
!is_array($server['id']) ||
!is_string($server['ip']) ||
!is_string($server['title'])
) {
return false;
}
// validate all server.id's
foreach ($server['id'] as $id) {
if (!is_string($id)) {
return false;
}
}
}
return true;
}
];
Because $arr['server'] is an array, you have to validate its contents using your own function, as you cannot easily refer to them.
This makes our validation function very simple:
function isPropertyValid($key, $isValid, $arr) {
if (!isset($arr[$key])) {
return false;
}
return isset($arr[$key]) && $isValid($arr[$key]);
}
You no longer need recursion there which is great, as it would introduce some complications.
You might just as well throw in a function that validates all requirements instead of doing it one by one:
function isArrayValid($requirements, $arr) {
foreach ($requirements as $key => $validator) {
if (!isPropertyValid($key, $validator, $arr)) {
return false;
}
}
return true;
}
I've put together a working example here.

How to loop 3 dimension array using foreach PHP

Below is foreach and the 3 dimension arrays, no problem with the looping but i cannot sepcify which array to echo, they must me the whole arrays like echo $subvalue, any better solutions with looping 3 dimension array? i actually feel weird with this looping. Thanks in adv
foreach ($stories as $key => $story){
//echo "<br />";
foreach($story as $subkey => $subvalue){
echo $subvalue."<br />";
foreach($subvalue as $key => $subsubvalue){
echo $subsubvalue."<br />";
}
}
}
Array
(
[270] => Array
(
[uid] => 36
[user_email] => aaa#hotmail.com
[sid] => 270
[story_name] => Story C
[photo_url] => Array
(
[0] => story_photos/2012/0322/361332381418153311.jpg
[1] => story_photos/2012/0322/361332393792911587.jpg
)
[photo_added_date] => Array
(
[0] => 1332381418
[1] => 1332393792
)
)
[269] => Array
(
[uid] => 36
[user_email] => aaa#hotmail.com
[sid] => 269
[story_name] => Story B
[photo_url] => Array
(
[0] => story_photos/2012/0322/361332381406580761.jpg
)
[photo_added_date] => Array
(
[0] => 1332381406
)
)
[268] => Array
(
[uid] => 36
[user_email] => aaa#hotmail.com
[sid] => 268
[story_name] => Story A
[photo_url] => Array
(
[0] => story_photos/2012/0322/361332381393552719.jpg
)
[photo_added_date] => Array
(
[0] => 1332381393
)
)
)
Why not try this :
foreach ($stories as $key => $story){
if(is_array($story)){
foreach($story as $subkey => $subvalue){
if(is_array($subvalue)){
foreach($subvalue as $key => $subsubvalue){
echo $subsubvalue."<br />";
}
} else {
echo $subvalue."<br />";
}
}
} else {
echo $story."<br />";
}
}
Also, I am not sure because your question isn't really clear or specified.
Or
function echoArray( $array )
{
foreach ($array as $key => $cell)
{
if ( true == is_array($cell) )
{
echoArray($cell);
}
else
{
echo "$cell<br />";
}
}
}
It works for N dimensionnal array
An improved version to know the depth and use different css class for depth and to use set the tag in which the value should be added:
Eg: for depth 0 the class will by arrayclass_0, for depth 1 arrayclass_1, etc...
/**
$array : The array
$depth: The depth ( you should always set it to 0)
$cssclassprefix: The css class prefix you want to set
$tag: the default tag to use to render
$arraytagkey: An optionnal key in your array to extract the tag to use
*/
function echoArray( $array, $depth=0, $cssclassprefix='arrayclass_', $tag='div', $arraytagkey = '' )
{
if ( 0 != strcmp($arraytagkey) && isset($array[$arraytagkey]) )
{
$tag=$array[$arraytagkey];
}
foreach ($array as $key => $cell)
{
if ( true == is_array($cell) )
{
echoArray($cell, $depth+1, $cssclassprefix, $tag, $arraytagkey);
}
else
{
$matches = array();
if ( 0 != preg_match("/^(img|iframe|input)$/i",$tag) )
{
if ( 0 != strcasecmp('input',$tag) )
{
echo "<input class='$cssclassprefix$depth' value='$cell' />";
}
else
{
echo "<$tag class='$cssclassprefix$depth' src='$cell' />";
}
}
else if( 0 != preg_match("/^(br|hr)$/i",$tag) )
{
echo "$cell<$tag />";
}
else
{
echo "<$tag class='$cssclassprefix$depth'>$cell</$tag>";
}
}
}
}
This doesn't really answer your question, but note, your third loop is this:
foreach ($subvalue as $key => $subsubvalue){
But you've already used $key in the first loop:
foreach ($stories as $key => $story){
You should change the third to:
foreach ($subvalue as $subsubkey => $subsubvalue){
Are you just wanting to loop through and get access to the photo_urls and other data? If that's the case then here's a simple example of how you can access the data:
foreach($stories as $key => $story)
{
// here you can echo the $store['user_email'] etc
echo 'Email: ' . $story['user_email'] . '<br />';
// loop over the photo urls
foreach($story['photo_url'] as $photo_url)
{
echo 'Photo URL: ' . $photo_url . '<br />';
}
// loop over the photo added dates
foreach($story['photo_added_date'] as $photo_added_date)
{
echo 'Photo Date: ' . $photo_added_date . '<br />';
}
}
If you're wanting to recursively search the array then the other answers are what you want.

Categories