Luracast / Laravel-Database

Laravel database for your non laravel projects. Built on top of illuminate/database to provide migration, seeding and artisan support
85 stars 12 forks source link

Can't connect to database #1

Closed tonglil closed 10 years ago

tonglil commented 10 years ago

Hi, I integrated this library into my application with Artisan commands running smoothly.

However now when I am trying to use my models, it seems like it is unable to connect with the database (even though I have set up all of the connection details in database.php): Call to a member function connection() on a non-object in /vagrant/vendor/illuminate/database/Illuminate/Database/Eloquent/Model.php

I see you have loaded the db singleton here, but do I still have to initialize another "capsule" instance? Or is there a way I can access the already loaded singleton capsule?

Thanks for all the work so far :+1:

Update:

My work around for the moment is to expose the database singleton to the app (there is probably a performance hit so I'm still interested in the "proper" solution):

$app->singleton('db', function () use ($app) {
    $config = $app['config'];
    $default = $config['database.default'];
    $fetch = $config['database.fetch'];
    $db = new Capsule($app);
    $config['database.fetch'] = $fetch;
    $config['database.default'] = $default;
    $db->addConnection($config['database.connections'][$default]);
    $db->setEventDispatcher($app['events']);
    $db->setAsGlobal();
    $db->bootEloquent();

    return $db->getDatabaseManager();
});

// Expose the database connection to the models without needing the $app
$db = $app->make('db');
Arul- commented 10 years ago

I'm using this project in my day to day projects and did not come accross the issue so far!

Here we are lazy loading db so that it is initialized only when needed. Your workaround seems to initialize it immediately.

Can you share the minimal code to reproduce the issue at our end?

tonglil commented 10 years ago

I would like to share the code, but it will take me a bit to shave it down (I'll report back soon).

Basically I am trying to use this wonderful package with CodeIgniter and I am unable to get the lazy load to work (it seems like CodeIgniter does not know what has been loaded / the db is not visible).

Maybe this stacktrace can give you an idea of what I mean.

screen shot 2014-10-07 at 4 34 47 pm

I included bootstrap/autoload.php in CodeIgniter's public/index.php at the very top so that I know it will boot the app, but I am unsure how to access those singletons. Perhaps you can explain that to me? Is there a open source app that I can reference from?

Best regards.

tonglil commented 10 years ago

PS: I know that this way can work because in autoload.php, I am also booting other Laravel components into singletons (validator for example) and they are working.

However the validator is being called by by a third party library (Watson/Validating), therefore I am still unsure of how I can call them from my code :disappointed:

Arul- commented 10 years ago

Problem could be because of the way code igniter autoloader works. Just try reversing the process

I mean use the bootstrap autoloader first and load code igniters autoloader from there

Arul- commented 10 years ago

does php artisan tinker make DB::table('TABLE_NAME_HERE')->... and other Model queries work?

Arul- commented 10 years ago

DB is actually initialized when you use the DB, Model classes without proper namespaces. There is a smart autoloader that maps them to actual namespaced classes using class_alias method

So make sure you are extending Eloquent and not Illuminate\Database\Eloquent\Model

tonglil commented 10 years ago

1: I tried to load CI before autoloader.php, but I think it doesn't reach past the CI loader. 2: Yes, DB class works through tinker (for example DB::table('users')->get(); and Config::get('database');). 3: The thing is, I have to use namespacing because I need to load other classes that are namespaced. If I do not add use Illuminate\Database\Eloquent\Model as Eloquent; then it tries to look for Eloquent in the class's namespace (which is why I think autoloader.php isn't getting booted).

I will do my best to get a code example to you asap.

tonglil commented 10 years ago

If I add a new connection resolver to each of the models I can get it so that I don't need to initialize the $db right away (but this is not what I want because it seems more like a hack than using the $app):

    $CI = & get_instance();

    $config = $CI->db; // Get the DB object

    $pdo = new PDO('mysql:host='.$config->hostname.';dbname='.$config->database, $config->username, $config->password);

    $drivers = array(
        'mysql' => '\Illuminate\Database\MySqlConnection',
    );

    $conn = new $drivers['mysql']($pdo, $config->database, $config->dbprefix);

    $resolver = new Illuminate\Database\ConnectionResolver;
    $resolver->addConnection('default', $conn);
    $resolver->setDefaultConnection('default');

    \Illuminate\Database\Eloquent\Model::setConnectionResolver($resolver);
tonglil commented 10 years ago

Order of loading:

  1. Composer's autoload has to go above loading CodeIgniter's core (because the core uses the classes loaded by composer)
  2. CI's core
  3. This library's require_once autoload.php never gets called (because CI seems to stop after loading itself).
Arul- commented 10 years ago

I'm not suggesting to avoid namespacing totally. Use namespaces for all classes except Laravel classes.

Refer them with '/' in front if you are using them in namespaced classes (/DB)

tonglil commented 10 years ago

Oh gosh, I think that fixes everything (I understand what you mean now, the loader loads those classes into a root namespace. Interesting, I will test further to confirm and report back.

Thank you! :smiley:

tonglil commented 10 years ago

:+1:

Arul- commented 10 years ago

Glad to hear that the issue is solved for you!

cheche22 commented 9 years ago

how can i connect the laravel code to database

Arul- commented 9 years ago

I'm not sure I understand your question!