Frage

Edited question. Validated after 18.Dec.2013.

after more search on SO and google, I decided that probably I need to utilize collator_create and collator_sort functions since my site's language is Turkish and I use UTF-8 encoding.

new position where I am is:

/* fetch values */
$etiket_bulutu = '';
while ($beyan->fetch()) 
{
    $etiket_bulutu .=  $tags.', ';
}

$etiket_bulutu = substr_replace($etiket_bulutu ,'',-2); //omit last {, } chars

$etiketler = explode(", ", $etiket_bulutu); //get each tag as arr

$etiketler = array_unique($etiketler);
$etiketler = array_values($etiketler); //only unique tags without NULLs

$etadet = count($etiketler);

$coll = collator_create('tr_TR'); //from http://www.php.net/manual/en/collator.sort.php
collator_sort($coll, $etiketler);

for($x=0;$x<$etadet;$x++)
 {
  echo $etiketler[$x];
  echo "<br />";
 }

Now, I have no html output and in my error.log file I got this warning "... PHP Warning: sort() expects parameter 2 to be long, string given in ..." and this fatal error "PHP Fatal error: Class 'Collator' not found"

I also googled for these issues but couldn't solve my issue. My PHP version is 5.3.24 waiting for your valuable help. BR

question until 18.Dec.2013 is below. this is old ver. of my Q.

my input

in my related MySql table, my each article (each table row) has its tags in row's related cell. my tagging format has 2 rules:

  1. seperate tags using comma and 1 space character (example: tag1, tag2)
  2. if tag has more than 1 word then seperate the words with dash symbol (-).(example: smart-phone, tag2)

as last input, different articles can have same tags of course

my aim

having a page titled "tags", I try to achieve alphabetical sort of all tags and print them with links back to the list of related articles.

I thought the procedure below:

  1. get all tags from table and cretae an array which consists of unique tags.
  2. execute alphabetical sort
  3. visit each element of last form of array to print the tag with the related link

what I tried

note: convert_one_row is a string validation function.



if ($beyan = $db_baglanti->prepare($sorgum)) { /* bind parameters */ $beyan -> bind_param("s", $bindparametre1);

/* execute statement */
$beyan->execute();

/* bind result variables */
$beyan->bind_result($etiketler);

echo "\t".''."\r\n"; echo "\t\t".'

'.'Etiketler'.'

'."\r\n";

/* fetch values */
$etiket_bulutu = '';
while ($beyan->fetch()) 
{
    $etiket_bulutu .=  $etiketler.', ';
}

$etiket_bulutu = substr_replace($etiket_bulutu ,'',-2); //en son 2karakteri yani {, } attık $etiket_bulutu = explode(", ", $etiket_bulutu); //her bir etiketten array yarattık sort($etiket_bulutu, SORT_NATURAL | SORT_FLAG_CASE); $etiket_bulutu = array_unique($etiket_bulutu, SORT_STRING); //sadece tekil etiketler kaldı $bulut = ''; foreach($etiket_bulutu as $etiket) {$bulut .= ''.convert_one_row($etiket).', ';} $bulut = substr_replace($bulut ,'',-2); //en son 2karakteri yani {, } attık echo "\r\n\r\n".'

'.$bulut.'

'."\r\n\r\n";

echo "\t".''."\r\n";
/* close statement */ $beyan->close(); } ?>

my current result

I achieved to print tags with related links however alphabetical sort issue has failed. Currently, 1st article's tags are written then 2nd article's tags, 3rd and so on... But there is no alphabetical sorting.

current situation example:

article 1 tags: table, apple, smart-phone

article 2 tags: smart-phone, world, soccer

current situation: table, apple, smart-phone, world, soccer

what I require: apple, smart-phone, soccer, table

Can you please correct me thank you in advance

War es hilfreich?

Lösung

After asking this question and learning the answer of it, I needed to find a way to sort UTF-8 (Turkish input) string array from MySql db alphabetically.

then I used Fy-'s answer in this link and it worked.

Now, my solution is:

setlocale(LC_COLLATE, 'tr_TR.utf8'); //utf-8 sorting için gerekli
$sorgum = "...";
$bindparametre1 = '...';

if ($beyan = $db_baglanti->prepare($sorgum)) 
{
    /* bind parameters */
    $beyan -> bind_param("s", $bindparametre1);

    /* execute statement */
    $beyan->execute();

    /* bind result variables */
    $beyan->bind_result($etiketler);

echo "\t".'<div class="sol-icerik-kapsar">'."\r\n";
echo "\t\t".'<h1>'.'Etiketler'.'</h1>'."\r\n";

    /* fetch values */
    $etiket_bulutu = '';
    while ($beyan->fetch()) 
    {
        $etiket_bulutu .=  $etiketler.', ';
    }
$etiket_bulutu = substr_replace($etiket_bulutu ,'',-2); //en son 2karakteri yani {, } attık
$etiketler = explode(", ", $etiket_bulutu); //her bir etiketten array yarattık
$etiketler = array_unique($etiketler);
$etiketler = array_values($etiketler); //sadece tekil etiketler kaldı
$etadet = count($etiketler);

usort($etiketler, 'strcoll');

echo "\n\t\t".'<p>'."\n";
for($x=0;$x<$etadet;$x++)
  {
  echo "\t\t\t".'<a href="'.url_validate(sitenin_koku.'etiketler/'.$etiketler[$x]).'">'.convert_one_row($etiketler[$x]).'</a>, '."\n";
  }
echo "\t\t".'</p>'."\n";

key codes for my solution here are : setlocale(LC_COLLATE, 'tr_TR.utf8'); and usort($etiketler, 'strcoll');

regards

Andere Tipps

I did a quick local check of your code and it works for me. This is what I do:

$etiket_bulutu = 'table, apple, smart-phone, smart-phone, world, soccer, ';

$etiket_bulutu = substr_replace($etiket_bulutu ,'',-2);
$etiket_bulutu = explode(", ", $etiket_bulutu); 
sort($etiket_bulutu, SORT_NATURAL | SORT_FLAG_CASE);
$etiket_bulutu = array_unique($etiket_bulutu, SORT_STRING); $bulut = '';
foreach($etiket_bulutu as $etiket){
    $bulut .= $etiket.', ';
}

$bulut = substr_replace($bulut ,'',-2);

echo "\r\n\r\n".'  
'.$bulut.''."\r\n\r\n";

The given output is: apple, smart-phone, soccer, table, world

So your code is basically correct but seems a little complicated to me. Why it is not working I do not really now. Do you have any not visible signs in the database-data? How does $etiket_bulut look like, after putting all data from the database in it? Is it the same as in my code? Try to do a array_unique before the sort. Maybe this helps.

And I would advice you to use different variables for different things. Your $etiket_bulut is first a string and then it gets an array. That is (in my opinion) bad coding style. If someone looks at the code and misses the explode(), the person is going to wonder why you are using array-functions on a string.

And you could simplify this:

foreach($etiket_bulutu as $etiket){
    $bulut .= $etiket.', ';
}
$bulut = substr_replace($bulut ,'',-2);

into

$bulut = implode(', ', $etiket_bulutu);

You are missing a parameter in your Collator::sort() The sort flag. As the documentation explains it:

sort_flag

Optional sorting type, one of the following:

    Collator::SORT_REGULAR - compare items normally (don't change types)

    Collator::SORT_NUMERIC - compare items numerically

    Collator::SORT_STRING - compare items as strings

Default sorting type is Collator::SORT_REGULAR. It is also used if an invalid sort_flag value has been specified.

https://www.php.net/manual/en/collator.sort.php

So, in most situations you should specify Collator::SORT_REGULAR as that parameter, and you will be alright.

In your case you need to write this:

//example of an array with words in turkish
$etiketler = ['İyiyim', 'sabah', 'şemsiye', 'Ağaç', 'çay', 'çanta', 'üzüm', 'şeftali', 'çilek', 'maltaeriği'];
//Make a Collator object with the turkish locale
$collator = new Collator('tr_TR');
//Notice the parameter: Collator::SORT_REGULAR It is the sort flag, it instructs the function as to how the sorting could be done, as there are other sorting possibilities.
$collator->sort($etiketler, Collator::SORT_REGULAR);

var_dump($etiketler);
//ordered array:
/*
array(10) {
  [0]=>
  string(6) "Ağaç"
  [1]=>
  string(6) "çanta"
  [2]=>
  string(4) "çay"
  [3]=>
  string(6) "çilek"
  [4]=>
  string(7) "İyiyim"
  [5]=>
  string(11) "maltaeriği"
  [6]=>
  string(5) "sabah"
  [7]=>
  string(8) "şeftali"
  [8]=>
  string(8) "şemsiye"
  [9]=>
  string(6) "üzüm"
}
*/

ALSO, if PHP says that the class was not found, probably you have the Internationalization Functions disabled. To activate them use the instructions here: https://www.php.net/manual/en/intl.installation.php Look at the user comments, it might be as easy as deleting 1 character from the php.ini in windows: https://www.php.net/manual/en/intl.installation.php#114933 Or running 1 command in linux.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top