Omdat (o.a.) Marktplaats de onhebbelijkheid heeft om URL's standaard naar lower case ("kleine letters") te drukken kun je daar niet met 
base-64 encoding werken (die gebruikt zowel hoofd- als kleine letters - wat daardoor dus onbruikbaar wordt). Maar om nou meteen terug te schakelen naar 
hexadecimaal is ook zo wat. PHP biedt zelf geen ondersteuning voor andere encodings, dus dan moet je het zelf maar doen (online is van alles te vinden, maar niet zo geheugen/processor-efficiƫnt als deze!):
<?php
  /**
   * Base encode parameters.
   * @param string $base  Base characters.
   * @param int $length  Number of characters in base.
   * @param int $bits  Number of bits possible in character range (rounded up).
   * @param int $max  Maximum value in base without data loss.
   * @param bool $oversize  True when the bit size is too large for the base.
   */
  protected static function baseParams(&$base,&$length,&$bits,&$max,&$oversize){
    if(($length = strlen($base)) < 2) throw new \ValueError('Not enough characters in base');
    if(count(array_unique($base = str_split($base))) < $length) throw new \ValueError('Duplicate characters in base');
    $bits = 0;
    while(($max = (1 << ++$bits)) < $length);
    if($oversize = $max > $length) $max >>= 1;
  }
  /**
   * Encode a string with a base set of characters.
   * @param string $base  Base characters.
   * @param string $str  String to encode.
   * @return string  String encoded with characters from base.
   */
  public static function baseEncode($base,$str){
    $result = null;
    if($count = strlen($str)){
      self::baseParams($base,$length,$bits,$max,$oversize);
      $buffer = $size = $fill = $position = 0; //bit buffer, buffer size, fillers in buffer, position in string
      while(($position < $count) || ($size > $fill)){ //still bytes or bits to process
        if($size < $bits){ //add next byte (or filler) to buffer
          $buffer <<= 8;
          $size += 8;
          if($position < $count) $buffer += ord($str[$position++]);
          else $fill += 8;
        }
        $index = $buffer >> ($size - ($gone = $bits)); //get bits from buffer
        if($oversize && (($index < $max) || ($index >= $length))){ //not in extra chars - take 1 bit less.
          $index >>= 1;
          $gone--;
        }
        $result .= $base[$index];
        $buffer &= (1 << ($size -= $gone)) - 1;
      }
    }
    return $result;
  }
  /**
   * Decode a string encoded with a base set of characters.
   * @param string $base  Base characters.
   * @param string $str  String to decode.
   * @return string  Decoded (original) string.
   */
  public static function baseDecode($base,$str){
    $result = null;
    if($count = strlen($str)){
      self::baseParams($base,$length,$bits,$max,$oversize);
      $map = array_flip($base);
      $buffer = $size = 0; //bit buffer, buffer size
      for($position = 0; $position < $count; $position++){
        if (!array_key_exists($char = $str[$position],$map)) throw new \ValueError("Char '$char' is not in base");
        $index = $map[$char];
        $add = $bits;
        if($oversize){ //bit size larger then char range
          if($index < $max) $add--; //lower range = 1 bit less
          elseif($index >= $length){ //out of range = 1 bit less
            $index >>= 1;
            $add--;
          } //else: in extra range = maximum bits used
        }
        $buffer = ($buffer << $add) | $index;
        $size += $add;
        while($size >= 8){ //write bytes from buffer
          $result .= chr($buffer >> ($size -= 8));
          $buffer &= (1 << $size) - 1;
        }
      }
    }
    return $result;
  }
De "base" kan dus van alles zijn. Als het maar meer dan 2 (en minder dan 256) unieke karakters zijn - het precieze aantal maakt niet uit (hoeft geen macht van 2 te zijn).
Rob, zaterdag 30 september 2023, 13:22