PHP ellipsis using substr and concatenation - php

foreach($products as $val)
{
$name = $val["name"];
if(strlen($name) > 5){
$name = substr($name,0,5) . '..';
}
}
I have a list of string, and I want to add dot dot at the end of it using PHP, but above code return 0?

If you want to make changes you need to reference & the copy in the foreach.
Example:
foreach($products as &$val) {
// ^ reference
if(strlen($val['name']) > 5) {
$val['name'] = substr($val['name'], 0, 5) . ' ...';
}
}
Or if you are not comfortable this way, could also use the key of the foreach to point it directly to that index.
foreach($products as $key => $val) {
if(strlen($val['name']) > 5) {
$products[$key]['name'] = substr($val['name'], 0, 5) . ' ...';
// ^ use $key
}
}
And lastly, if you do not want any changes at all (just output echo), then this:
foreach($products as $key => $val) {
$name = $val['name'];
if(strlen($name) > 5) {
$name = substr($name['name'], 0, 5) . '...';
}
echo $name; // you forgot to echo
}

your question is a bit unclear as to where you are stuck.
If you want to modify your $products array, then Ghost offered you one solution.
If you simply want an array of shortened product names, I would store them in a new array since you might need the full names later.
$shortNames = array();
foreach($products as $val)
{
$name = $val["name"];
if(strlen($name) > 5){
$name = substr($name,0,5) . '..';
}
$shortNames[] = $name;
}
You wrote
but above code return 0
if this code is inside a function, maybe you simple missed to return the result?
for example with my code, put return $shortNames; at the end of the function

Related

PHP -- identifying last key in foreach to eleminate last delimeter

I've been trying to get this to work and while I have tried many methods posted on this site on other pages, I can't get any of them to work.
I need to identify the last key so that my results don't have a , at the end. This sounds like such and easy task but I just cant seem to get it to work! At this point I'm guessing I've just had a typo or something that I overlooked. Any help would be greatly appreciated.
This is what I have:
<?php
$searchString = $_GET["s"];
$prefix = 'http://link_to_my_xml_file.xml?q=';
$suffix = '&resultsPerPage=100';
$file = $prefix . $searchString . $suffix;
if(!$xml = simplexml_load_file($file))
exit('False'.$file);
foreach($xml->results->result as $item) {
echo $item->sku . ",";
}
?>
Now this works just fine, it just has a , at the end:
12345,23456,34567,45678,
For reference my xml file is laid out like: results->result->sku, but with a lot more mixed in. I'm just singling out the fields.
Consider identifying the first instead?
$first = true;
foreach($xml->results->result as $item) {
if ($first) {
$first = false;
} else {
echo ',';
}
echo $item->sku;
}
Use rtrim()
foreach($xml->results->result as $item) {
$mystr .= $item->sku . ",";
}
echo rtrim($mystr, ",")
Should output:
12345,23456,34567,45678
Demo!
If your keys are in numerical order like: 0, 1, 2, 3 etc this could be a solution:
foreach($xml->results->result as $key => $item)
{
if( $key > 0 ) echo ", ";
echo $item->sku
}
Possible solution #1:
$first = true;
foreach ($xml->results->result as $item) {
if ($first) {
$first = false;
} else {
echo ', ';
}
echo $item->sku;
}
Possible solution #2:
$items = array();
foreach ($xml->results->result as $item) {
$items[] = $item->sku;
}
echo join(', ', $items);
You can just put everything in a string and then run:
substr($yourstr, 0, -1);
on your code to remove the last character:
http://de1.php.net/manual/en/function.substr.php
Or get the total number of entries in your array and count your position

PHP Array foreach question

I have a question about arrays and foreach.
If i have an array like this:
$test_arr = array();
$test_arr['name1'] = "an example sentence";
$test_arr['anything'] = "dsfasfasgsdfg";
$test_arr['code'] = "4334refwewe";
$test_arr['empty1'] = "";
$test_arr['3242'] = "";
how can I do a foreach and "pick" only the ones that have values? (in my array example, would only take the first 3 ones, name1, anything and code).
I tried with
foreach ($test_arr as $test) {
if (strlen($test >= 1)) {
echo $test . "<br>";
}
}
but it doesn't work. Without the "if" condition it works, but empty array values are taken into consideration and I don't want that (because I need to do a <br> after each value and I don't want a <br> if there is no value)
Sorry if I don't explain myself very well, I hope you understand my point. Shouldn't be too difficult I guess..
Thanks for your help !
Maybe will work
foreach ($test_arr as $test) {
if (strlen($test)!=="") {
echo $test . "<br>";
}
}
Your solution with corrected syntax:
foreach ($test_arr as $test) {
if (strlen($test)>=1) {
echo $test . "<br>";
}
}
Since empty strings are false, you could just do this (but you'd exclude 0's with the if):
foreach ($test_arr as $key => $val) {
if ($val) {
echo $val. "<br>";
}
}
If it has to be an empty string then (excluding 0 and FALSE):
foreach ($test_arr as $key => $val) {
// the extra = means that this will only return true for strings.
if ($val !== '' ) {
echo $val. "<br>";
}
}
Since it looks like you're using an associative array, you should be able to do this:
foreach( $test_arr as $key => $value )
{
if( $value != "" )
{
echo $value . "<br />";
}
}
As shown, you can test $value for an empty string directly. Since this is precisely the test you are trying to accomplish, I would hope that this would solve your problem perfectly.
On another note, this is pretty straight forward and should be very maintainable in the future when you've forgotten exactly what it was that you were doing!
You are better off to use a while loop like this:
while(list($test_key, $test_value) = each($test_arr))
{
if($test_value != "") { echo $test_value . "<br/>"; }
}
reset($test_arr);
If your array gets large, the while will be much faster. Even on small arrays, I have noticed a big difference in the execution time.
And if you really don't want the array key. You can just do this:
while(list(, $test_value) = each($test_arr))
{
if($test_value != "") { echo $test_value . "<br/>"; }
}
reset($test_arr);
You can check if the value is emtpy with empty().
Note that values like 0 or false are considered empty as well, so you might have to check for string length instead.
just a simple typing error:
foreach ($test_arr as $test) {
if (strlen($test) >= 1) {
echo $test . "<br>";
}
}
Try this:
foreach ($test_arr as $test) {
if (strlen($test) > 0) {
echo $test . "<br>";
}
}

Replace value in array doesn't work

I'm going crazy, spent a couple of hours trying different methods in replace values in arrays, but I can't get it to work.
foreach($potentialMatches as $potentialKey)
{
$searchKeywordQuery = "SELECT keyword, id FROM picture WHERE id='$potentialKey'";
$searchKeywords = mysql_query($searchKeywordQuery) or die(mysql_error());
while ($searchKeyWordsRow = mysql_fetch_array($searchKeywords))
{
$keyword = $searchKeyWordsRow['keyword'];
$pictureKeywordArray[$searchKeyWordsRow['id']]['keywords'] = explode(",", $keyword);
$pictureKeywordArray[$searchKeyWordsRow['id']]['match'] = 4;
}
}
foreach($pictureKeywordArray as $key = > $picValue)
{
foreach($picValue['keywords'] as $key = > $picIdValue)
{
if ($picIdValue == $searchIdKey)
{
echo $picValue['match'];
$picValue['match']++;
echo $picValue['match'];
}
}
}
foreach($pictureKeywordArray as $key = > $picValue)
{
echo $picValue['match'];
}
I'm novice as you can see, When I echo the picValue['match'] in the foreach loop it gives me a correct value after "++". But then below when I call the array again it gives me the value of 4 instead of 5 as intended. Thanks in advance for any help with this.
Cause you work with the item copy in first case try $pictureKeywordArray[$key]['match'] instead of $picValue['match']
In that second foreach you need to call it by reference:
foreach($pictureKeywordArray as $key => &$picValue)
{ //^-- `&` makes it by reference
foreach($picValue['keywords'] as $key => $picIdValue)
{
if ($picIdValue == $searchIdKey)
{
echo $picValue['match'];
$picValue['match']++; //now updates what you want it to update
echo $picValue['match'];
}
}
}
foreach works on a copy of the data. You must use a reference to modify the original:
foreach ($foo as $i => &$f)
{
$f++;
}
unset($f); // important to do this if you ever want to reuse that variable later

Comparing two identical strings returns false in PHP

I'm trying to compare two strings. When I echo them, they appear to be identical, yet when I compare them with the '==' operator, it returns false. For example, when running the code below on my database. It outputs things like "APPARENTLY Apple does not equal Apple". What is the reason?
if ($this->data['list_text']) { // The user has entered into textarea
$list = nl2br($this->data['list_text']);
$list_array = explode('<br />', $list);
$ranking = 1;
$company_array = $this->CompanyList->CompanyRanking->Company->find('list', null);
// This is the comparison bit
foreach ($list_array as $key => $value) {
$companyId = null;
foreach ($company_array as $key2 => $value2) {
if ($value2 != $value) {
echo 'APPARENTLY ' . $value2 . ' does not equal ' . $value;
} else {
$companyId = $key2;
break;
}
}
$this->data['CompanyRanking'][$ranking]['ranking'] = $ranking;
$this->data['CompanyRanking'][$ranking]['company_id'] = $companyId;
$ranking++;
}
}
Try var_dump() instead of echo.
echo 'APPARENTLY '.$value2.' does not equal '.$value;
echo '<pre>Debug: ';
echo 'value='; var_dump($value);
echo 'value2='; var_dump($value2);
echo '</pre>';
It provides additional information. E.g. the actual type. And the length of strings.
Do the strings have any extra whitespace you're not seeing? Try trimming them.
Try to check the encoding of both strings compared.
Maybe it is UTF-8 compared with ISO 8859-1 with some weird characters.
I agree with Olafur. I removed trim and replaced it with a preg_replace due to the fact you are assuming $value and $value2 are companyIDs. You can make a quick modification on these if the companyID is supposed to be alphanumeric, contain hyphens, etc... This version should do it:
if ($this->data['list_text']) {
$list = nl2br($this->data['list_text']);
$list_array = explode('<br />', $list);
$ranking = 1;
$company_array = $this->CompanyList->CompanyRanking->Company->find('list',null);
foreach ($list_array as $key => $value) {
// remove any non digit characters
$value = preg_replace('/[^0-9]/i','', $value);
$companyId = null;
foreach ($company_array as $key2 => $value2) {
// remove any non digit characters
$value2 = preg_replace('/[^0-9]/i','', $value2);
if ($value2 != $value) {
echo 'values not equal';
} else {
$companyId = $key2;
break;
}
}
$this->data['CompanyRanking'][$ranking]['ranking'] = $ranking;
$this->data['CompanyRanking'][$ranking]['company_id'] = $companyId;
$ranking++;
}
}
Try trim() for any white space as well as var_dump() to see if anything else is being passed with it.

Find the last element of an array while using a foreach loop in PHP

I am writing a SQL query creator using some parameters. In Java, it's very easy to detect the last element of an array from inside the for loop by just checking the current array position with the array length.
for(int i=0; i< arr.length;i++){
boolean isLastElem = i== (arr.length -1) ? true : false;
}
In PHP they have non-integer indexes to access arrays. So you must iterate over an array using a foreach loop. This becomes problematic when you need to take some decision (in my case to append or/and parameter while building query).
I am sure there must be some standard way of doing this.
How do you solve this in PHP?
It sounds like you want something like this:
$numItems = count($arr);
$i = 0;
foreach($arr as $key=>$value) {
if(++$i === $numItems) {
echo "last index!";
}
}
That being said, you don't -have- to iterate over an "array" using foreach in php.
You could get the value of the last key of the array using end(array_keys($array)) and compare it to the current key:
$last_key = end(array_keys($array));
foreach ($array as $key => $value) {
if ($key == $last_key) {
// last element
} else {
// not last element
}
}
Note: This doesn't work because calling next() advances the array pointer, so you're skipping every other element in the loop
why so complicated?
foreach($input as $key => $value) {
$ret .= "$value";
if (next($input)==true) $ret .= ",";
}
This will add a , behind every value except the last one!
When toEnd reaches 0 it means it is at the last iteration of the loop.
$toEnd = count($arr);
foreach($arr as $key=>$value) {
if (0 === --$toEnd) {
echo "last index! $value";
}
}
The last value is still available after the loop, so if you just want to use it for more stuff after the loop this is better:
foreach($arr as $key=>$value) {
//something
}
echo "last index! $key => $value";
If you do not want to treat the last value as special inside loops. This should be faster if you have large arrays. (If you reuse the array after the loop inside the same scope you have to "copy" the array first).
//If you use this in a large global code without namespaces or functions then you can copy the array like this:
//$array = $originalArrayName; //uncomment to copy an array you may use after this loop
//end($array); $lastKey = key($array); //uncomment if you use the keys
$lastValue = array_pop($array);
//do something special with the last value here before you process all the others?
echo "Last is $lastValue", "\n";
foreach ($array as $key => $value) {
//do something with all values before the last value
echo "All except last value: $value", "\n";
}
//do something special with the last value here after you process all the others?
echo "Last is $lastValue", "\n";
And to answer your original question "in my case to append or/and parameter while building query"; this will loop over all the values, then join them together to a string with " and " between them but not before the first value or after the last value:
$params = [];
foreach ($array as $value) {
$params[] = doSomething($value);
}
$parameters = implode(" and ", $params);
There are already many answers, but it's worth to look into iterators as well, especially as it has been asked for a standard way:
$arr = range(1, 3);
$it = new CachingIterator(new ArrayIterator($arr));
foreach($it as $key => $value)
{
if (!$it->hasNext()) echo 'Last:';
echo $value, "\n";
}
You might find something that does work more flexible for other cases, too.
One way could be to detect if the iterator has next. If there is no next attached to the iterator it means you are in the last loop.
foreach ($some_array as $element) {
if(!next($some_array)) {
// This is the last $element
}
}
SINCE PHP 7.3 :
You could get the value of the last key of the array using array_key_last($array) and compare it to the current key:
$last_key = array_key_last($array);
foreach ($array as $key => $value) {
if ($key == $last_key) {
// last element
} else {
// not last element
}
}
to get first and last element from foreach array
foreach($array as $value) {
if ($value === reset($array)) {
echo 'FIRST ELEMENT!';
}
if ($value === end($array)) {
echo 'LAST ITEM!';
}
}
So, if your array has unique array values, then determining last iteration is trivial:
foreach($array as $element) {
if ($element === end($array))
echo 'LAST ELEMENT!';
}
As you see, this works if last element is appearing just once in array, otherwise you get a false alarm. In it is not, you have to compare the keys (which are unique for sure).
foreach($array as $key => $element) {
end($array);
if ($key === key($array))
echo 'LAST ELEMENT!';
}
Also note the strict coparision operator, which is quite important in this case.
Don't add a comma after the last value:
The array:
$data = ['lorem', 'ipsum', 'dolor', 'sit', 'amet'];
The function:
$result = "";
foreach($data as $value) {
$resut .= (next($data)) ? "$value, " : $value;
}
The result:
print $result;
lorem, ipsum, dolor, sit, amet
You can still use that method with associative arrays:
$keys = array_keys($array);
for ($i = 0, $l = count($array); $i < $l; ++$i) {
$key = $array[$i];
$value = $array[$key];
$isLastItem = ($i == ($l - 1));
// do stuff
}
// or this way...
$i = 0;
$l = count($array);
foreach ($array as $key => $value) {
$isLastItem = ($i == ($l - 1));
// do stuff
++$i;
}
Assuming you have the array stored in a variable...
foreach($array as $key=>$value)
{
echo $value;
if($key != count($array)-1) { echo ", "; }
}
If you need to do something for every element except either the first or the last and only if there is more than one element in the array, I prefer the following solution.
I know there are many solutions above and posted months/one year before mine, but this is something I feel is fairly elegant in its own right. The check every loop is also a boolean check as opposed to a numeric "i=(count-1)" check, which may allow for less overhead.
The structure of the loop may feel awkward, but you can compare it to the ordering of thead (beginning), tfoot (end), tbody (current) in HTML table tags.
$first = true;
foreach($array as $key => $value) {
if ($first) {
$first = false;
// Do what you want to do before the first element
echo "List of key, value pairs:\n";
} else {
// Do what you want to do at the end of every element
// except the last, assuming the list has more than one element
echo "\n";
}
// Do what you want to do for the current element
echo $key . ' => ' . $value;
}
For instance, in web development terms, if you want to add a border-bottom to every element except the last in an unordered list (ul), then you can instead add a border-top to every element except the first (the CSS :first-child, supported by IE7+ and Firefox/Webkit supports this logic, whereas :last-child is not supported by IE7).
You can feel free to reuse the $first variable for each and every nested loop as well and things will work just fine since every loop makes $first false during the first process of the first iteration (so breaks/exceptions won't cause issues).
$first = true;
foreach($array as $key => $subArray) {
if ($first) {
$string = "List of key => value array pairs:\n";
$first = false;
} else {
echo "\n";
}
$string .= $key . '=>(';
$first = true;
foreach($subArray as $key => $value) {
if ($first) {
$first = false;
} else {
$string .= ', ';
}
$string .= $key . '=>' . $value;
}
$string .= ')';
}
echo $string;
Example output:
List of key => value array pairs:
key1=>(v1_key1=>v1_val1, v1_key2=>v1_val2)
key2=>(v2_key1=>v2_val1, v2_key2=>v2_val2, v2_key3=>v2_val3)
key3=>(v3_key1=>v3_val1)
This should be the easy way to find the last element:
foreach ( $array as $key => $a ) {
if ( end( array_keys( $array ) ) == $key ) {
echo "Last element";
} else {
echo "Just another element";
}
}
Reference : Link
I have a strong feeling that at the root of this "XY problem" the OP wanted just implode() function.
As your intention of finding the EOF array is just for the glue. Get introduced to the below tactic. You need not require the EOF:
$given_array = array('column1'=>'value1',
'column2'=>'value2',
'column3'=>'value3');
$glue = '';
foreach($given_array as $column_name=>$value){
$where .= " $glue $column_name = $value"; //appending the glue
$glue = 'AND';
}
echo $where;
o/p:
column1 = value1 AND column2 = value2 AND column3 = value3
How about using "end"?
http://php.net/manual/en/function.end.php
It sounds like you want something like this:
$array = array(
'First',
'Second',
'Third',
'Last'
);
foreach($array as $key => $value)
{
if(end($array) === $value)
{
echo "last index!" . $value;
}
}
$array = array("dog", "rabbit", "horse", "rat", "cat");
foreach($array as $index => $animal) {
if ($index === array_key_first($array))
echo $animal; // output: dog
if ($index === array_key_last($array))
echo $animal; // output: cat
}
you can do a count().
for ($i=0;$i<count(arr);$i++){
$i == count(arr)-1 ? true : false;
}
or if you're looking for ONLY the last element, you can use end().
end(arr);
returns only the last element.
and, as it turns out, you CAN index php arrays by integers. It's perfectly happy with
arr[1];
You could also do something like this:
end( $elements );
$endKey = key($elements);
foreach ($elements as $key => $value)
{
if ($key == $endKey) // -- this is the last item
{
// do something
}
// more code
}
I kinda like the following as I feel it is fairly neat. Let's assume we're creating a string with separators between all the elements: e.g. a,b,c
$first = true;
foreach ( $items as $item ) {
$str = ($first)?$first=false:", ".$item;
}
Here's my solution:
Simply get the count of your array, minus 1 (since they start in 0).
$lastkey = count($array) - 1;
foreach($array as $k=>$a){
if($k==$lastkey){
/*do something*/
}
}
foreach ($array as $key => $value) {
$class = ( $key !== count( $array ) -1 ) ? " class='not-last'" : " class='last'";
echo "<div{$class}>";
echo "$value['the_title']";
echo "</div>";
}
Reference
If it is a single dimensional array you can do this to keep it short and sweet:
foreach($items as $idx => $item) {
if (!isset($items[$idx+1])) {
print "I am last";
}
}
Here's another way you could do it:
$arr = range(1, 10);
$end = end($arr);
reset($arr);
while( list($k, $v) = each($arr) )
{
if( $n == $end )
{
echo 'last!';
}
else
{
echo sprintf('%s ', $v);
}
}
If I understand you, then all you need is to reverse the array and get the last element by a pop command:
$rev_array = array_reverse($array);
echo array_pop($rev_array);
You could also try this to make your query... shown here with INSERT
<?php
$week=array('one'=>'monday','two'=>'tuesday','three'=>'wednesday','four'=>'thursday','five'=>'friday','six'=>'saturday','seven'=>'sunday');
$keys = array_keys($week);
$string = "INSERT INTO my_table ('";
$string .= implode("','", $keys);
$string .= "') VALUES ('";
$string .= implode("','", $week);
$string .= "');";
echo $string;
?>
For SQL query generating scripts, or anything that does a different action for the first or last elements, it is much faster (almost twice as fast) to avoid using unneccessary variable checks.
The current accepted solution uses a loop and a check within the loop that will be made every_single_iteration, the correct (fast) way to do this is the following :
$numItems = count($arr);
$i=0;
$firstitem=$arr[0];
$i++;
while($i<$numItems-1){
$some_item=$arr[$i];
$i++;
}
$last_item=$arr[$i];
$i++;
A little homemade benchmark showed the following:
test1: 100000 runs of model morg
time: 1869.3430423737 milliseconds
test2: 100000 runs of model if last
time: 3235.6359958649 milliseconds
Another way to go is to remember the previous loop cycle result and use that as the end result:
$result = $where = "";
foreach ($conditions as $col => $val) {
$result = $where .= $this->getAdapter()->quoteInto($col.' = ?', $val);
$where .= " AND ";
}
return $this->delete($result);

Categories