Skip to content

Use single connection using DSN for testing #2462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions .github/workflows/build-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ jobs:

build:
runs-on: ${{ matrix.os }}
name: PHP v${{ matrix.php }} with Mongo v${{ matrix.mongodb }}
continue-on-error: ${{ matrix.experimental }}
name: PHP v${{ matrix.php }} with MongoDB ${{ matrix.mongodb }}
strategy:
matrix:
include:
- { os: ubuntu-latest, php: 8.0, mongodb: '4.0', experimental: false }
- { os: ubuntu-latest, php: 8.0, mongodb: 4.2, experimental: false }
- { os: ubuntu-latest, php: 8.0, mongodb: 4.4, experimental: false }
- { os: ubuntu-latest, php: 8.0, mongodb: '5.0', experimental: false }
- { os: ubuntu-latest, php: 8.1, mongodb: '4.0', experimental: false }
- { os: ubuntu-latest, php: 8.1, mongodb: 4.2, experimental: false }
- { os: ubuntu-latest, php: 8.1, mongodb: 4.4, experimental: false }
- { os: ubuntu-latest, php: 8.1, mongodb: '5.0', experimental: false }
os:
- ubuntu-latest
mongodb:
- '4.0'
- '4.2'
- '4.4'
- '5.0'
php:
- '8.0'
- '8.1'
services:
mongo:
image: mongo:${{ matrix.mongodb }}
Expand Down Expand Up @@ -88,7 +88,7 @@ jobs:
run: |
./vendor/bin/phpunit --coverage-clover coverage.xml
env:
MONGO_HOST: 0.0.0.0
MONGODB_URI: 'mongodb://127.0.0.1/'
MYSQL_HOST: 0.0.0.0
MYSQL_PORT: 3307
- uses: codecov/codecov-action@v1
Expand Down
41 changes: 15 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,47 +143,36 @@ Keep in mind that these traits are not yet supported:

Configuration
-------------
You can use MongoDB either as the main database, either as a side database. To do so, add a new `mongodb` connection to `config/database.php`:

To configure a new MongoDB connection, add a new connection entry to `config/database.php`:

```php
'mongodb' => [
'driver' => 'mongodb',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', 27017),
'dsn' => env('DB_DSN'),
'database' => env('DB_DATABASE', 'homestead'),
'username' => env('DB_USERNAME', 'homestead'),
'password' => env('DB_PASSWORD', 'secret'),
'options' => [
// here you can pass more settings to the Mongo Driver Manager
// see https://www.php.net/manual/en/mongodb-driver-manager.construct.php under "Uri Options" for a list of complete parameters that you can use

'database' => env('DB_AUTHENTICATION_DATABASE', 'admin'), // required with Mongo 3+
],
],
```

For multiple servers or replica set configurations, set the host to an array and specify each server host:
The `dsn` key contains the connection string used to connect to your MongoDB deployment. The format and available options are documented in the [MongoDB documentation](https://docs.mongodb.com/manual/reference/connection-string/).

Instead of using a connection string, you can also use the `host` and `port` configuration options to have the connection string created for you.

```php
'mongodb' => [
'driver' => 'mongodb',
'host' => ['server1', 'server2', ...],
...
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', 27017),
'database' => env('DB_DATABASE', 'homestead'),
'username' => env('DB_USERNAME', 'homestead'),
'password' => env('DB_PASSWORD', 'secret'),
'options' => [
'replicaSet' => 'rs0',
'appname' => 'homestead',
],
],
```

If you wish to use a connection string instead of full key-value params, you can set it so. Check the documentation on MongoDB's URI format: https://docs.mongodb.com/manual/reference/connection-string/

```php
'mongodb' => [
'driver' => 'mongodb',
'dsn' => env('DB_DSN'),
'database' => env('DB_DATABASE', 'homestead'),
],
```
The `options` key in the connection configuration corresponds to the [`uriOptions` parameter](https://www.php.net/manual/en/mongodb-driver-manager.construct.php#mongodb-driver-manager.construct-urioptions).

Eloquent
--------
Expand Down Expand Up @@ -223,7 +212,7 @@ class Book extends Model
protected $primaryKey = 'id';
}

// Mongo will also create _id, but the 'id' property will be used for primary key actions like find().
// MongoDB will also create _id, but the 'id' property will be used for primary key actions like find().
Book::create(['id' => 1, 'title' => 'The Fault in Our Stars']);
```

Expand All @@ -238,7 +227,7 @@ class Book extends Model
}
```

### Extending the Authenticable base model
### Extending the Authenticatable base model
This package includes a MongoDB Authenticatable Eloquent class `Jenssegers\Mongodb\Auth\User` that you can use to replace the default Authenticatable class `Illuminate\Foundation\Auth\User` for your `User` model.

```php
Expand Down
3 changes: 1 addition & 2 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@
</testsuite>
</testsuites>
<php>
<env name="MONGO_HOST" value="mongodb"/>
<env name="MONGODB_URI" value="mongodb://127.0.0.1/" />
<env name="MONGO_DATABASE" value="unittest"/>
<env name="MONGO_PORT" value="27017"/>
<env name="MYSQL_HOST" value="mysql"/>
<env name="MYSQL_PORT" value="3306"/>
<env name="MYSQL_DATABASE" value="unittest"/>
Expand Down
5 changes: 3 additions & 2 deletions src/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public function raw($expression = null)
$results = iterator_to_array($results, false);

return $this->model->hydrate($results);
} // Convert Mongo BSONDocument to a single object.
} // Convert MongoDB BSONDocument to a single object.
elseif ($results instanceof BSONDocument) {
$results = $results->getArrayCopy();

Expand All @@ -192,7 +192,8 @@ public function raw($expression = null)
* TODO Remove if https://github.com/laravel/framework/commit/6484744326531829341e1ff886cc9b628b20d73e
* wiil be reverted
* Issue in laravel frawework https://github.com/laravel/framework/issues/27791.
* @param array $values
*
* @param array $values
* @return array
*/
protected function addUpdatedAtColumn(array $values)
Expand Down
24 changes: 12 additions & 12 deletions src/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ abstract class Model extends BaseModel
/**
* Custom accessor for the model's id.
*
* @param mixed $value
* @param mixed $value
* @return mixed
*/
public function getIdAttribute($value = null)
{
// If we don't have a value for 'id', we will use the Mongo '_id' value.
// If we don't have a value for 'id', we will use the MongoDB '_id' value.
// This allows us to work with models in a more sql-like way.
if (! $value && array_key_exists('_id', $this->attributes)) {
$value = $this->attributes['_id'];
Expand Down Expand Up @@ -279,7 +279,7 @@ public function originalIsEquivalent($key)
/**
* Remove one or more fields.
*
* @param mixed $columns
* @param mixed $columns
* @return int
*/
public function drop($columns)
Expand Down Expand Up @@ -325,8 +325,8 @@ public function push()
/**
* Remove one or more values from an array.
*
* @param string $column
* @param mixed $values
* @param string $column
* @param mixed $values
* @return mixed
*/
public function pull($column, $values)
Expand All @@ -344,9 +344,9 @@ public function pull($column, $values)
/**
* Append one or more values to the underlying attribute value and sync with original.
*
* @param string $column
* @param array $values
* @param bool $unique
* @param string $column
* @param array $values
* @param bool $unique
*/
protected function pushAttributeValues($column, array $values, $unique = false)
{
Expand All @@ -369,8 +369,8 @@ protected function pushAttributeValues($column, array $values, $unique = false)
/**
* Remove one or more values to the underlying attribute value and sync with original.
*
* @param string $column
* @param array $values
* @param string $column
* @param array $values
*/
protected function pullAttributeValues($column, array $values)
{
Expand Down Expand Up @@ -402,7 +402,7 @@ public function getForeignKey()
/**
* Set the parent relation.
*
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
*/
public function setParentRelation(Relation $relation)
{
Expand Down Expand Up @@ -495,7 +495,7 @@ protected function getRelationsWithoutParent()
* Checks if column exists on a table. As this is a document model, just return true. This also
* prevents calls to non-existent function Grammar::compileColumnListing().
*
* @param string $key
* @param string $key
* @return bool
*/
protected function isGuardableColumn($key)
Expand Down
127 changes: 94 additions & 33 deletions tests/ConnectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,101 @@ public function testDb()
$this->assertInstanceOf(Client::class, $connection->getMongoClient());
}

public function testDsnDb()
public function dataConnectionConfig(): Generator
{
$connection = DB::connection('dsn_mongodb_db');
$this->assertInstanceOf(Database::class, $connection->getMongoDB());
$this->assertInstanceOf(Client::class, $connection->getMongoClient());
yield 'Single host' => [
'expectedUri' => 'mongodb://some-host',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => 'some-host',
'database' => 'tests',
],
];

yield 'Host and port' => [
'expectedUri' => 'mongodb://some-host:12345',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => 'some-host',
'port' => 12345,
'database' => 'tests',
],
];

yield 'Port in host name takes precedence' => [
'expectedUri' => 'mongodb://some-host:12345',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => 'some-host:12345',
'port' => 54321,
'database' => 'tests',
],
];

yield 'Multiple hosts' => [
'expectedUri' => 'mongodb://host-1,host-2',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => ['host-1', 'host-2'],
'database' => 'tests',
],
];

yield 'Multiple hosts with same port' => [
'expectedUri' => 'mongodb://host-1:12345,host-2:12345',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => ['host-1', 'host-2'],
'port' => 12345,
'database' => 'tests',
],
];

yield 'Multiple hosts with port' => [
'expectedUri' => 'mongodb://host-1:12345,host-2:54321',
'expectedDatabaseName' => 'tests',
'config' => [
'host' => ['host-1:12345', 'host-2:54321'],
'database' => 'tests',
],
];

yield 'DSN takes precedence over host/port config' => [
'expectedUri' => 'mongodb://some-host:12345/auth-database',
'expectedDatabaseName' => 'tests',
'config' => [
'dsn' => 'mongodb://some-host:12345/auth-database',
'host' => 'wrong-host',
'port' => 54321,
'database' => 'tests',
],
];

yield 'Database is extracted from DSN if not specified' => [
'expectedUri' => 'mongodb://some-host:12345/tests',
'expectedDatabaseName' => 'tests',
'config' => [
'dsn' => 'mongodb://some-host:12345/tests',
],
];
}

/** @dataProvider dataConnectionConfig */
public function testConnectionConfig(string $expectedUri, string $expectedDatabaseName, array $config): void
{
$connection = new Connection($config);
$client = $connection->getMongoClient();

$this->assertSame($expectedUri, (string) $client);
$this->assertSame($expectedDatabaseName, $connection->getMongoDB()->getDatabaseName());
}

public function testConnectionWithoutConfiguredDatabase(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Database is not properly configured.');

new Connection(['dsn' => 'mongodb://some-host']);
}

public function testCollection()
Expand Down Expand Up @@ -89,33 +179,4 @@ public function testDriverName()
$driver = DB::connection('mongodb')->getDriverName();
$this->assertEquals('mongodb', $driver);
}

public function testAuth()
{
$host = Config::get('database.connections.mongodb.host');
Config::set('database.connections.mongodb.username', 'foo');
Config::set('database.connections.mongodb.password', 'bar');
Config::set('database.connections.mongodb.options.database', 'custom');

$connection = DB::connection('mongodb');
$this->assertEquals('mongodb://'.$host.'/custom', (string) $connection->getMongoClient());
}

public function testCustomHostAndPort()
{
Config::set('database.connections.mongodb.host', 'db1');
Config::set('database.connections.mongodb.port', 27000);

$connection = DB::connection('mongodb');
$this->assertEquals('mongodb://db1:27000', (string) $connection->getMongoClient());
}

public function testHostWithPorts()
{
Config::set('database.connections.mongodb.port', 27000);
Config::set('database.connections.mongodb.host', ['db1:27001', 'db2:27002', 'db3:27000']);

$connection = DB::connection('mongodb');
$this->assertEquals('mongodb://db1:27001,db2:27002,db3:27000', (string) $connection->getMongoClient());
}
}
16 changes: 0 additions & 16 deletions tests/DsnTest.php

This file was deleted.

Loading