compare if with hebrew letter - php

I write code that work only with english letters. when I ctry to do it with hebrew letter I get error.
the code:
<?php
$idan="emr";
$firstletter = mb_substr($idan, 0, 1, 'UTF-8');
if ($firstletter=='e')
echo "tov";
else echo "lo tove";
?>
work good.
but the code:
<?php
$idan="אבהבה";
$firstletter = mb_substr($idan, 0, 1, 'UTF-8');
if ($firstletter=='א')
echo "tov";
else echo "lo tove";
?>
not work, How I can to fix it?

You do realize that mb_substr works from left to right? (is Hebrew written from right to left?) You are therefore reading the first character which is ה not א. To get the first letter from the right (the last one), use -1 as a starting index:
$firstletter = mb_substr($idan, -1, 1, 'UTF-8');
You can also use mb_internal_encoding("UTF-8"); to set the encoding for every call, instead of propagating it (if you're making many calls to mb_ functions)
Edit: Following your comments, here's a quick example of a script that handles letters depending on the language:
$desiredLetter = 'e';
$startIndex = 0;
// some condition to figure out the language
if(mb_detect_encoding($idan, 'ASCII', true) == FALSE)
{
$desiredLetter = 'א';
$startIndex = -1;
}
$firstletter = mb_substr($idan, $startIndex, 1, 'UTF-8');
if ($firstletter == $desiredLetter)
echo "tov";
else
echo "lo tove";

Your code worked correctly (e.g. printed tov) when I saved it to a PHP file and ran it. If you are seeing different results, you may want to check your text editor settings and ensure that you're saving the file as UTF-8.

Related

How to print Hexadecimal UTF-8 characters in PHP

How to print UFT-8 Characters from their Hexadecimal UTF-8 values? I read this post, but it did not solve my problem...
I work with many strings that are sanskrit words stored in a database. I have their HTML values, 16 bit binary code points, hex codes, and decimal codes, but I want to be able to work with their Hexadecimal UTF-8 values and output their symbolic form.
For example, here is a word आम that has a Binary UTF-8 value of 111000001010010010111000111000001010010010101110. I want to see/store/print its Hexadecimal UTF-8 value and print its symbolic form.
For example, here's a snippet of my code:
$BinaryUTF8 = "111000001010010010000110111000001010010010101110";
$Temporary = dechex(bindec($BinaryUTF8));
$HexadecimalUTF8 = NULL;
for($i = 0; $i < strlen($Temporary); $i+=2)
{
$HexadecimalUTF8 .= "\x".$Temporary[$i].$Temporary[$i+1];
}
$Test = "\xe0\xa4\x86\xe0\xa4\xae";
echo "\$Test = ".$Test;
echo "<br>";
echo "\$HexadecimalUTF8 = ".$HexadecimalUTF8;
The output is:
$Test = आम
$HexadecimalUTF8 = \xe0\xa4\x86\xe0\xa4\xae
$Test output the desired characters.
Why does $HexadecimalUTF8 not output the desired characters?
Your binary is wrong (I have fixed it below)
You are making a string containing the text "\xe0" instead of the character which represents that, The hex is just a number really.
This seems to work now
<?php
$BinaryUTF8 = "111000001010010010000110111000001010010010101110";
$Temporary = dechex(bindec($BinaryUTF8));
$HexadecimalUTF8 = NULL;
for($i = 0; $i < strlen($Temporary); $i+=2)
{
$HexadecimalUTF8 .= '\x' . $Temporary[$i].$Temporary[$i+1];
}
$Test = "\xe0\xa4\x86\xe0\xa4\xae";
echo "\$Test = ".$Test;
echo "<br>";
echo "\$HexadecimalUTF8 = " . makeCharFromHex($HexadecimalUTF8);
function makeCharFromHex($hex) {
return preg_replace_callback(
'#(\\\x[0-9A-F]{2})#i',
function ($matches) {
return chr(hexdec($matches[1]));
},
$hex
);
}
This question reminds me how poor PHP is for multi byte support
To print UTF-8 characters from their decimal value you can use this function
<?php
function chr_utf8($n,$f='C*'){
return $n<(1<<7)?chr($n):($n<1<<11?pack($f,192|$n>>6,1<<7|191&$n):
($n<(1<<16)?pack($f,224|$n>>12,1<<7|63&$n>>6,1<<7|63&$n):
($n<(1<<20|1<<16)?pack($f,240|$n>>18,1<<7|63&$n>>12,1<<7|63&$n>>6,1<<7|63&$n):'')));
}
echo chr_utf8(9405).chr_utf8(9402).chr_utf8(9409).chr_utf8(hexdec('24C1')).chr_utf8(9412);
// Output ⒽⒺⓁⓁⓄ
// Note : Use hexdec to print UTF-8 encoded characters from hexadecimal number.
For your snippet you can try this… and check it in https://eval.in/748161
<?php
// function chr_utf8 shown above is required…
$BinaryUTF8 = "111000001010010010000110111000001010010010101110";
if (preg_match_all('#(0[01]{7})|(?:110([01]{5})10([01]{6}))|(?:1110([01]{4})10([01]{6})10([01]{6}))|(?:11110([01]{3})10([01]{6}),10([01]{6})10([01]{6}))#',$BinaryUTF8,$a,PREG_SET_ORDER))
$result=implode('',array_map(function($n){return chr_utf8(bindec(implode('',array_slice($n,1))));},$a));
echo $result;
// Output आम
// Note : If you work with "binary" the length of input must be multiple of 8.
// You can't remove leading zeros because this regex will not detect the character…
One other nice inline solution is the following… (php v5.6+ required) Check it in https://eval.in/748162
<?php
$BinaryUTF8 = "111000001010010010000110111000001010010010101110";
echo pack('C*',...array_map('bindec',str_split($BinaryUTF8,8)));
// Output आम
// Note : Length or $BinaryUTF8 of input must be multiple of 8.

How does python converts mysql binary(16)

I have two apps one written in php and one in python and both of them use the same mysql database.
For the public id of the entries in some of the tables I use binary(16) fields(I can't change this, it must remain this way).
The question is how does python does the conversion of this binary field?
Let's take one of the entries as an example.
When I get it in php(from the db) the value of the public id is °•WiCÄ‘õ0Iò|–g, the same value is shown in SequelPro. But php myAdmin does a hex function over binary fields and shows 0bb09557691443c491f53049f27c9667. Now I managed in php to convert the binary to the value showed in php myAdmin and it works for all the entries but I've just noticed that python does another conversion. When I get the entry used in this example via python the public id is owwweye1rjnvt3i1d0ib18x3.
What I need to achieve is to convert in php what I get from MySql: °•WiCÄ‘õ0Iò|–g to what python sees: owwweye1rjnvt3i1d0ib18x3. The php app makes calls on the python one(not developed by me) and thus the id needs to be in the same format for a successfull call.
Any suggestions are welcomed. Thanks.
EDIT: If i send °•WiCÄ‘õ0Iò|–g from php to python and print it rigth away I get: °•WiCÄ‘õ0Iò|–g
Finally I've sorted this out.
Seems that python converts to base36 not hex as I've wrongly supposed.
I've tried to simply base_convert 0bb09557691443c491f53049f27c9667 from 16 to 36 but I've got owwweye1rk04k4cskkw4s08s. Not really what I needed but still a great step further as it started to look like owwweye1rjnvt3i1d0ib18x3.
This difference I supposed to appear because of the large values to be converted(loss of precision), so I've further researched and found the bellow function, written by Clifford dot ct at gmail dot com on the php.net website:
<?php
function str_baseconvert($str, $frombase=10, $tobase=36) {
$str = trim($str);
if (intval($frombase) != 10) {
$len = strlen($str);
$q = 0;
for ($i=0; $i<$len; $i++) {
$r = base_convert($str[$i], $frombase, 10);
$q = bcadd(bcmul($q, $frombase), $r);
}
}
else $q = $str;
if (intval($tobase) != 10) {
$s = '';
while (bccomp($q, '0', 0) > 0) {
$r = intval(bcmod($q, $tobase));
$s = base_convert($r, 10, $tobase) . $s;
$q = bcdiv($q, $tobase, 0);
}
}
else $s = $q;
return $s;
}
?>
I don't think others will come across this issue very often, but still if it happens hope they'll find this instead of burning their brains out like I did :))))

Parse UTF-8 string char-by-char in PHP

I'm sorry if I'm asking the obvious, but I can't seem to find a working solution for a simple task. On the input I have a string, provided by a user, encoded with UTF-8 encoding. I need to sanitize it by removing all characters less than 0x20 (or space), except 0x7 (or tab.)
The following works for ANSI strings, but not for UTF-8:
$newName = "";
$ln = strlen($name);
for($i = 0; $i < $ln; $i++)
{
$ch = substr($name, $i, 1);
$och = ord($ch);
if($och >= 0x20 ||
$och == 0x9)
{
$newName .= $ch;
}
}
It totally missed UTF-8 encoded characters and treats them as bytes. I keep finding posts where people suggest using mb_ functions, but that still doesn't help me. (For instance, I tried calling mb_strlen($name, "utf-8"); instead of strlen, but it still returns the length of string in BYTEs instead of characters.)
Any idea how to do this in PHP?
PS. Sorry, my PHP is somewhat rusty.
If you use multibyte functions (mb_) then you have to use them for everything. In this example you should use mb_strlen() and mb_substr().
The reason it is not working is probably because you are using ord(). It only works with ASCII values:
ord
(PHP 4, PHP 5)
ord — Return ASCII value of character
...
Returns the ASCII value of the first character of string.
In other words, if you throw a multibyte character into ord() it will only use the first byte, and throw away the rest.
Wow, PHP is one messed up language. Here's what worked for me (but how much slower will this run for a longer chunk of text...):
function normalizeName($name, $encoding_2_use, $encoding_used)
{
//'$name' = string to normalize
// INFO: Must be encoded with '$encoding_used' encoding
//'$encoding_2_use' = encoding to use for return string (example: "utf-8")
//'$encoding_used' = encoding used to encode '$name' (can be also "utf-8")
//RETURN:
// = Name normalized, or
// = "" if error
$resName = "";
$ln = mb_strlen($name, $encoding_used);
if($ln !== false)
{
for($i = 0; $i < $ln; $i++)
{
$ch = mb_substr($name, $i, 1, $encoding_used);
$arp = unpack('N', mb_convert_encoding($ch, 'UCS-4BE', $encoding_used));
if(count($arp) >= 1)
{
$och = intval($arp[1]); //Index 1?! I don't understand why, but it works...
if($och >= 0x20 || $och == 0x9)
{
$ch2 = mb_convert_encoding('&#'.$och.';', $encoding_2_use, 'HTML-ENTITIES');
$resName .= $ch2;
}
}
}
}
return $resName;
}

How can i change the encoding of imagefttext() result in php gd library?

I'm trying to change the encoding of my imagefttext() result.
My idea is to print some text in "Arabic" language onto a specified image , but the result appear in strange
form.
I used this code, but it is work correctly just with English string :
mb_internal_encoding('UTF-8');
$im =imagecreatefromjpeg('x.jpg');
$textcolor=imagecolorallocate($im, 0, 0, 255);
imagefttext($im, 18, 0, 10, 20,$textcolor,"Fonts/tahoma.ttf","مسعود أوزبل");
imagejpeg($im,"mozil.jpg",100);
imagedestroy($im);
Can i have any solution for this problem ?
Thanks
Arabic characters can not be treated as an array. Also imagefttext() does not support RTL languages like Arabic out of the box. What you need to do is to reverse every character without changing its shape (glyph/symbol). #Lars answer won't work because a char in Arabic might change based on its position in the word. See here for a similar answer and a solution: Error while writting Arabic to image
in the comments of the manual for imagettftext, there's an example for RTL languages. Try this
$wordsArray = explode(" ", $text);
$rtlCompleteText='';
for ($i = sizeOf($wordsArray); $i > -1; $i = $i-1) {
//$lettersArray = explode("|", str_replace(";|", ";", $wordsArray[$i]));
$lettersArray = explode(";", $wordsArray[$i]);
$rtlWord='';
for ($k = sizeOf($lettersArray); $k > -1; $k = $k-1) {
if (strlen($lettersArray[$k]) > 1) { // make sure its full unicode letter
$rtlWord = $rtlWord."".$lettersArray[$k].";";
}
}
$rtlCompleteText = $rtlCompleteText." ".$rtlWord;
}
return $rtlCompleteText;
}

Clear PHP CLI output

I'm trying to get a "live" progress indicator working on my php CLI app. Rather than outputting as
1Done
2Done
3Done
I would rather it cleared and just showed the latest result. system("command \C CLS") doesnt work. Nor does ob_flush(), flush() or anything else that I've found.
I'm running windows 7 64 bit ultimate, I noticed the command line outputs in real time, which was unexpected. Everyone warned me that out wouldn't... but it does... a 64 bit perk?
Cheers for the help!
I want to avoid echoing 24 new lines if I can.
Try outputting a line of text and terminating it with "\r" instead of "\n".
The "\n" character is a line-feed which goes to the next line, but "\r" is just a return that sends the cursor back to position 0 on the same line.
So you can:
echo "1Done\r";
echo "2Done\r";
echo "3Done\r";
etc.
Make sure to output some spaces before the "\r" to clear the previous contents of the line.
[Edit] Optional: Interested in some history & background? Wikipedia has good articles on "\n" (line feed) and "\r" (carriage return)
I came across this while searching for a multi line solution to this problem. This is what I eventually came up with. You can use Ansi Escape commands. http://www.inwap.com/pdp10/ansicode.txt
<?php
function replaceOut($str)
{
$numNewLines = substr_count($str, "\n");
echo chr(27) . "[0G"; // Set cursor to first column
echo $str;
echo chr(27) . "[" . $numNewLines ."A"; // Set cursor up x lines
}
while (true) {
replaceOut("First Ln\nTime: " . time() . "\nThird Ln");
sleep(1);
}
?>
I recently wrote a function that will also keep track of the number of lines it last output, so you can feed it arbitrary string lengths, with newlines, and it will replace the last output with the current one.
With an array of strings:
$lines = array(
'This is a pretty short line',
'This line is slightly longer because it has more characters (i suck at lorem)',
'This line is really long, but I an not going to type, I am just going to hit the keyboard... LJK gkjg gyu g uyguyg G jk GJHG jh gljg ljgLJg lgJLG ljgjlgLK Gljgljgljg lgLKJgkglkg lHGL KgglhG jh',
"This line has newline characters\nAnd because of that\nWill span multiple lines without being too long",
"one\nmore\nwith\nnewlines",
'This line is really long, but I an not going to type, I am just going to hit the keyboard... LJK gkjg gyu g uyguyg G jk GJHG jh gljg ljgLJg lgJLG ljgjlgLK Gljgljgljg lgLKJgkglkg lHGL KgglhG jh',
"This line has newline characters\nAnd because of that\nWill span multiple lines without being too long",
'This is a pretty short line',
);
One can use the following function:
function replaceable_echo($message, $force_clear_lines = NULL) {
static $last_lines = 0;
if(!is_null($force_clear_lines)) {
$last_lines = $force_clear_lines;
}
$term_width = exec('tput cols', $toss, $status);
if($status) {
$term_width = 64; // Arbitrary fall-back term width.
}
$line_count = 0;
foreach(explode("\n", $message) as $line) {
$line_count += count(str_split($line, $term_width));
}
// Erasure MAGIC: Clear as many lines as the last output had.
for($i = 0; $i < $last_lines; $i++) {
// Return to the beginning of the line
echo "\r";
// Erase to the end of the line
echo "\033[K";
// Move cursor Up a line
echo "\033[1A";
// Return to the beginning of the line
echo "\r";
// Erase to the end of the line
echo "\033[K";
// Return to the beginning of the line
echo "\r";
// Can be consolodated into
// echo "\r\033[K\033[1A\r\033[K\r";
}
$last_lines = $line_count;
echo $message."\n";
}
In a loop:
foreach($lines as $line) {
replaceable_echo($line);
sleep(1);
}
And all lines replace each other.
The name of the function could use some work, just whipped it up, but the idea is sound. Feed it an (int) as the second param and it will replace that many lines above instead. This would be useful if you were printing after other output, and you didn't want to replace the wrong number of lines (or any, give it 0).
Dunno, seemed like a good solution to me.
I make sure to echo the ending newline so that it allows the user to still use echo/print_r without killing the line (use the override to not delete such outputs), and the command prompt will come back in the correct place.
i know the question isn't strictly about how to clear a SINGLE LINE in PHP, but this is the top google result for "clear line cli php", so here is how to clear a single line:
function clearLine()
{
echo "\033[2K\r";
}
function clearTerminal () {
DIRECTORY_SEPARATOR === '\\' ? popen('cls', 'w') : exec('clear');
}
Tested on Win 7 PHP 7. Solution for Linux should work, according to other users reports.
something like this :
for ($i = 0; $i <= 100; $i++) {
echo "Loading... {$i}%\r";
usleep(10000);
}
Use this command for clear cli:
echo chr(27).chr(91).'H'.chr(27).chr(91).'J'; //^[H^[J
Console functions are platform dependent and as such PHP has no built-in functions to deal with this. system and other similar functions won't work in this case because PHP captures the output of these programs and prints/returns them. What PHP prints goes to standard output and not directly to the console, so "printing" the output of cls won't work.
<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE);
function bufferout($newline, $buffer=null){
$count = strlen(rtrim($buffer));
$buffer = $newline;
if(($whilespace = $count-strlen($buffer))>=1){
$buffer .= str_repeat(" ", $whilespace);
}
return $buffer."\r";
};
$start = "abcdefghijklmnopqrstuvwxyz0123456789";
$i = strlen($start);
while ($i >= 0){
$new = substr($start, 0, $i);
if($old){
echo $old = bufferout($new, $old);
}else{
echo $old = bufferout($new);
}
sleep(1);
$i--;
}
?>
A simple implementation of #dkamins answer. It works well. It's a bit- hack-ish. But does the job. Wont work across multiple lines.
function (int $count = 1) {
foreach (range(1,$count) as $value){
echo "\r\x1b[K"; // remove this line
echo "\033[1A\033[K"; // cursor back
}
}
See the full example here
Unfortunately, PHP 8.0.2 does not has a function to do it. However, if you just want to clear console try this: print("\033[2J\033[;H"); or use : proc_open('cls', 'w');
It works in php 8.0.2 and windows 10. It is the same that system('cls') using c language programing.
Tried some of solutions from answers:
<?php
...
$messages = [
'11111',
'2222',
'333',
'44',
'5',
];
$endlines = [
"\r",
"\033[2K\r",
"\r\033[K\033[1A\r\033[K\r",
chr(27).chr(91).'H'.chr(27).chr(91).'J',
];
foreach ($endlines as $i=>$end) {
foreach ($messages as $msg) {
output()->write("$i. ");
output()->write($msg);
sleep(1);
output()->write($end);
}
}
And \033[2K\r seems like works correct.

Categories