2

I have installed a new server running (alpine) linux with Apache and PHP7. I have also installed the mongodb driver. The following is what I see when I run phpinfo():

mongodb support enabled
mongodb version 1.1.10-dev
mongodb stability   devel
libmongoc version   1.3.6
libbson version 1.3.6

I have also installed the mongodb php7 library (https://pkgs.alpinelinux.org/package/edge/testing/x86_64/mongo-php7-library) and it created the following dir structure for me:

webdev1:/var/www/# ls -lah /usr/lib/php7/vendor/mongodb/mongodb/
total 104
drwxr-xr-x    6 root     root        4.0K Aug 16 18:03 .
drwxr-xr-x    3 root     root        4.0K Aug 15 18:07 ..
-rw-r--r--    1 root     root        5.1K Sep 23  2016 BulkWriteResult.php
-rw-r--r--    1 root     root        5.3K Aug 16 18:03 Client.php
-rw-r--r--    1 root     root       27.1K Sep 23  2016 Collection.php
-rw-r--r--    1 root     root        9.6K Sep 23  2016 Database.php
-rw-r--r--    1 root     root        1.3K Sep 23  2016 DeleteResult.php
drwxr-sr-x    2 root     root        4.0K Aug 15 18:07 Exception
-rw-r--r--    1 root     root        2.0K Sep 23  2016 InsertManyResult.php
-rw-r--r--    1 root     root        2.0K Sep 23  2016 InsertOneResult.php
drwxr-sr-x    2 root     root        4.0K Aug 15 18:07 Model
drwxr-sr-x    2 root     root        4.0K Aug 15 18:07 Operation
-rw-r--r--    1 root     root        3.3K Sep 23  2016 UpdateResult.php
-rw-r--r--    1 root     root        4.3K Sep 23  2016 functions.php
drwxr-sr-x    6 root     root        4.0K Aug 16 17:41 tests

I'm trying to write a basic page now that will prove that this library is working.
So far I have:

  1. Copied the library files into a sub folder in my test project. So i have this in my test web app folder:

    webdev1:/var/www/localhost/htdocs/test# ls -lah
    total 16
    drwxr-sr-x    3 root     root        4.0K Aug 16 18:41 .
    drwxr-sr-x    4 root     root        4.0K Aug 16 18:30 ..
    drwxr-xr-x    6 root     root        4.0K Aug 16 18:44 mongodb
    -rw-r--r--    1 root     root         516 Aug 16 18:39 test.php
    
    webdev1:/var/www/localhost/htdocs/test# ls -lah mongodb/
    total 104
    drwxr-xr-x    6 root     root        4.0K Aug 16 18:44 .
    drwxr-sr-x    3 root     root        4.0K Aug 16 18:41 ..
    -rw-r--r--    1 root     root        5.1K Aug 16 18:32 BulkWriteResult.php
    -rw-r--r--    1 root     root        5.3K Aug 16 18:32 Client.php
    -rw-r--r--    1 root     root       27.1K Aug 16 18:32 Collection.php
    -rw-r--r--    1 root     root        9.6K Aug 16 18:32 Database.php
    -rw-r--r--    1 root     root        1.3K Aug 16 18:32 DeleteResult.php
    drwxr-sr-x    2 root     root        4.0K Aug 16 18:32 Exception
    -rw-r--r--    1 root     root        2.0K Aug 16 18:32 InsertManyResult.php
    -rw-r--r--    1 root     root        2.0K Aug 16 18:32 InsertOneResult.php
    drwxr-sr-x    2 root     root        4.0K Aug 16 18:32 Model
    drwxr-sr-x    2 root     root        4.0K Aug 16 18:32 Operation
    -rw-r--r--    1 root     root        3.3K Aug 16 18:32 UpdateResult.php
    -rw-r--r--    1 root     root        4.3K Aug 16 18:32 functions.php
    drwxr-sr-x    6 root     root        4.0K Aug 16 18:41 tests
    
  2. Create a test.php page with the following code:

    "; echo extension_loaded("mongodb") ? "loaded\n" : "not loaded\n"; echo "Test 2 - MongoDB Client Library working...
    "; $client = new MongoDB\Client("mongodb://localhost:27017"); $collection = $client->jjtest->col1; $result = $collection->find(); var_dump($result); ?>

Results

When I run the test.php page, it shows that my driver is loaded... but I'm getting the error:

Test 1 - Mongodb Driver loaded?
loaded Test 2 - MongoDB Client Library working...

Fatal error: Uncaught Error: Class 'MongoDB\Database' not found in /var/www/localhost/htdocs/test/mongodb/Client.php:168 Stack trace: #0 /var/www/localhost/htdocs/test/mongodb/Client.php(93): MongoDB\Client->selectDatabase('jjtest') #1 /var/www/localhost/htdocs/test/test.php(9): MongoDB\Client->__get('jjtest') #2 {main} thrown in /var/www/localhost/htdocs/test/mongodb/Client.php on line 168

What I've tried So Far

To prove that mongo itself is working, I launched a CLI and ran this command:

> use jjtest
switched to db jjtest
> show collections
col1
> db.col1.find();
{ "_id" : ObjectId("5994980ba9e72bb4f6afed66"), "name" : "john", "age" : "99" }
>

I'm currently reading up on namespaces and the autoloader.php (Why my autoload.php of composer doesn't work?) but nothing I've tried so far is working there either. The files that were auto created by installing the mongo-php7-library doesn't include an autoloader.php that i can point to.

Update 1

I also tried to include this at the top of my test.php file:

 require_once __DIR__ . "/mongodb/";

But I get the following error:

Warning: require_once(/var/www/localhost/htdocs/test/mongodb/): failed to open stream: No error information in /var/www/localhost/htdocs/test/test.php on line 1

Fatal error: require_once(): Failed opening required '/var/www/localhost/htdocs/test/mongodb/' (include_path='.:') in /var/www/localhost/htdocs/test/test.php on line 1

dot
  • 14,928
  • 41
  • 110
  • 218

1 Answers1

0

You are struggling with php's class loading. Currently you are doing this by yourself with a single require statement for mongodb/Client.php, but this very file references other class (and therefor: files) that are not loaded. That's why php is complaining about a missing class. Calling require on a folder does not help there, as you already noticed.

Unless you want to stick with a require call for each and every class in your project, you should now check for autoloading. In php, autoloading is basically a function that gets triggered for each class that is referenced by code at runtime and loads the proper file containing the class definition.

A simple example that you could include to your test.php:

<?php

/**
 * Load file with class
 * 
 * @param string $class
 * 
 */
function mongo_autoload($class)
{
    /**
     * All classes of your library are defined within the "MongoDB" namespace.
     * Example: MongoDB\Model\BSONArray
     * Each part after "MongoDB" refers to a folder, the final part is the filename (without .php suffix).
     * We strip the MongoDBm add .php suffix and load the file from mongodb/ folder   
     */
    $filename = str_replace('MongoDB\\', '', $class) . '.php';
    require 'mongodb/' . $filename;
}

/**
 * Here we register our function as autoload method
 */
spl_autoload_register('mongo_autoload');


//proof that the mongo driver is loaded:
echo "Test 1 - Mongodb Driver loaded?<BR>";
echo extension_loaded("mongodb") ? "loaded\n" : "not loaded\n";

echo "Test 2 - MongoDB Client Library working...<BR>";
$client = new MongoDB\Client("mongodb://localhost:27017");
$collection = $client->jjtest->col1;
$result = $collection->find();
var_dump($result);
?>

Working this way is not very handy, as there are different naming strategies for php classes and namespaces and you cannot control which one to use if you have many packages you depend on. In php-land we got composer for this, which manages every package your project depends on and creates proper autoloading strategies for them. You only need to include one autload.php after installing your dependencies. Your lib is distributed with composer as well, see their readme ;)

Jojo
  • 2,720
  • 1
  • 17
  • 24
  • So I understand in theory what composer is but I think what's not clear is who is supposed to create autoload.php. is it me? or is it the vendor / third party that would provide an autoload.php for their library for me to consume as a user? I've been trying to follow the instructions for consuming / using a library via composer... but when I do that for this library, i get a bunch of errors. I'm just about to give your test code above a run through. I will report back. – dot Aug 17 '17 at 13:18
  • I tried your example, and yes, the error message goes away... which tells me that it's ME that has to generate the autoload.php for this library that I want to consume. Now that I understand this part, I think I will repost a new question that displays the errors I get when I try to run the composer commands. Initially, because I wasn't sure who was to generate the autoload.php, I didn't post the details of the errors I get when I try to run the composer commands. – dot Aug 17 '17 at 13:27
  • The other question that arises for me is should i have installed the package via the apk interface or does composer take care of that? (I know I need to install the mongo driver and have it available before I can install / use the mongo php7 library.) – dot Aug 17 '17 at 13:33
  • you should let composer take care of your dependencies. it will also solve your class loading issues – Jojo Aug 17 '17 at 14:53
  • yes, i agree i should let composer do the work. I guess the part that's not clear to me is whether or not I should have installed the mongo-php7-library via apk, or if composer would download all the files I need for me? Sorry for remedial questions, but I'm a noob as you can tell, with composer. – dot Aug 17 '17 at 15:14
  • Yes, composer will download all the files a library provides ;) – Jojo Aug 17 '17 at 15:26
  • ok. so then the fact that someone contributed an apk package for linux that includes all the library files already... means.. there must be a way to maybe install this library via apk and "point" composer to the local copy some how?? anyways. I can post this as a separate question since i think i'm a little clearer on how composer is supposed to work – dot Aug 17 '17 at 17:38
  • Installing via apk is just one way of installing a lib, leaving you alone with all other setup tasks. Composer is the preferred way for php packages. Post your specific problems as another question then. – Jojo Aug 17 '17 at 17:41