MongoException: zero-length keys are not allowed, did you use $ with double quotes? - mongodb

I'm using symfony2 and mongodb, until today, everything is OK, but I create a new document, and suddenly, appears this error :
"MongoException: zero-length keys are not allowed, did you use $ with double quotes?"
$dm = $this->get('doctrine.odm.mongodb.document_manager');
$_repo = $dm->getRepository('CantaoCustomerBundle:CustomerTags');
$_repo->findOneByCustomer($customer);
The $customer it's OK, the repository is empty, and my document class is like this :
/**
* #MongoDB\ID
**/
private $id;
/**
* #MongoDB\ReferenceOne(targetDocument="Tapronto\Mats\ProductBundle\Document\Tag", cascade={"persist"})
**/
private $tag;
/**
* #MongoDB\ReferenceOne(targetDocument="Tapronto\Mats\CustomerBundle\Document\Customer", cascade={"persist"})
**/
private $customer;
/**
* #MongoDB\Float
**/
private $points;
/**
* #MongoDB\Int
**/
private $viewed;
/**
* #MongoDB\Int
**/
private $brought;
/**
* #MongoDB\Int
**/
private $favorited;
/**
* #MongoDB\Date
* #Gedmo\Timestampable(on="create")
**/
private $createdAt;
/**
* #MongoDB\Date
* #Gedmo\Timestampable(on="update")
**/
private $updatedAt;
Can anyone help me, have some idea, I tried everything and nothing seems to work

I just fixed this by using the referenced object's ID instead of the reference object itself as my search term.
$_repo->findOneByCustomer($customer->getId());
EDIT:
That isn't throwing the exception but it isn't actually returning anything either. I tried using new MongoId($id) as was suggested a few places (Doctrine MongoDB find by id), but that didn't work either. Finally, I found something in the full query builder that searches by references (note: this uses the object instead of the object's ID).
$dm->createQueryBuilder()->find('CantaoCustomerBundle:CustomerTags')
->field('customer')->references($customer)
->getQuery()->execute();
I feel like this should be done more simply (like you did originally), but this fix is working for me.

It could be that you're trying to persist an object private attribute.
If that's not the case a good way to debug is to shut off the zero-length key check so that you can actually debug by checking what it's being written into mongo.
zero-length keys are not allowed, did you use $ with double quotes?
Code: 1
You tried to save "" as a key. You generally should not do this. "" can mess up subobject access and is used by MongoDB internally. However, if you really want, you can set mongo.allow_empty_keys to true in your php.ini file to override this sanity check. If you override this, it is highly recommended that you set error checking to strict to avoid string interpolation errors.
http://php.net/manual/en/mongo.configuration.php#ini.mongo.allow-empty-keys

Related

zend2 + doctrine 2 Uncaught exception 'Doctrine\Common\Annotations\AnnotationException' $jobId does not exist

I am new to zend 2 and Doctrine 2. I tried to create an entity class but got the following message:
Fatal error: Uncaught exception
'Doctrine\Common\Annotations\AnnotationException' with message
'[Semantical Error] The annotation "#Doctrine\ORM\Mapping\jobId" in
property Workers\Entity\Jobsought::$jobId does not exist, or could not
be auto-loaded
Below is the entity class
namespace Workers\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
/**
*
*
* #ORM\Entity
* #ORM\Table(name="worker_main_jobsort")
* #property int $jobId
*/
class Jobsought implements InputFilterAwareInterface
{
protected $inputFilter;
/**
* #ORM\jobId
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $jobId;
/**
* Magic getter to expose protected properties.
*
* #param string $property
* #return mixed
*/
public function __get($property)
{
return $this->$property;
}
/**
* Magic setter to save protected properties.
*
* #param string $property
* #param mixed $value
*/
public function __set($property, $value)
{
$this->$property = $value;
}
}
Any ideas why the ORM cannot map it? The table exist in my database.
Also just started out using the two of these combined - but think I know what your issue is.
First off, you can't try specifying any "strange" (according to doctrine strange) annotations without using the #ignore directive.
Secondly, I think you're trying to say with #property int $jobId that "$jobId" is your PK? Well you're already doing so when you say #ORM\GeneratedValue(strategy="AUTO"), telling doctrine to map jobid to be your PK. Also, I read somewhere that adding name="job_id" to your #Column annotation is good practice, but don't quote me on that. Guess it doesn't really matter.
Hope this helps!
Edit -
My bad, also missed that you need to remove #ORM\jobId as it's not a valid doctrine annotation (jobId that is). Just specify it as #ORM\Id and you should be fine.

dangerous to select fields in MongoDB Doctrine?

I'm not sure whether this is my fault. But I find that select fields in mongodb doctrine queries can lead to horrible consequence.
For example, I have a Page document like:
class Page
{
/**
* #MongoDB\String
*/
private $title;
/**
* #MongoDB\Int
*/
private $nbClicks = 0;
/**
* #MongoDB\Int
*/
private $nbShares = 0;
// other fields ...
}
I may write some query like
$queryBuilder->select('title')->getQuery()->execute();
And somewhere behind this I do
$dm->flush();
nbClicks and nbShares of Pages I retrieved earlier are set to 0.
Is this something expected or might be a bug?
Thank you!

SphinxQL & Phalcon\Mvc\Model

I have a Sphinx search engine running on MySQL protocol and I use Phalcon\Db\Adapter\Pdo\Mysql to connect to it. Sphinx tables are implemented as models.
When I try to select (using SpinxQL) I, obviously, get an error when database adapter attempts to extract table metadata running queries against tables which are not supported and not present respectively in SpinxQL. There is a workaround in the documentation showing how to manually assign metadata... But being to lazy by nature I want to try to automate metadata generation.
I assume that metadata is produced by the database adapter, probably as a result of calling getColumnsList() on the instance following getColumnDefinition() or something else (???). Is this my assumption correct? I want is to extend Phalcon\Db\Adapter\Pdo\Mysql and override those methods to be compatible with Sphinx.
Thanks in advance for your suggestions!
Ok, you need to override at least two methods to make this work, the following class would work:
<?php
class SphinxQlAdapter extends Phalcon\Db\Adapter\Pdo\Mysql implements Phalcon\Db\AdapterInterface
{
/**
* This method checks if a table exists
*
* #param string $table
* #param string $schema
* #return boolean
*/
public function tableExists($table, $schema=null)
{
}
/**
* This method describe the table's columns returning an array of
* Phalcon\Db\Column
*
* #param string $table
* #param string $schema
* #return Phalcon\Db\ColumnInterface[]
*/
public function describeColumns($table, $schema=null)
{
}
}
Then in your connection, you use the new adapter:
$di->set('db', function(){
return new SphinxQlAdapter(
//...
);
});

Symfony/Doctrine: "Catchable Fatal Error: Object of class <type> could not be converted to string" when persisting

A symfony2 application has a Job entity that has as a property of type WebSite.
A simplified representation of this without other properties or methods:
/**
* #ORM\Entity
* #ORM\Table(name="Job")
*/
class Job
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="integer", name="website_id", nullable=false)
* #ORM\ManyToOne(targetEntity="Example\ExampleBundle\Entity\WebSite")
*/
protected $website;
}
Symfony/Doctrine is trying to cast the website property to a string when persisting resulting in the error:
Catchable Fatal Error: Object of class
Example\ExampleBundle\Entity\WebSite could not be converted to string
in /vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php line 131
I believe the above #ORM\Column annotation denotes the website property to be an integer. I don't understand why Symfony/Doctrine wishes to try and convert the website property to a string.
Non-ideal workarounds I have tried in an attempt to resolve the matter:
Adding __toString() method to WebSite, returning a string representation of the id property, causes the correct value to ultimately end up in the Job.website_id datafield; this workaround is impractical as I will in the future need __toString() to be available to present a string elsewhere in the application.
Removing the #ORM\Column annotation from the website property; this results in all future diff-generated migrations (php app/console doctrine:migrations:diff) removing the 'not null' aspect of the relevant database field.
Are there any changes I should make to the above annotation to inform Symfony/Doctrine to call the getId() method of WebSite to get what it needs when persisting? Are there any changes I could make to WebSite to achieve the same?
What changes are required to ensure that the above annotation can remain in place such that Doctrine ultimately calls WebSite.getId() to get what it needs when persisting instead of trying to cast the object to a string?
You have to remove the #ORM\Column(type="integer" annotation from the $website property.
To be sure that the website_id column keeps the NOT NULL constraint, add a JoinColumn annotation with nullable=false in it:
/**
* #var Example\ExampleBundle\Entity\WebSite
*
* #ORM\ManyToOne(targetEntity="Example\ExampleBundle\Entity\WebSite")
* #ORM\JoinColumn(name="website_id", referencedColumnName="id", nullable=false)
*/
protected $website;

is it possible to override doctrine2 persistentobject magic getters and setting

Can anybody tell me whether its posible to override doctrine2 persistentobject magic getters\setters? i'd like to do the below:-
public function setDob($dob)
{
$this->dob= new \Date($date);
}
however my entity is defined as:-
use Doctrine\Common\Persistence\PersistentObject;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="Ajfit\Repository\User")
* #ORM\HasLifecycleCallbacks
*/
class User extends \Doctrine\Common\Persistence\PersistentObject
{
/**
* #var date $dob
*
* #ORM\Column(name="dob", type="date")
*/
protected $dob;
}
the public function setDob does not get called when I create the entity using:-
public function getNewRecord() {
return $this->metadata->newInstance();
}
I get the below error:-
Notice:- array to string conversion ...Doctrine\DBAL\Statement.php on line 98
Any help would be much apprieciated.
Thanks
Andrew
__call of PersistentObject#__call will not be called if you defined the setDob method.
What you're doing there is creating a new instance via metadata. What you are doing there is probably assuming that __construct or any setter/getter should be called by the ORM. Doctrine avoids to call any methods on your object when generating it via metadata/hydration (check ClassMetadataInfo#newInstance to see how it is done) as it does only know it's fields.
This allows you to be completely independent from Doctrine's logic.
About the notice, that is a completely different issue coming from Doctrine\DBAL\Statement, which suggests me that you have probably some wrong parameter binding in a query. That should be handled separately.