Problem with query from PHP script

We do sometimes manually create documents for configurations.

$couchBucket->setTranscoder(
  // encoder($value) -> array($bytes, $flags, $datatype)
  couchbase_default_encoder,

  // decoder($bytes, $flags, $datatype) -> $value
  function ($bytes, $flags, $datatype) {
    if ($flags == 0) {
       $flags = COUCHBASE_CFFMT_JSON;
    }
    return couchbase_default_decoder($bytes, $flags, $datatype);
  }

);

That code doesn’t seem to work for us as couchbase_default_encoder is not defined.

Web UI does not set flags (it uses zero AFAIK)

Yeah, that’s the issue.
(Thanks for formatting my code - how do you use the code blocks here??)

It is defined here:

https://github.com/couchbase/php-couchbase/blob/master/stub/default_transcoder.php#L198-L218

I verified that snippet

An exception occurred: Use of undefined constant couchbase_default_encoder - assumed ‘couchbase_default_encoder’ in /var/www/exfusion.net/html/protected/Exfusion.inc.php on line 36

Like on github

```php
```
1 Like

Does it work, if you wrap it into function?

function ($value) {
  return couchbase_default_encoder($value);
}

it also accepts string name "couchbase_default_encoder"

It was the spacing by the looks of it. What should $value be? (The argument for couchbase_default_encoder())

it is the thing you pass as the second argument to upsert() for example. In general array()

Would this be a plausible fix? We applied it as a botch but would it actually be acceptable?

            if(is_string($data)){
              $data = json_decode($data, true);
            }

in decoder? It would be always a string. In decoder you will receive bytes as a string

I would recommend to wrap decoder and fix the zero flags case. Because what if the $data is a string, but cannot be parsed? You will get null where it is not a null originally.

The reason we don’t use (array) and instead use JSON_decode and encode is that (array) is not recursive.

In this case you could either update $COUCHBASE_DEFAULT_DECOPTS, or use couchbase_basic_decoder_v1 instead couchbase_default_decoder when wrapping transcoders. The following two examples are equivalent:

<?php
$cluster = new CouchbaseCluster("couchbase://localhost");
$bucket = $cluster->openBucket("default");


$COUCHBASE_DEFAULT_DECOPTS = array(
    'jsonassoc' => true
);
$bucket->setTranscoder(

  // encoder($value) -> array($bytes, $flags, $datatype)
  couchbase_default_encoder,

  // decoder($bytes, $flags, $datatype) -> $value
  function ($bytes, $flags, $datatype) {
    if ($flags == 0) {
       $flags = COUCHBASE_CFFMT_JSON;
    }
    return couchbase_default_decoder($bytes, $flags, $datatype);
  }

);

printf("Wrapped transcoders\n");
var_dump($bucket->get("foo_json_flags"));
var_dump($bucket->get("foo_zero_flags"));
<?php
$cluster = new CouchbaseCluster("couchbase://localhost");
$bucket = $cluster->openBucket("default");

$bucket->setTranscoder(

  // encoder($value) -> array($bytes, $flags, $datatype)
  couchbase_default_encoder,

  // decoder($bytes, $flags, $datatype) -> $value
  function ($bytes, $flags, $datatype) {
    if ($flags == 0) {
       $flags = COUCHBASE_CFFMT_JSON;
    }
    return couchbase_basic_decoder_v1($bytes, $flags, $datatype, array('jsonassoc' => true));
  }

);

printf("Wrapped transcoders\n");
var_dump($bucket->get("foo_json_flags"));
var_dump($bucket->get("foo_zero_flags"));

And output arrays as you would expect:

Wrapped transcoders
object(CouchbaseMetaDoc)#4 (5) {
  ["error"]=>
  NULL
  ["value"]=>
  array(1) {
    ["foo"]=>
    string(3) "bar"
  }
  ["flags"]=>
  int(33554438)
  ["cas"]=>
  string(10) "20vtgyjz10"
  ["token"]=>
  NULL
}
object(CouchbaseMetaDoc)#4 (5) {
  ["error"]=>
  NULL
  ["value"]=>
  array(1) {
    ["foo"]=>
    string(3) "bar"
  }
  ["flags"]=>
  int(0)
  ["cas"]=>
  string(10) "2a9yzs4844"
  ["token"]=>
  NULL
}
$COUCHBASE_DEFAULT_DECOPTS = array(
    'jsonassoc' => true
);
$couchBucket->setTranscoder(couchbase_default_encoder(array()), function($bytes, $flags, $datatype) {
    if ($flags == 0) {
        $flags = COUCHBASE_CFFMT_JSON;
    } //$flags == 0
    return couchbase_default_decoder($bytes, $flags, $datatype);
});

Would that work out? It seems to work but I’m still unsure about this line, specifically the array() parameter.

$couchBucket->setTranscoder(couchbase_default_encoder(array()), function($bytes, $flags, $datatype) {
couchbase_default_encoder(array())

this is not correct, you should specify function name, or string "couchbase_default_encoder". What version of PHP are you using?

PHP 5.5.9-1ubuntu4.19

Does it work when you specify name of the function as a string?

$couchBucket->setTranscoder(couchbase_default_encoder("couchbase_default_encoder"), function($bytes, $flags, $datatype) {
    if ($flags == 0) {
        $flags = COUCHBASE_CFFMT_JSON;
    } //$flags == 0
    return couchbase_default_decoder($bytes, $flags, $datatype);
});

Works. But it did with array() as the argument also.