How do I merge all the array items into a single string?
Use the implode function.
For example:
$fruits = array('apples', 'pears', 'bananas');
echo implode(',', $fruits);
Try this from the PHP manual (implode):
<?php
$array = array('lastname', 'email', 'phone');
$comma_separated = implode(",", $array);
echo $comma_separated; // lastname, email, and phone
// Empty string when using an empty array:
var_dump(implode('hello', array())); // string(0) ""
?>
If you are trying to just concatenate all of strings in the array, then you should look at implode().
$array1 = array(
"one",
"two",
)
$array2 = array(
"three",
"four",
)
$finalarr = array_merge($array1, $array2);
$finalarr = implode(",", $finalarr);
will produce this one,two,three,four
You can use join. It's an alias for implode, and in my opinion more readable:
$fruits = array('apples', 'pears', 'bananas');
echo join(',', $fruits);
join(" -- ", Array("a", "b")) == "a -- b"
actually join is an alias for the implode function.
If you want to merge the string representation of a group of objects into a single string, you can use implode on an array of those objects. The objects' classes just have to have the __toString() magic method defined.
class myClass {
protected $name;
protected $value;
public function __construct($name,$value) {
$this->name = $name;
$this->value = $value;
}
public function __toString() {
return $this->name . '/' . $this->value;
}
}
$obj1 = new myClass('one',1);
$obj2 = new myClass('two',2);
$obj_array = array($obj1, $obj2);
$string_of_all_objects = implode('|',$obj_array);
echo $string_of_all_objects; // 'one/1|two/2'
I found that trick useful to quickly get a string representation of a group of objects for display on a webpage. No need to loop through the object array with foreach and using echo $obj->get('name').
EDIT: And here's and example with a "collection" class. I have 2 outputs (echos) at the end. The 2nd one should work, but I'm not sure about the 1st.
class myCollectionClass implements IteratorAggregate {
protected $objects = array();
public function __construct() {};
public function add(myClass $object) {
$this->objects[] = $object;
return $this; // fluid
}
public function getIterator() { // for the interface
return new ArrayIterator($this->objects);
}
public function __toString() {
return implode($this->objects);
}
}
$my_collection = new myCollectionClass();
$my_collection->add($obj1)->add($obj2); // add both myClass objects to the collection. can do in one line because fluid
//echo implode('|',$my_collection); // Comment out myCollectionClass's __toString method to test this. does it work? I'm not sure. But the next line will work thanks to myCollectionClass' __toString, which itself uses myClass's __toString
echo $my_collection; // same output as previous block before EDIT.
$array= array( "Alfred Hitchcock", "Stanley Kubrick", "Martin Scorsese", "Fritz Lang" );
$string="";
foreach ( $tempas $array) {
$string=$string.",".$temp;
}
foreach($array as $key => $value) {
$string .= $value .' ';
}
For Multi Array such as:
$multi_arrays = array(
0 => array('model' => 'Product 1'),
1 => array('model' => 'Product 2'),
2 => array('model' => 'Product 3'),
3 => array('model' => 'Product 4'));
$pattern = array('/\[/', '/\]/', '/{"model":/', '/}/', '/\"/');
$str_models = preg_replace($pattern, '', json_encode( $multi_arrays));
The result will be:
Product 1, Product 2, Product 3, Product 4
You can change pattern for get any result you want!
Related
I have for example:
$onePack = $pack->findByCity('London'); //this return me 3 objects from class Pack
$twoPack = $pack->findByCity('New York'); //this return me 2 objects from class Pack
$threePack = $pack->findByCity('Los Angeles'); //this return me 5 objects from class Pack
And I would like merge this object to one variable and next use with foreach.
I know - i can make array, for example:
$array = array();
and next:
foreach($onePack as $one) {
$array[] = $one;
}
foreach($twoPack as $two) {
$array[] = $two;
}
foreach($threePack as $three) {
$array[] = $three;
}
And now I have all objects (10) in one variable, but maybe is better way for this?
How about:
$cities = array('London', 'New York', 'Los Angeles');
$arr = array();
foreach($cities as $city) {
$arr[] = $pack->findByCity($city);
}
You can add new cities to the cities array and they will all be added to the $arr variable
You can use array_merge
$arr = array_merge($pack1->toArray(), $pack2->toArray(), $pack3->toArray());
And create an toArray method in the pack object.
I have a simple Template engine and I have a problem giving it a data from assoc array. Can anybody give me an advice? In method getStatisticData, I give an assoc array as first variable $data. My input array is in the form:
[0] => Array
(
[OrderNumber] => 1
[Name] => Zahid
[Total revenue] => 8363.38
)
I'm trying to get data from it using foreach but it doesn't work. I'm getting notice
Notice: Array to string conversion in C:\Server\htdocs\Task\lib\TemplateGen.php on line 34
protected function getStatisticData($data, $template){
$text = "";
if($data === false) {
return "We don't have any data in database";
}
foreach($data as $key => $value){
$data[$key] = $value;
$text .= $this->template_gen->getReplaceTemplate($data ,$template);
}
return $text;
}
getReplaceContent and associated methods from TemplateGen.php:
private function getReplaceContent($dataString, $content)
{
$search = array();
$replace = array();
$i = 0;
foreach ($dataString as $key => $value) {
$search[$i] = "%$key%";
$replace[$i] = $value;
$i++;
}
return str_replace($search, $replace, $content); ## LINE 34
}
function getReplaceTemplate($dataString, $template)
{
return $this->getReplaceContent($dataString, $this->getTemplate($template));
}
function getTemplate($name)
{
return $content = file_get_contents($this->config->tpl_path . $name . ".tpl");
}
UPDATE:
I got 2 new errors
Warning: implode(): Invalid arguments passed in C:\Server\htdocs\Task\lib\TemplateGen.php on line 28
Fatal error: Cannot redeclare add_percent() (previously declared in C:\Server\htdocs\Task\lib\TemplateGen.php:25) in C:\Server\htdocs\Task\lib\TemplateGen.php on line 25
Line 25:
function add_percent($i) {
Line 28:
return implode("", str_replace(array_map("add_percent", array_keys($dataString)), array_values($dataString),$content));
UPDATE2:
In theory, everything provided in new method should work very well. But there are same problems which were at the beginning
Notice: Array to string conversion in C:\Server\htdocs\Task\lib\TemplateGen.php on line 44`
line 44 :
return str_replace(
array_map($addPercent, array_keys($data)), array_values($data), $template
);
But if I'am using my getStatisticData instead of yours, it works but there are many other errors
My method :
protected function getStatisticData($data, $template){
$text = array();
if($data === false) {
return "We don't have any data in database";
}
$i=0;
foreach($data as $dataString){
if (!empty($data[$i+1])){
foreach($dataString as $key => $value){
$dataString[$i][$key] = $dataString[$i][$value];
}}
$text .= $this->template_gen->getReplaceTemplate($dataString ,$template);
}
return $text;
}
Your code is rather inefficient at present, and it's leading to some isuues. Let's look at the first method you posted:
protected function getStatisticData($data, $template){
$text = "";
if($data === false) {
return "We don't have any data in database";
}
foreach($data as $key => $value){
$data[$key] = $value;
$text .= $this->template_gen->getReplaceTemplate($data ,$template);
}
return $text;
}
The foreach loop is doing the same thing for each key/value pair (plus $data[$key] = $value is redundant as you are already getting each key and value in the foreach loop), so you could eliminate the loop, and replace it with something like this:
protected function getStatisticData($data, $template){
if ($data === false) {
return "We don't have any data in database";
}
return $this->template_gen->getReplaceTemplate($data, $template);
}
Similarly for getReplaceContent - you're basically using the array keys and array values as the search and the replacement values. You can use PHP's handy array_keys and array_values instead of building new arrays. The catch is that the array keys need to be surrounded by %, but that is easy to do using array_map - just define a function that will take in a string and add % to either end of it, and then array_map it to your array keys:
private function getReplaceContent($data, $template)
{
$addPercent = function( $i ){
return "%$i%";
};
return str_replace(
array_map( $addPercent, array_keys($data)), array_values($data), $template
);
}
Now, calling getStatisticData will return the template text with all the replaced data in it.
Sample input:
$arr = array(
'OrderNumber' => 1,
'Name' => 'Zahid',
'Total revenue' => '8363.38'
);
$template =
'<p>Name: %Name%<br>
Total revenue: %Total revenue%<br>
Order number: %OrderNumber%</p>';
Output of getStatisticData:
<p>Name: Zahid<br>
Total revenue: 8363.38<br>
Order number: 1</p>
EDIT: it is not clear from the OP what the input to getStatisticData is, but it looks like it is supposed to be an array of associative arrays. If this is so, the code for getStatisticData should be altered as follows:
protected function getStatisticData($dataArray, $template){
if ($dataArray === false) {
return "We don't have any data in database";
}
$text = "";
foreach ($dataArray as $aa) {
$text .= $this->template_gen->getReplaceTemplate($aa, $template);
}
return $text;
}
Sample input:
$arr =
[
[ 'OrderNumber' => 1,
'Name' => 'Zahid',
'Total revenue' => '8363.38'
],
[ 'OrderNumber' => 2,
'Name' => 'Paul',
'Total revenue' => '123.45'
],
[ 'OrderNumber' => 3,
'Name' => 'Jane',
'Total revenue' => '567.89'
],
];
Output:
<p>Name: Zahid<br>
Total revenue: 8363.38<br>
Order number: 1</p>
<p>Name: Paul<br>
Total revenue: 123.45<br>
Order number: 2</p>
<p>Name: Jane<br>
Total revenue: 567.89<br>
Order number: 3</p>
I'm assuming that the associative array $data has simply strings in it. I'm assuming that the $data array has its keys as the template placeholder and the value as the value to input.
If so, and if you're trying to get a single string, then consider doing this:
protected function getStatisticData($data, $template) {
if ($data === false) {
return "We don't have any data in the database.";
}
return this->template_gen->getReplaceTemplate($data, $template);
}
private function getReplaceContent($dataString, $content) {
content = '';
foreach ($dataString as $key => $value) {
$content .= str_replace("%{$key}%", $value, $content);
}
return $content;
}
You don't need quite as many foreach loops. One should do just fine.
I write a code for sync two array and know which was must delete and which was add to new array.
<?php
$currentArray = array('ali', 'hasan', 'husein'); //base array read from database
$saveArray = array('husein', 'Hasan', 'taghi'); //requested item for save/delete in database
$deleteArray = array();
$addArray = array();
$currentArray = array_map('strtolower', $currentArray);
$saveArray = array_map('strtolower', $saveArray);
foreach ($currentArray as $a) {
if (!in_array($a, $saveArray))
$deleteArray[] = $a;
}
foreach ($saveArray as $a) {
if (!in_array($a, $currentArray))
$addArray[] = $a;
}
echo 'must be deleted:';
var_dump($deleteArray);
echo 'must be added:';
var_dump($addArray);
?>
Output:
must be deleted:
array
0 => string 'ali' (length=3)
must be added:
array
0 => string 'taghi' (length=5)
Now, Do you thinks is it better, faster and simpler code for this action?
You can use array_udiff() for this, using strcasecmp() as the callback function.
$currentArray = array('ali', 'hasan', 'husein');
$saveArray = array('husein', 'Hasan', 'taghi');
$deleteArray = array_udiff($currentArray, $saveArray, 'strcasecmp');
$addArray = array_udiff($saveArray, $currentArray, 'strcasecmp');
See demo
The values must be the same.
$currentArray = array_map('strtolower', $currentArray);
$saveArray = array_map('strtolower', $saveArray);
And basically use use Array diff.
$deleteArray = array_diff($currentArray, $saveArray);
$addArray = array_diff($saveArray, $currentArray);
Because this seems like what I have to do to get this effect:
$arr = ['a'=>'first', 'b'=>'second', ...];
$iter = new ArrayIterator( $arr );
// Do a bunch of iterations...
$iter->next();
// ...
$new_iter = new ArrayIterator( $arr );
while( $new_iter->key() != $iter->key() ) {
$new_iter->next();
}
Edit: Also, just to be clear, should I NOT be modifying the base array with unset()? I figure the array iterator stores its own copy of the base array, so using offsetUnset() doesn't seem right.
ArrayIterator does not implement a tell() function, but you can emulate this, and then use seek() to go to the position you want. Here's an extended class that does just that:
<?php
class ArrayIteratorTellable extends ArrayIterator {
private $position = 0;
public function next() {
$this->position++;
parent::next();
}
public function rewind() {
$this->position = 0;
parent::rewind();
}
public function seek($position) {
$this->position = $position;
parent::seek($position);
}
public function tell() {
return $this->position;
}
public function copy() {
$clone = clone $this;
$clone->seek($this->tell());
return $clone;
}
}
?>
Use:
<?php
$arr = array('a' => 'first', 'b' => 'second', 'c' => 'third', 'd' => 'fourth');
$iter = new ArrayIteratorTellable( $arr );
$iter->next();
$new_iter = new ArrayIteratorTellable( $arr );
var_dump($iter->current()); //string(6) "second"
var_dump($new_iter->current()); //string(6) "first"
$new_iter->seek($iter->tell()); //Set the pointer to the same as $iter
var_dump($new_iter->current()); //string(6) "second"
?>
DEMO
Alternately, you can use the custom copy() function to clone the object:
<?php
$arr = array('a' => 'first', 'b' => 'second', 'c' => 'third', 'd' => 'fourth');
$iter = new ArrayIteratorTellable( $arr );
$iter->next();
$new_iter = $iter->copy();
var_dump($iter->current()); //string(6) "second"
var_dump($new_iter->current()); //string(6) "second"
?>
DEMO
The only solution I thought of is using a copy of current array
$arr = ['a'=>'first', 'b'=>'second'];
$iter = new ArrayIterator( $arr );
// Do a bunch of iterations...
$iter->next();
var_dump($iter->current());
// ...
$arr2 = $iter->getArrayCopy();
$new_iter = new ArrayIterator( $arr2 );
while( $new_iter->key() != $iter->key() ) {
var_dump($new_iter->current());
$new_iter->next();
}
I want to create an array using recursion in Codeigniter. my function make_tree() in controller is :
function make_tree($customer_id,$arr = array()){
$ctree = $this->customer_operations->view_customer_tree($customer_id);
foreach($ctree as $v):
echo $customer_id = $v['customer_id'];
array_push($arr, $customer_id);
$this->make_tree($customer_id);
endforeach;
var_dump($arr);
}
But the var_dump($arr) and echo results output like:
1013
array
empty
array
0 => string '13' (length=2)
11
array
empty
array
0 => string '10' (length=2)
1 => string '11' (length=2)
How can I make a single array of all the three outputs, ie an array with elements 13,10,11
you need to send the array with the parameters otherwise a new array is created.
function make_tree($customer_id,$arr = array()){
$ctree = $this->customer_operations->view_customer_tree($customer_id);
foreach($ctree as $v):
echo $customer_id = $v['customer_id'];
array_push($arr, $customer_id);
$this->make_tree($customer_id, $arr);
endforeach;
var_dump($arr);
}
PS: I don't know what you are trying to do exactly, but you probably need to add a stopping condition that is going to return the final array, unless you want to pass it by reference.
UPDATE
Here is one way to do it:
function make_tree($customer_id, &$arr)
{
$ctree = $this->customer_operations->view_customer_tree($customer_id);
foreach($ctree as $v):
$customer_id = $v['customer_id'];
array_push($arr, $customer_id);
$this->make_tree($customer_id, $arr);
endforeach;
}
and this is how you'd use it:
$final_array = array();
make_tree($some_customer_id, $final_array);
// now the $final_array is populated with the tree data
You can use class scope.
class TheController {
private $arr = array();
function make_tree($customer_id){
$ctree = $this->customer_operations->view_customer_tree($customer_id);
foreach($ctree as $v) {
$customer_id = $v['customer_id'];
array_push($this->arr, $customer_id);
$this->make_tree($customer_id);
}
}
}