Hello to everyone,
I am trying to get a some values from the database.
My issue is that I want some results stored into a variable to be exactly 25 caracteres long.
When the result($title) is > 25 caracters long there is no problem with this substr($title, 0, 24),
but when the result($title) is less than 25 caracters long I want that difference to be filled with spaces.

Also another issue is that I echo this result($title) so the spaces I think that should be  

Hello,
You can try this:

$initialtitle = 'ABCDEFGHI';
$title = str_pad($initialtitle, 25," ");

str_pad is a good solution for this, however the code provided by catalinetu won't work because HTML truncates multiple spaces to one space unless you use non-breaking spaces with " "

Now the problem with using   with str_pad is, as per PHP Manual:

"Note: The pad_string may be truncated if the required number of padding characters can't be evenly divided by the pad_string's length."

Which basically means this:

<?php
    $someString = "Hello";
    $someString = str_pad($someString, 25, "&nbsp;");

    echo $someString;

    // This will output:
    // Hello   &n
    // Because depending on your string's length, it's trying to truncate &nbsp;
?>

You'll have to play with it a little to get exactly what you want. This should do the trick:

<?php
    $someString = "Hello";
    $someString = str_pad($someString, 25, "*");
    $someString = str_replace("*", "&nbsp;", $someString);

    echo $someString;

    // This pads the string on the right side by default
    // To pad the left:
    // $someString = str_pad($someString, 25, "*", STR_PAD_LEFT);
?>
Member Avatar
diafol

Heh, that's fine as long as the otiginal string doesn't contain your original pad text. This can also be an issue if you need to save the data to a db of length 25 characters.

In addition, if the input text contains multibyte characters, we're in trouble. For a truly robust function, we need to use mb_* functions and I would imagine the conversion of html entities to their decoded characters.

As mentioned &nbsp; (or &#160;) is not a 'space', so if you need to urlencode it, then you end up with... "%A0" as opposed to "+". Again this may be an issue if storing in a length-critical field or if the affected url part is important for the correct functioning of a site.

//EDIT

BTW even if you decode &nbsp; you'll find its string length (ascii and mb) to be 2, no the expected 1.

https://bugs.php.net/bug.php?id=65072&edit=3

So if you try to force &nbsp; to a single character length, by various means, you'll probably end up with those delightful little black diamonds with the question marks. :(

Member Avatar
diafol

Here's some code I put together which seems to work. Even though we can pass   as a single character, html will output it as   in source view.

<?php
header('Content-Type: text/html; charset=utf-8');

$type='right';
$input = 'hello';
$len = 10;
$str = '&amp;nbsp;';
$enc = 'UTF-8';

if($_GET)
{
    function mb_str_pad( $input, $pad_length, $pad_string = ' ', $pad_type = STR_PAD_RIGHT, $encoding="UTF-8" )
    {
        //Decode input string
        $decoded_input = html_entity_decode($input,NULL,$encoding);
        //Get new decoded input string length
        $decoded_input_length = mb_strlen($decoded_input,$encoding);
        //How many characters to add?
        $pad_places = $pad_length - $decoded_input_length;
        //Decode pad string
        $decoded_pad_string = html_entity_decode($pad_string,NULL,$encoding);
        //Get new decoded pad string length
        $decoded_pad_length = mb_strlen($decoded_pad_string, $encoding);
        //Complete repeats
        $repeat = floor($pad_places / $decoded_pad_length);
        //Remainder -how many extra characters to add
        $remainder = $pad_places % $decoded_pad_length;
        $additional = ($remainder) ? mb_substr($decoded_pad_string,0,$remainder,$encoding) : '';
        //Get tag-on 'pad' text
        $pad = str_repeat($decoded_pad_string, $repeat) . $additional;
        //Place 'pad' in the correct position
        if($pad_type === STR_PAD_RIGHT)
        {
            $output = $decoded_input . $pad;
        }elseif($pad_type === STR_PAD_LEFT){
            $output = $pad . $decoded_input;
        }elseif($pad_type === STR_PAD_BOTH){
            $l =  mb_substr($pad,0,floor($pad_places/2),$encoding);
            $r =  mb_substr($pad,0,ceil($pad_places/2),$encoding);
            $output = $l . $decoded_input . $r;
        }
        return $output;
    }

    $input = $_GET['input'];
    $len = $_GET['len'];
    $str = $_GET['str'];
    $type = $_GET['type'];
    $enc = $_GET['enc'];
    if($type == 'left') $constant = STR_PAD_LEFT;
    if($type == 'right') $constant = STR_PAD_RIGHT;
    if($type == 'both') $constant = STR_PAD_BOTH;

    $getOut = mb_str_pad($input, $len, $str, $constant, $enc);
    $str = htmlentities($str); //can be optioonal
}
?>

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
    div{
        font-family:"Courier New", Courier, monospace;  
        border: 1px solid black;
        padding: 20px;
    }
    span.end{
        color: red;
        font-weight: bold;
    }
    span.subject{
        background-color: yellow;
    }
</style>
<title>Multibyte str_pad tester</title>
</head>
<body>
<?php if($_GET){?>
<div>

    <span>123456789012345678901234567890123456789012345678901234567890</span><br>
    <span class="subject"><?php echo $getOut;?></span><span class="end">|END HERE</span>
</div><br><br><br>
<?php }?>
<form method="get">
    <label for="input">Input:</label>
    <input value="<?php echo $input;?>" name="input" /><br>
    <label for="len">String Length:</label>
    <input value="<?php echo $len;?>" name="len" /><br>
    <label for="str">Pad String:</label>
    <input value="<?php echo $str;?>" name="str" /><br>
    <label for="type">Pad Type:</label>
    <select name="type">
        <option value="right"<?php if($type=='right')echo ' selected';?>>STR_PAD_RIGHT</option>
        <option value="left"<?php if($type=='left')echo ' selected';?>>STR_PAD_LEFT</option>
        <option value="both"<?php if($type=='both')echo ' selected';?>>STR_PAD_BOTH</option>
    </select><br>
    <label for="enc">Encoding:</label>
    <input value="<?php echo $enc;?>" name="enc" /><br>
    <input type="submit" value="Test" name="submit" />
</form>
</body>
</html>

There are other ways I would imagine of doing this, e.g. repeating the whole endoded string and then decoding afterwards.

Thank you to everyone for the help, especially for #diafol :)