4

I'm putting together a PHP website for a class project, and we are using a MS SQL Server 2008 database to populate fields on the site. However, one of the fields is outputting garbage onto the page instead of what is actually stored in the database.

The field in question, called description, is a varchar(MAX) field; a stored procedure queries the database for a tuple and dumps the values from its table into text boxes on the page; the description field is output to a textarea control.

Here is the PHP that handles pulling the information from the database:

$res = odbc_exec($dbhandle, "exec dbo.usp_ProgramGet " . $_GET["program"]);
$id = $_GET["program"];
$name = odbc_result($res, "title");
$desc = odbc_result($res, "description");

The $name variable works as expected (in the database, it is of type char(15)). However, if (for example) the description field contains "This is a test" then $desc will result in "�$ime�����", which is what gets dumped into the textarea control, instead of what's stored in the database.

I've searched all over and found no solutions to this problem yet, although it sounds like a bug in PHP itself although I'm not sure.


Update

I am using SQL Server queries to update the varchar values. I tried putting in a really long string and I got this:

�,ime�������stringDayToInt��É������à‰,���N={���������������������������������������������

"stringDayToInt" is the name of a PHP function I wrote that lives in a totally different file that got included into the page I'm trying out. Very bizarre.

Andrew
  • 4,953
  • 15
  • 40
  • 58
  • general comment - always best to filter / sanitize any input via $_GET / $_POST etc. Passing this directly to the DB engine might be unsafe, depending on your prog's use context. – trickwallett Feb 10 '11 at 16:49
  • @trickwallett - Yes, this is definitely good advice. Fortunately for this project we don't really need to worry about it due to the small scope and the general nature of the application. – Andrew Feb 10 '11 at 17:02

5 Answers5

4

I had the same Ugly problem on PHP 5.3...

The .php page displayed random characters where must be the column value.
Some times was ramdom characters and script sections of executed php page. This is not good.

SQL Server: MS SQL Server 2008 R2

My odbc connect driver: Driver={SQL Server Native Client 10.0}

My PHP version: PHP 5.3

I was looking around but I did not find the solution.
The workaround I tried and work for me is:

select cast(the_column_varcharmax as text) as column_name from table_name

Try it, I hope it works for you.

2

This bug is in MSSQL/ODBC/PHP for long time and I lost the hope it will be fixed in my life. The solution is converting it to text in the procedure:

select name, convert(text,description) as description. .....

I do it so for many years.

Hink
  • 1,054
  • 1
  • 15
  • 31
  • In my case, I used `CONVERT(VARCHAR(longervalue), column)` so thank you, this was driving me nuts! Couldn't understand why results were completely dropped. Explanation: the column stores strings with accented characters in `VARCHAR(30)`. For some reason, connecting via PDO ODBC, results were dropped if the length was exactly 30 and the data had special characters. Using `CONVERT(VARCHAR(40), column)` solved my issue. Now to figure out why PHP cli returns the accents and with apache strings need conversion... – katalin_2003 Nov 16 '16 at 10:12
1

This is a known bug in PHP.

Either compile your own patched version, or use the workaround above.

Rostyslav Dzinko
  • 39,424
  • 5
  • 49
  • 62
  • 1
    Tracked in the PHP bug database doesn't make it a PHP bug. It's a major change in behavior by *one* ODBC driver, which forces changes in client tools using that driver. Different ODBC drivers, like [the one from my employer](http://uda.openlinksw.com/odbc-sqlserver-st/), don't exhibit the same issue. – TallTed Jun 03 '15 at 19:39
0

I had the same problem with PHP 5.3 and MS SQL 2008 R2. Rather than workaround with a cast (which I did not find satisfactory), I switched drivers from ODBC to SQLSRV, which seems to work just fine.

  • Changing from ODBC to SQLSRV changes your PHP from DBMS-agnostic to DBMS-specific. Different ODBC drivers, like [the one from my employer](http://uda.openlinksw.com/odbc-sqlserver-st/), don't exhibit the same issue, so I'd suggest changing *ODBC Drivers* as a better options. – TallTed Jun 03 '15 at 19:40
0

Had a similar problem: php remove/identify this symbol �

Replacement Character

FFFD � REPLACEMENT CHARACTER

used to replace an incoming character whose value is unknown or unrepresentable in Unicode

UPDATE:

What does this output:

echo mb_detect_encoding($desc).' ';
var_dump($desc);

If mb_detect_encoding doesn't work

if(is_utf8($desc)) {
    echo "UTF-8 Encoded";
} else {
    echo "Oops, not UTF-8";
}

var_dump($desc);

function is_utf8($str) {
    $c=0; $b=0;
    $bits=0;
    $len=strlen($str);
    for($i=0; $i<$len; $i++){
        $c=ord($str[$i]);
        if($c > 128){
            if(($c >= 254)) return false;
            elseif($c >= 252) $bits=6;
            elseif($c >= 248) $bits=5;
            elseif($c >= 240) $bits=4;
            elseif($c >= 224) $bits=3;
            elseif($c >= 192) $bits=2;
            else return false;
            if(($i+$bits) > $len) return false;
            while($bits > 1){
                $i++;
                $b=ord($str[$i]);
                if($b < 128 || $b > 191) return false;
                $bits--;
            }
        }
    }
    return true;
}
Community
  • 1
  • 1
Phill Pafford
  • 83,471
  • 91
  • 263
  • 383
  • That's not the issue. The database fields have only basic ASCII characters in it. Something is getting corrupted on the way over. – Andrew Feb 10 '11 at 16:24
  • I suggest you do a var_dump on the return value as MS enters in weird or even hidden characters. echo "|".$desc."|"; look for spaces, that would indicate a carriage return or something. – Phill Pafford Feb 10 '11 at 16:51
  • Could you post the value from the database field description? – Phill Pafford Feb 10 '11 at 16:55
  • The value in the field is exactly "This is a test". `var_dump` gives `string(14) "ime"`. `echo` simply prints "ime". Good suggestions though. (this comment stripped out the junk box characters, but they're still there on my php page.) – Andrew Feb 10 '11 at 16:59
  • could you manually enter it a new test record through a GUI tool and run the PHP script? I still think that the data is not UNICODE. Try the example code I updated my answer with, what does it output? – Phill Pafford Feb 10 '11 at 18:05
  • @Phill - `mb_detect_encoding` threw an "undefined function" error; I'll install the necessary library and get back to you. But I entered this data manually in SQL Server, so there should be no extra characters floating around. – Andrew Feb 10 '11 at 18:14
  • okay so I got `mb_detect_encoding` to work; it says `UTF-8 string(14) "ime"`. – Andrew Feb 10 '11 at 18:26
  • hmm when I ran it gives me ASCII – Phill Pafford Feb 10 '11 at 18:46
  • 1
    hmm I found this thead interesting: http://bytes.com/topic/sql-server/answers/808461-cannot-read-varchar-max What ODBC are you using? might not yet support varchar(max). Any chance for testing you could change the data type and see if it works then? like to char – Phill Pafford Feb 10 '11 at 19:04
  • @phill - Actually I have no idea which ODBC I am using; however I took the suggestion of someone in that thread and simply casted to `varchar(5000)`; now it works perfectly. thanks so much for your help! – Andrew Feb 10 '11 at 19:08