I'm using php to create a ziparchive which contains some images. This works fine exept when i try to rename the files. This is the code that works:
$zip_archive->open(tempnam("tmp", "zip"), ZipArchive::OVERWRITE);
foreach ($images as $image) {
$path = $image['path'];
$title = $image['title'];
if(file_exists($path)){
$zip_file->addFile($path, pathinfo($path, PATHINFO_BASENAME));
}
}
$zip_archive->close();
$images is an array and could look like this:
$images = array(
'path' => array(
'folder/title1.jpg',
'folder/title2.jpg'
),
'title' => array(
'new_name1.jpg',
'new_name2.jpg'
)
)
I would like to name the image as its title.
$zip_file->addFile($path, $title);
But whats happening is that the files in the zip with the title as name are empty. What am I doing wrong?
If I run this
$images = array(
'path' => array(
'folder/title1.jpg',
'folder/title2.jpg'
),
'title' => array(
'new_name1.jpg',
'new_name2.jpg'
)
);
$i = 0;
foreach($images as $image)
var_dump($image, $i++);
I get
array(2) {
[0]=>
string(17) "folder/title1.jpg"
[1]=>
string(17) "folder/title2.jpg"
}
int(0)
array(2) {
[0]=>
string(13) "new_name1.jpg"
[1]=>
string(13) "new_name2.jpg"
}
int(1)
This means that these
$path = $image['path'];
$title = $image['title'];
are both NULL
You have two ways to fix this:
Change the array to look like
$images = array(
[0] => array(
'path' => 'folder/title1.jpg',
'title' => 'new_name1.jpg'
),
[1] => array(
'path' => 'folder/title2.jpg'
'title' => 'new_name2.jpg',
)
);
in this case your initial code should work
Change the way to access the array, doing something like
for($i = 0;$i < count($images['path']);$i++)
{
$path = $image['path'][$i];
$title = $image['title'][$i];
}
This way you are sure that path and title of the image will have the same index, but it's not recommanded to do so because the array must be ordered.
I suggest you to change the array, your code should be ok that way
Related
i have some data like this
but i cant create it data to array multidimensi, how to create and view array like this? thank you.
Array (A => array (part_no=>A, control_no=>0001, qty=>1000))
i try like
$data = array();
while ($r = pg_fetch_array($query)) {
$data_arr = array(
$control = $r['control_no'], $part_no= $r[part_no]);
$data = $data_arr
);
}
print_r ($data);
you can do it like this. Note you have to use => not = also note used $data[] instead of $data. still unclear on the output requirement. asuming you want all rows.
$data = array();
while ($r = pg_fetch_array($query)) {
$data_arr = array($r[part_no] => array(
'control' => $r['control_no'],
'part_no'=> $r[part_no],
'qty'=> $r[qty]
));
$data[] = $data_arr);
}
print_r ($data);
this will output something like
Array (
[0]=> Array( A => array (part_no=>A, control_no=>0001, qty=>1000)),
[1]=> Array( A => array (part_no=>A, control_no=>0002, qty=>1000)),
[2]=> Array( A => array (part_no=>A, control_no=>0003, qty=>1000)),
[3]=> Array( B => array (part_no=>B, control_no=>0004, qty=>1500)),
...........
)
I'm making a twitter bot using Codebird.
I want to sort the data status in php array without duplicates. Line by line (urls media /remote file links)
This my code:
require_once ('codebird.php');
\Codebird\Codebird::setConsumerKey("pubTRI3ik5hJqxxxxxxxxxx", "xxxxxS6Uj1t5GJPi6AUxxxxx");
$cb = \Codebird\Codebird::getInstance();
$cb->setToken("xxxxxxx-aVixxxxxxxxxX5MsEHEK", "Dol6RMhOYgxxxxxxFnDtJ6IzXMOLyt");
$statusimgs = array (
"/images.com/hfskehfskea33/jshdfjsh.jpeg",
"/pic.images.com/SDjhs33/sZddszf.jpeg",
"/pic.images.com/dfggfd/dgfgfgdg.jpeg",
"//pic.images.com/xgxg/xdgxg6.jpeg",
);
$params = array(
'status' => 'halo my ststus',
'media[]' => $statusimgs[array_rand($statusimgs)]
);
$reply = $cb->statuses_updateWithMedia($params);
Initially I use random array, but this can make duplicate photos.
I want to sort link remote files from first line to last. I have 1-100 link images to upload on twitter from remote file methot. One by one when script execute manual or with cron.
I want set cron every 60s , 60s 1 photo tweet.
I understand your question as "Remove duplicates from an array and sort it".So, you could try this:
Make $statusarray unique,
sort $statusarray,
add $statusarray to $params array (key = 'media').
Code
<?php
// Input array
$statusimgs = array (
"/images.com/hfskehfskea33/jshdfjsh.jpeg",
"/pic.images.com/SDjhs33/sZddszf.jpeg",
"/pic.images.com/dfggfd/dgfgfgdg.jpeg",
"/pic.images.com/dfggfd/dgfgfgdg.jpeg",
"/pic.images.com/xgxg/xdgxg6.jpeg",
"/pic.images.com/xgxg/xdgxg6.jpeg",
"/pic.images.com/xgxg/xdgxg6.jpeg",
);
// Make unique and sort
$statusimgs = array_unique($statusimgs, SORT_STRING);
sort($statusimgs,SORT_STRING);
// Create the resulting $params array
$params = array(
'status' => 'halo my ststus',
'media' => $statusimgs
);
// Display the result
echo '<pre>'; var_dump($params); '</pre>';
//$reply = $cb->statuses_updateWithMedia($params);
?>
Result
array(2) {
["status"]=>
string(14) "halo my ststus"
["media"]=>
array(4) {
[0]=> string(39) "/images.com/hfskehfskea33/jshdfjsh.jpeg"
[1]=> string(36) "/pic.images.com/SDjhs33/sZddszf.jpeg"
[2]=> string(36) "/pic.images.com/dfggfd/dgfgfgdg.jpeg"
[3]=> string(32) "/pic.images.com/xgxg/xdgxg6.jpeg"
}
}
Alternative Code
<?php
$statusimgs = array (
"/images.com/hfskehfskea33/jshdfjsh.jpeg",
"/pic.images.com/SDjhs33/sZddszf.jpeg",
"/pic.images.com/dfggfd/dgfgfgdg.jpeg",
"/pic.images.com/dfggfd/dgfgfgdg.jpeg",
"/pic.images.com/xgxg/xdgxg6.jpeg",
"/pic.images.com/xgxg/xdgxg6.jpeg",
"/pic.images.com/xgxg/xdgxg6.jpeg",
);
$statusimgs = array_unique($statusimgs, SORT_STRING);
sort($statusimgs,SORT_STRING);
session_start();
if (!isset($_SESSION['index'])) {
$_SESSION['index'] = 1;
} else {
$_SESSION['index'] = ($_SESSION['index']>=count($statusimgs)) ? 1 : $_SESSION['index']+1;
}
session_write_close();
$params = array(
'status' => 'halo my ststus',
'media' => $statusimgs
);
// echo '<pre>'; var_dump($params); '</pre>';
echo 'Choosen: ' . $params['media'][$_SESSION['index']-1] . '<br />';
//$reply = $cb->statuses_updateWithMedia($params);
?>
I have been puzzling with this problem for days, without any luck. I hope some of you can help.
From my database I get a list of files, which various information attached, including a virtual path. Some typical data is:
Array
(
[0] => Array
(
[name] => guide_to_printing.txt
[virtual_path] => guides/it
)
[1] => Array
(
[name] => guide_to_vpn.txt
[virtual_path] => guides/it
)
[2] => Array
(
[name] => for_new_employees.txt
[virtual_path] => guides
)
)
I wish to convert this into a hierarchical array structure from the virtual paths, so the output of the above should be:
Array
(
[0] => Array
(
[type] => dir
[name] => guides
[children] => Array
(
[0] => Array
(
[type] => dir
[name] => it
[children] = Array
(
[0] => Array
(
[type] => file
[name] => guide_to_printing.txt
)
[1] => Array
(
[type] => file
[name] => guide_to_vpn.txt
)
)
)
[1] => Array
(
[type] => file
[name] => for_new_employees.txt
)
)
)
)
Where the type property indicates if it is a directory or a file.
Can someone help with creating a function which does this conversion. It will be of great help. Thanks.
My own best solution so far is:
foreach($docs as $doc) {
$path = explode("/",$doc['virtual_path']);
$arrayToInsert = array(
'name' => $doc['name'],
'path' => $doc['virtual_path'],
);
if(count($path)==1) { $r[$path[0]][] = $arrayToInsert; }
if(count($path)==2) { $r[$path[0]][$path[1]][] = $arrayToInsert; }
if(count($path)==3) { $r[$path[0]][$path[1]][$path[2]][] = $arrayToInsert; }
}
Of course this only works for a depth of 3 in the directory structure, and the keys are the directory names.
Function
function hierarchify(array $files) {
/* prepare root node */
$root = new stdClass;
$root->children = array();
/* file iteration */
foreach ($files as $file) {
/* argument validation */
switch (true) {
case !isset($file['name'], $file['virtual_path']):
case !is_string($name = $file['name']):
case !is_string($virtual_path = $file['virtual_path']):
throw new InvalidArgumentException('invalid array structure detected.');
case strpos($virtual_path, '/') === 0:
throw new InvalidArgumentException('absolute path is not allowed.');
}
/* virtual url normalization */
$parts = array();
$segments = explode('/', preg_replace('#/++#', '/', $virtual_path));
foreach ($segments as $segment) {
if ($segment === '.') {
continue;
}
if (null === $tail = array_pop($parts)) {
$parts[] = $segment;
} elseif ($segment === '..') {
if ($tail === '..') {
$parts[] = $tail;
}
if ($tail === '..' or $tail === '') {
$parts[] = $segment;
}
} else {
$parts[] = $tail;
$parts[] = $segment;
}
}
if ('' !== $tail = array_pop($parts)) {
// skip empty
$parts[] = $tail;
}
if (reset($parts) === '..') {
// invalid upper traversal
throw new InvalidArgumentException('invalid upper traversal detected.');
}
$currents = &$root->children;
/* hierarchy iteration */
foreach ($parts as $part) {
while (true) {
foreach ($currents as $current) {
if ($current->type === 'dir' and $current->name === $part) {
// directory already exists!
$currents = &$current->children;
break 2;
}
}
// create new directory...
$currents[] = $new = new stdClass;
$new->type = 'dir';
$new->name = $part;
$new->children = array();
$currents = &$new->children;
break;
}
}
// create new file...
$currents[] = $new = new stdClass;
$new->type = 'file';
$new->name = $name;
}
/* convert into array completely */
return json_decode(json_encode($root->children), true);
}
Example
Case 1:
$files = array(
0 => array (
'name' => 'b.txt',
'virtual_path' => 'A/B//',
),
1 => array(
'name' => 'a.txt',
'virtual_path' => '././A/B/C/../..',
),
2 => array(
'name' => 'c.txt',
'virtual_path' => './A/../A/B/C//////',
),
3 => array(
'name' => 'root.txt',
'virtual_path' => '',
),
);
var_dump(hierarchify($files));
will output...
array(2) {
[0]=>
array(3) {
["type"]=>
string(3) "dir"
["name"]=>
string(1) "A"
["children"]=>
array(2) {
[0]=>
array(3) {
["type"]=>
string(3) "dir"
["name"]=>
string(1) "B"
["children"]=>
array(2) {
[0]=>
array(2) {
["type"]=>
string(4) "file"
["name"]=>
string(5) "b.txt"
}
[1]=>
array(3) {
["type"]=>
string(3) "dir"
["name"]=>
string(1) "C"
["children"]=>
array(1) {
[0]=>
array(2) {
["type"]=>
string(4) "file"
["name"]=>
string(5) "c.txt"
}
}
}
}
}
[1]=>
array(2) {
["type"]=>
string(4) "file"
["name"]=>
string(5) "a.txt"
}
}
}
[1]=>
array(2) {
["type"]=>
string(4) "file"
["name"]=>
string(8) "root.txt"
}
}
Case 2:
$files = array(
0 => array (
'name' => 'invalid.txt',
'virtual_path' => '/A/B/C',
),
);
var_dump(hierarchify($files));
will throw...
Fatal error: Uncaught exception 'InvalidArgumentException' with message 'absolute path is not allowed.'
Case 3:
$files = array(
0 => array (
'name' => 'invalid.txt',
'virtual_path' => 'A/B/C/../../../../../../../..',
),
);
var_dump(hierarchify($files));
will throw...
Fatal error: Uncaught exception 'InvalidArgumentException' with message 'invalid upper traversal detected.'
With something like this:
foreach ($array as $k => $v) {
$tmp = explode('/',$v['virtual_path']);
if(sizeof($tmp) > 1){
$array_result[$tmp[0]]['children'][$k]['type'] = 'file';
$array_result[$tmp[0]]['children'][$k]['name'] = $v['name'];
$array_result[$tmp[0]]['type'] = 'dir';
$array_result[$tmp[0]]['name'] = $v['name'];
}
}
I get an array like this on:
Array
(
[guides] => Array
(
[children] => Array
(
[0] => Array
(
[type] => file
[name] => guide_to_printing.txt
)
[1] => Array
(
[type] => file
[name] => guide_to_vpn.txt
)
)
[type] => dir
[name] => guide_to_vpn.txt
)
)
I know that's not exactly what you want but i think that can put you in the right direction.
Event though you should have tried something before you post here, I like your question and think it is a fun one. So here you go
function &createVirtualDirectory(&$structure, $path) {
$key_parts = $path ? explode('/', $path) : null;
$last_key = &$structure;
if (is_array($key_parts) && !empty($key_parts)) {
foreach ($key_parts as $name) {
// maybe directory exists?
$index = null;
if (is_array($last_key) && !empty($last_key)) {
foreach ($last_key as $key => $item) {
if ($item['type'] == 'dir' && $item['name'] == $name) {
$index = $key;
break;
}
}
}
// if directory not exists - create one
if (is_null($index)) {
$last_key[] = array(
'type' => 'dir',
'name' => $name,
'children' => array(),
);
$index = count($last_key)-1;
}
$last_key =& $last_key[$index]['children'];
}
}
return $last_key;
}
$input = array(
0 => array (
'name' => 'guide_to_printing.txt',
'virtual_path' => 'guides/it',
),
1 => array(
'name' => 'guide_to_vpn.txt',
'virtual_path' => 'guides/it',
),
2 => array(
'name' => 'for_new_employees.txt',
'virtual_path' => 'guides',
)
);
$output = array();
foreach ($input as $file) {
$dir =& createVirtualDirectory($output, $file['virtual_path']);
$dir[] = array(
'type' => 'file',
'name' => $file['name']
);
unset($dir);
}
print_r($output);
Provides the exact output you want
Here is simple way to do this with 2 recursive functions.
One function to parse one line of data.
Another to merge each parsed line of data.
// Assuming your data are in $data
$tree = array();
foreach ($data as $item) {
$tree = merge($tree, parse($item['name'], $item['virtual_path']));
}
print json_encode($tree);
// Simple parser to extract data
function parse($name, $path){
$parts = explode('/', $path);
$level = array(
'type' => 'dir',
'name' => $parts[0],
'children' => array()
);
if(count($parts) > 1){
$path = str_replace($parts[0] . '/', '', $path);
$level['children'][] = parse($name, $path);
}
else {
$level['children'][] = array(
'type' => 'file',
'name' => $name
);
}
return $level;
}
// Merge a new item to the current tree
function merge($tree, $new_item){
if(!$tree){
$tree[] = $new_item;
return $tree;
}
$found = false;
foreach($tree as $key => &$item) {
if($item['type'] === $new_item['type'] && $item['name'] === $new_item['name']){
$item['children'] = merge($item['children'], $new_item['children'][0]);
$found = true;
break;
}
}
if(!$found) {
$tree[] = $new_item;
}
return $tree;
}
I'm iterating over a folder and formatting its contents in a certain way.
I've to form an array from this set of strings:
home--lists--country--create_a_country.jpg
home--lists--country--list_countries.jpg
profile--edit--account.jpg
profile--my_account.jpg
shop--orders--list_orders.jpg
The array needs to look like this:
<?php
array(
'home' => array(
'lists' => array(
'country' => array(
'create_a_country.jpg',
'list_countries.jpg'
)
)
),
'profile' => array(
'edit' => array(
'account.jpg'
),
'my_account.jpg'
),
'shop' => array(
'orders' => array(
'list_orders.jpg',
)
);
The thing is, the depth of the array could be infinitely deep depending on how many '--' dividers the file name has. Here's what I've tried (assuming each string is coming from an array:
$master_array = array();
foreach($files as $file)
{
// Get the extension
$file_bits = explode(".", $file);
$file_ext = strtolower(array_pop($file_bits));
$file_name_long = implode(".", $file_bits);
// Divide the filename by '--'
$file_name_bits = explode("--", $file_name_long);
// Set the file name
$file_name = array_pop($file_name_bits).".".$file_ext;
// Grab the depth and the folder name
foreach($file_name_bits as $depth => $folder)
{
// Create sub-arrays as the folder structure goes down with the depth
// If the sub-array already exists, don't recreate it
// Place $file_name in the lowest sub-array
// .. I'm lost
}
}
Can anyone shed some light on how I might do this? All insight appreciated.
w001y
Try this:
$files=array("home--lists--country--create_a_country.jpg","home--lists--country--list_countries.jpg","profile--edit--account.jpg","profile--my_account.jpg","shop--orders--list_orders.jpg");
$master_array=array();
foreach($files as $file)
{
$file=explode("--",$file);
$cache=end($file);
while($level=prev($file))
{
$cache=array($level=>$cache);
}
$master_array=array_merge_recursive($master_array,$cache);
}
print_r($master_array);
Live demo
This question already has answers here:
How to re-index the values of an array in PHP? [duplicate]
(3 answers)
Closed 2 years ago.
I have an array:
$array = array(1,2,3,4,5);
If I were to dump the contents of the array they would look like this:
array(5) {
[0] => int(1)
[1] => int(2)
[2] => int(3)
[3] => int(4)
[4] => int(5)
}
When I loop through and unset certain keys, the index gets all jacked up.
foreach($array as $i => $info)
{
if($info == 1 || $info == 2)
{
unset($array[$i]);
}
}
Subsequently, if I did another dump now it would look like:
array(3) {
[2] => int(3)
[3] => int(4)
[4] => int(5)
}
Is there a proper way to reset the array so it's elements are Zero based again ??
array(3) {
[0] => int(3)
[1] => int(4)
[2] => int(5)
}
Try this:
$array = array_values($array);
Using array_values()
Got another interesting method:
$array = array('a', 'b', 'c', 'd');
unset($array[2]);
$array = array_merge($array);
Now the $array keys are reset.
Use array_splice rather than unset:
$array = array(1,2,3,4,5);
foreach($array as $i => $info)
{
if($info == 1 || $info == 2)
{
array_splice($array, $i, 1);
}
}
print_r($array);
Working sample here.
Just an additive.
I know this is old, but I wanted to add a solution I don't see that I came up with myself. Found this question while on hunt of a different solution and just figured, "Well, while I'm here."
First of all, Neal's answer is good and great to use after you run your loop, however, I'd prefer do all work at once. Of course, in my specific case I had to do more work than this simple example here, but the method still applies. I saw where a couple others suggested foreach loops, however, this still leaves you with after work due to the nature of the beast. Normally I suggest simpler things like foreach, however, in this case, it's best to remember good old fashioned for loop logic. Simply use i! To maintain appropriate index, just subtract from i after each removal of an Array item.
Here's my simple, working example:
$array = array(1,2,3,4,5);
for ($i = 0; $i < count($array); $i++) {
if($array[$i] == 1 || $array[$i] == 2) {
array_splice($array, $i, 1);
$i--;
}
}
Will output:
array(3) {
[0]=> int(3)
[1]=> int(4)
[2]=> int(5)
}
This can have many simple implementations. For example, my exact case required holding of latest item in array based on multidimensional values. I'll show you what I mean:
$files = array(
array(
'name' => 'example.zip',
'size' => '100000000',
'type' => 'application/x-zip-compressed',
'url' => '28188b90db990f5c5f75eb960a643b96/example.zip',
'deleteUrl' => 'server/php/?file=example.zip',
'deleteType' => 'DELETE'
),
array(
'name' => 'example.zip',
'size' => '10726556',
'type' => 'application/x-zip-compressed',
'url' => '28188b90db990f5c5f75eb960a643b96/example.zip',
'deleteUrl' => 'server/php/?file=example.zip',
'deleteType' => 'DELETE'
),
array(
'name' => 'example.zip',
'size' => '110726556',
'type' => 'application/x-zip-compressed',
'deleteUrl' => 'server/php/?file=example.zip',
'deleteType' => 'DELETE'
),
array(
'name' => 'example2.zip',
'size' => '12356556',
'type' => 'application/x-zip-compressed',
'url' => '28188b90db990f5c5f75eb960a643b96/example2.zip',
'deleteUrl' => 'server/php/?file=example2.zip',
'deleteType' => 'DELETE'
)
);
for ($i = 0; $i < count($files); $i++) {
if ($i > 0) {
if (is_array($files[$i-1])) {
if (!key_exists('name', array_diff($files[$i], $files[$i-1]))) {
if (!key_exists('url', $files[$i]) && key_exists('url', $files[$i-1])) $files[$i]['url'] = $files[$i-1]['url'];
$i--;
array_splice($files, $i, 1);
}
}
}
}
Will output:
array(1) {
[0]=> array(6) {
["name"]=> string(11) "example.zip"
["size"]=> string(9) "110726556"
["type"]=> string(28) "application/x-zip-compressed"
["deleteUrl"]=> string(28) "server/php/?file=example.zip"
["deleteType"]=> string(6) "DELETE"
["url"]=> string(44) "28188b90db990f5c5f75eb960a643b96/example.zip"
}
[1]=> array(6) {
["name"]=> string(11) "example2.zip"
["size"]=> string(9) "12356556"
["type"]=> string(28) "application/x-zip-compressed"
["deleteUrl"]=> string(28) "server/php/?file=example2.zip"
["deleteType"]=> string(6) "DELETE"
["url"]=> string(45) "28188b90db990f5c5f75eb960a643b96/example2.zip"
}
}
As you see, I manipulate $i before the splice as I'm seeking to remove the previous, rather than the present item.
I use $arr = array_merge($arr); to rebase an array. Simple and straightforward.
100% working for me ! After unset elements in array you can use this for re-indexing the array
$result=array_combine(range(1, count($your_array)), array_values($your_array));
Late answer but, after PHP 5.3 could be so;
$array = array(1, 2, 3, 4, 5);
$array = array_values(array_filter($array, function($v) {
return !($v == 1 || $v == 2);
}));
print_r($array);
Or you can make your own function that passes the array by reference.
function array_unset($unsets, &$array) {
foreach ($array as $key => $value) {
foreach ($unsets as $unset) {
if ($value == $unset) {
unset($array[$key]);
break;
}
}
}
$array = array_values($array);
}
So then all you have to do is...
$unsets = array(1,2);
array_unset($unsets, $array);
... and now your $array is without the values you placed in $unsets and the keys are reset
In my situation, I needed to retain unique keys with the array values, so I just used a second array:
$arr1 = array("alpha"=>"bravo","charlie"=>"delta","echo"=>"foxtrot");
unset($arr1);
$arr2 = array();
foreach($arr1 as $key=>$value) $arr2[$key] = $value;
$arr1 = $arr2
unset($arr2);