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  

4 Years
Discussion Span
Last Post by developer707

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:

    $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:

    $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);

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.


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


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. :(

Edited by 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.

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

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

    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

<meta charset="utf-8">
        font-family:"Courier New", Courier, monospace;  
        border: 1px solid black;
        padding: 20px;
        color: red;
        font-weight: bold;
        background-color: yellow;
<title>Multibyte str_pad tester</title>
<?php if($_GET){?>

    <span class="subject"><?php echo $getOut;?></span><span class="end">|END HERE</span>
<?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>
    <label for="enc">Encoding:</label>
    <input value="<?php echo $enc;?>" name="enc" /><br>
    <input type="submit" value="Test" name="submit" />

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

Edited by diafol

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.