We are moving our forum in GitHub Discussions. For questions about Phalcon v3/v4 you can visit here and for Phalcon v5 here.

Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

multiple call of User::findById

Hi Everybody, Just started with phalcon and ODM, What I can't understand is the folowing sample

>  $user1 = User::findById(new MongoId('556c639d6cc69be42600002a'));

>  $user2 = User::findById(new MongoId('556c6ee652ce0aa4b9ee58ad'));

>  echo "{$user1->getId()} => {$user1->firstName}<br />";

>  echo "{$user2->getId()} => {$user2->firstName}<br />";

>  die;

The output is

556c6ee652ce0aa4b9ee58ad => User 1

Fatal error: Call to a member function getId() on a non-object in IndexController.php on line 15

Expected:

556c6ee652ce0aa4b9ee58ad => User 1

556c639d6cc69be42600002a => User 2

Both records exist, why 2nd call on same model doesn't give me an object?

I'm testing this on windows 8 machine, with phalcon 2.0.2 and php 5.4.29

User::findById is expecting an integer as its sole argument. You're passing it an object - an instance of MongoId. As a result $user1 and $user2 are probably NULL, rather than an instance of User.

The method just make a findFirst(["_id": mongoId]), is your field called _id? https://github.com/phalcon/cphalcon/blob/2.0.x/phalcon/mvc/collection.zep#L933-L957



1.4k

Thank You,

Here is the real world sample. Can someone run it and show the output?

I tested this on mac and windows pc, but result is same, php 5.5.25, phalcon 2.0.2, mongo 3.0.3

Mongo Data:

> use testdb
switched to db testdb
> db.users.insert({name: "Oleg"})
WriteResult({ "nInserted" : 1 })
> db.users.insert({name: "James"})
WriteResult({ "nInserted" : 1 })
> db.users.find()
{ "_id" : ObjectId("556ecc523853a3a051cef3a2"), "name" : "Oleg" }
{ "_id" : ObjectId("556ecc6b3853a3a051cef3a3"), "name" : "James" }
> 
<?php

use Phalcon\Loader;
use Phalcon\Mvc\View;
use Phalcon\Mvc\Url as UrlProvider;
use Phalcon\Mvc\Application;
use Phalcon\Mvc\Collection\Manager as CollectionManager;
use Phalcon\DI\FactoryDefault;
use Phalcon\Events\Manager as EventsManager;

try {
    // Register an autoloader
    $loader = new Loader();
    $loader->registerDirs(array(
        '../app/controllers/',
        '../app/models/'
    ))->register();

    // Create a DI
    $di = new FactoryDefault();
    // Setup the view component
    $di->set('view', function(){
        $view = new View();
        $view->setViewsDir('../app/views/');
        return $view;
    });
    // Setup a base URI so that all generated URIs include the "tutorial" folder
    $di->set('url', function(){
        $url = new UrlProvider();
        $url->setBaseUri('/tutorial/');
        return $url;
    });
    // Simple database connection to localhost
    $di->set('mongo', function() {
        $mongo = new MongoClient();
        return $mongo->selectDB("testdb");
    }, true);
    //Registering the collectionManager service
    $di->set('collectionManager', function() {
        $modelsManager = new CollectionManager();
        return $modelsManager;
    }, true);
    // Handle the request
    $application = new Application($di);
    echo $application->handle()->getContent();
} catch(\Exception $e) {
     echo "PhalconException: ", $e->getMessage();
}
<?php

use Phalcon\Mvc\Collection;

class User extends Collection
{
    public $name;

    public function initialize()
    {
        $this->setSource('users');
    }
}
<?php

use Phalcon\Mvc\Controller;

class IndexController extends Controller
{

    public function indexAction()
    {
        echo "<h1>Hello!</h1>";

        $user1 = User::findById(new MongoId('556ecc523853a3a051cef3a2'));
        $user2 = User::findById(new MongoId('556ecc6b3853a3a051cef3a3'));

        echo $user1->name;
        echo $user2->name;
    }

}

Output:


Hello!
Oleg
Notice: Trying to get property of non-object in /phalcon/app/controllers/IndexController.php on line 16


1.4k

Yes, it is _id, I added another example

The method just make a findFirst(["_id": mongoId]), is your field called _id? https://github.com/phalcon/cphalcon/blob/2.0.x/phalcon/mvc/collection.zep#L933-L957



34.6k
Accepted
answer

I'm running this small script to reproduce the issue and it works:

<?php

use Phalcon\DI,
    Phalcon\Mvc\Collection,
    Phalcon\Mvc\Collection\Manager as CollectionManager;

$di = new DI();

$mongo = new \MongoClient();
$db = $mongo->selectDB("store");

// Insert sample data
$db->selectCollection("robots")->insert(["name" => "Voltron"]);
$db->selectCollection("robots")->insert(["name" => "Ultron"]);

$di->set('mongo', $db);

$di->set('collectionManager', function() {
    $modelsManager = new CollectionManager();
    return $modelsManager;
}, true);

// Maps to collection "robots"
class Robots extends Collection
{

}

// Accumulate the IDS
$ids = array();
foreach (Robots::find() as $robot) {
    $ids[] = $robot->getId();
}

// Find the ids
foreach ($ids as $id) {
    $robot = Robots::findById(new \MongoId((string) $id));
    echo $robot->name, PHP_EOL;
}


1.4k
edited Jun '15

It seems I understand the issue now. It is initialize method and setSource

// Maps to collection "the_robots"
class Robots extends Collection
{
    public function initialize()
    {
        $this->setSource("the_robots");
    }
}

The workaround is to use getSource method instead, It seems like a bug though? I will check phalcon sources