Commit 63715f17 by 杨树贤

安装mongo包

parent 263640a8
Showing with 4734 additions and 6 deletions
......@@ -116,7 +116,7 @@ class DealImageService
continue;
}
foreach ($itemList['data']['goods_id'] as $skuId) {
$skuDetail = DB::connection('mongo')->table('sku_detail')->where('sku_id', (string)$skuId)->first();
$skuDetail = DB::connection('mongodb')->table('sku_detail')->where('sku_id', (string)$skuId)->first();
dd($skuDetail);
$detail = $skuDetail['detail'];
if (empty($detail)) {
......
......@@ -15,7 +15,8 @@
"guzzlehttp/guzzle": "6.3",
"doctrine/inflector": "1.1.0",
"doctrine/instantiator": "1.0.2",
"phpdocumentor/reflection-docblock": "3.2.2"
"phpdocumentor/reflection-docblock": "3.2.2",
"jenssegers/mongodb": "3.0.0"
},
"require-dev": {
"fzaninotto/faker": "~1.4",
......
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5775f435235f4562361810bcd2f6e059",
"content-hash": "bcb4747641cc489a902e43d8506a0e13",
"packages": [
{
"name": "classpreloader/classpreloader",
......@@ -520,6 +520,60 @@
"time": "2015-04-20T18:58:01+00:00"
},
{
"name": "jenssegers/mongodb",
"version": "v3.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.tencent.com/repository/composer/jenssegers/mongodb/v3.0.0/jenssegers-mongodb-v3.0.0.zip",
"reference": "81ae6b9abbbae2a8d99c987ee462f7c7591f004f",
"shasum": ""
},
"require": {
"illuminate/container": "^5.1",
"illuminate/database": "^5.1",
"illuminate/events": "^5.1",
"illuminate/support": "^5.1",
"mongodb/mongodb": "^1.0.0"
},
"require-dev": {
"mockery/mockery": "^0.9",
"orchestra/testbench": "^3.1",
"phpunit/phpunit": "^4.0|^5.0",
"satooshi/php-coveralls": "^0.6"
},
"suggest": {
"jenssegers/mongodb-sentry": "Add Sentry support to Laravel-MongoDB",
"jenssegers/mongodb-session": "Add MongoDB session support to Laravel-MongoDB"
},
"type": "library",
"autoload": {
"psr-0": {
"Jenssegers\\Mongodb": "src/",
"Jenssegers\\Eloquent": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Jens Segers",
"homepage": "https://jenssegers.com"
}
],
"description": "A MongoDB based Eloquent model and Query builder for Laravel 4",
"homepage": "https://github.com/jenssegers/laravel-mongodb",
"keywords": [
"database",
"eloquent",
"laravel",
"model",
"mongo",
"mongodb"
],
"time": "2016-02-18T22:30:47+00:00"
},
{
"name": "jeremeamia/superclosure",
"version": "2.4.0",
"source": {
......@@ -936,6 +990,68 @@
"time": "2015-12-10T18:31:14+00:00"
},
{
"name": "mongodb/mongodb",
"version": "1.6.1",
"dist": {
"type": "zip",
"url": "https://mirrors.tencent.com/repository/composer/mongodb/mongodb/1.6.1/mongodb-mongodb-1.6.1.zip",
"reference": "4bb040c620ab95c487d05d5ff50cbc92fa68e920",
"shasum": ""
},
"require": {
"ext-hash": "*",
"ext-json": "*",
"ext-mongodb": "^1.7",
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.4 || ^8.3",
"sebastian/comparator": "^1.0 || ^2.0 || ^3.0",
"squizlabs/php_codesniffer": "^3.4",
"symfony/phpunit-bridge": "^4.4@dev"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
},
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"MongoDB\\": "src/"
}
},
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Andreas Braun",
"email": "andreas.braun@mongodb.com"
},
{
"name": "Jeremy Mikola",
"email": "jmikola@gmail.com"
},
{
"name": "Katherine Walker",
"email": "katherine.walker@mongodb.com"
}
],
"description": "MongoDB driver library",
"homepage": "https://jira.mongodb.org/browse/PHPLIB",
"keywords": [
"database",
"driver",
"mongodb",
"persistence"
],
"time": "2020-07-03T11:35:00+00:00"
},
{
"name": "monolog/monolog",
"version": "1.25.3",
"source": {
......
......@@ -147,6 +147,7 @@ return [
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
Jenssegers\Mongodb\MongodbServiceProvider::class,
/*
* Application Service Providers...
......
......@@ -357,7 +357,7 @@ return [
'strict' => false,
],
'mongo' => [
'mongodb' => [
'driver' => 'mongodb',
'host' => env('MONGO_HOST'),
'port' => 27017,
......
......@@ -14,6 +14,7 @@ return array(
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'1d1b89d124cc9cb8219922c9d5569199' => $vendorDir . '/hamcrest/hamcrest-php/hamcrest/Hamcrest.php',
'3a37ebac017bc098e9a86b35401e7a68' => $vendorDir . '/mongodb/mongodb/src/functions.php',
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
'e7223560d890eab89cda23685e711e2c' => $vendorDir . '/psy/psysh/src/Psy/functions.php',
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
......
......@@ -11,6 +11,8 @@ return array(
'PHPExcel' => array($vendorDir . '/phpoffice/phpexcel/Classes'),
'Mockery' => array($vendorDir . '/mockery/mockery/library'),
'Maatwebsite\\Excel\\' => array($vendorDir . '/maatwebsite/excel/src'),
'Jenssegers\\Mongodb' => array($vendorDir . '/jenssegers/mongodb/src'),
'Jenssegers\\Eloquent' => array($vendorDir . '/jenssegers/mongodb/src'),
'JakubOnderka\\PhpConsoleHighlighter' => array($vendorDir . '/jakub-onderka/php-console-highlighter/src'),
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src'),
'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib'),
......
......@@ -36,6 +36,7 @@ return array(
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'PhpAmqpLib\\' => array($vendorDir . '/php-amqplib/php-amqplib/PhpAmqpLib'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'MongoDB\\' => array($vendorDir . '/mongodb/mongodb/src'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
'JakubOnderka\\PhpConsoleColor\\' => array($vendorDir . '/jakub-onderka/php-console-color/src'),
'Illuminate\\' => array($vendorDir . '/laravel/framework/src/Illuminate'),
......
......@@ -655,6 +655,63 @@
"install-path": "../jakub-onderka/php-console-highlighter"
},
{
"name": "jenssegers/mongodb",
"version": "v3.0.0",
"version_normalized": "3.0.0.0",
"dist": {
"type": "zip",
"url": "https://mirrors.tencent.com/repository/composer/jenssegers/mongodb/v3.0.0/jenssegers-mongodb-v3.0.0.zip",
"reference": "81ae6b9abbbae2a8d99c987ee462f7c7591f004f",
"shasum": ""
},
"require": {
"illuminate/container": "^5.1",
"illuminate/database": "^5.1",
"illuminate/events": "^5.1",
"illuminate/support": "^5.1",
"mongodb/mongodb": "^1.0.0"
},
"require-dev": {
"mockery/mockery": "^0.9",
"orchestra/testbench": "^3.1",
"phpunit/phpunit": "^4.0|^5.0",
"satooshi/php-coveralls": "^0.6"
},
"suggest": {
"jenssegers/mongodb-sentry": "Add Sentry support to Laravel-MongoDB",
"jenssegers/mongodb-session": "Add MongoDB session support to Laravel-MongoDB"
},
"time": "2016-02-18T22:30:47+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"Jenssegers\\Mongodb": "src/",
"Jenssegers\\Eloquent": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Jens Segers",
"homepage": "https://jenssegers.com"
}
],
"description": "A MongoDB based Eloquent model and Query builder for Laravel 4",
"homepage": "https://github.com/jenssegers/laravel-mongodb",
"keywords": [
"database",
"eloquent",
"laravel",
"model",
"mongo",
"mongodb"
],
"install-path": "../jenssegers/mongodb"
},
{
"name": "jeremeamia/superclosure",
"version": "2.4.0",
"version_normalized": "2.4.0.0",
......@@ -1160,6 +1217,71 @@
"install-path": "../mockery/mockery"
},
{
"name": "mongodb/mongodb",
"version": "1.6.1",
"version_normalized": "1.6.1.0",
"dist": {
"type": "zip",
"url": "https://mirrors.tencent.com/repository/composer/mongodb/mongodb/1.6.1/mongodb-mongodb-1.6.1.zip",
"reference": "4bb040c620ab95c487d05d5ff50cbc92fa68e920",
"shasum": ""
},
"require": {
"ext-hash": "*",
"ext-json": "*",
"ext-mongodb": "^1.7",
"php": "^5.6 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.4 || ^8.3",
"sebastian/comparator": "^1.0 || ^2.0 || ^3.0",
"squizlabs/php_codesniffer": "^3.4",
"symfony/phpunit-bridge": "^4.4@dev"
},
"time": "2020-07-03T11:35:00+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"MongoDB\\": "src/"
}
},
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Andreas Braun",
"email": "andreas.braun@mongodb.com"
},
{
"name": "Jeremy Mikola",
"email": "jmikola@gmail.com"
},
{
"name": "Katherine Walker",
"email": "katherine.walker@mongodb.com"
}
],
"description": "MongoDB driver library",
"homepage": "https://jira.mongodb.org/browse/PHPLIB",
"keywords": [
"database",
"driver",
"mongodb",
"persistence"
],
"install-path": "../mongodb/mongodb"
},
{
"name": "monolog/monolog",
"version": "1.25.3",
"version_normalized": "1.25.3.0",
......
......@@ -5,7 +5,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '28a77aa4f4c9c4ee2d223a5fcd2492be745919f7',
'reference' => '263640a855b4a9af67344a2d8fd747fbb8b0a09e',
'name' => 'laravel/laravel',
'dev' => true,
),
......@@ -289,6 +289,15 @@
'reference' => '7daa75df45242c8d5b75a22c00a201e7954e4fb5',
'dev_requirement' => false,
),
'jenssegers/mongodb' => array(
'pretty_version' => 'v3.0.0',
'version' => '3.0.0.0',
'type' => 'library',
'install_path' => __DIR__ . '/../jenssegers/mongodb',
'aliases' => array(),
'reference' => '81ae6b9abbbae2a8d99c987ee462f7c7591f004f',
'dev_requirement' => false,
),
'jeremeamia/superclosure' => array(
'pretty_version' => '2.4.0',
'version' => '2.4.0.0',
......@@ -328,7 +337,7 @@
'type' => 'project',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'reference' => '28a77aa4f4c9c4ee2d223a5fcd2492be745919f7',
'reference' => '263640a855b4a9af67344a2d8fd747fbb8b0a09e',
'dev_requirement' => false,
),
'league/flysystem' => array(
......@@ -358,6 +367,15 @@
'reference' => 'be9bf28d8e57d67883cba9fcadfcff8caab667f8',
'dev_requirement' => true,
),
'mongodb/mongodb' => array(
'pretty_version' => '1.6.1',
'version' => '1.6.1.0',
'type' => 'library',
'install_path' => __DIR__ . '/../mongodb/mongodb',
'aliases' => array(),
'reference' => '4bb040c620ab95c487d05d5ff50cbc92fa68e920',
'dev_requirement' => false,
),
'monolog/monolog' => array(
'pretty_version' => '1.25.3',
'version' => '1.25.3.0',
......
{
"name": "jenssegers/mongodb",
"description": "A MongoDB based Eloquent model and Query builder for Laravel 4",
"keywords": ["laravel","eloquent","mongodb","mongo","database","model"],
"homepage": "https://github.com/jenssegers/laravel-mongodb",
"authors": [
{
"name": "Jens Segers",
"homepage": "https://jenssegers.com"
}
],
"license" : "MIT",
"require": {
"illuminate/support": "^5.1",
"illuminate/container": "^5.1",
"illuminate/database": "^5.1",
"illuminate/events": "^5.1",
"mongodb/mongodb": "^1.0.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0|^5.0",
"orchestra/testbench": "^3.1",
"mockery/mockery": "^0.9",
"satooshi/php-coveralls": "^0.6"
},
"autoload": {
"psr-0": {
"Jenssegers\\Mongodb": "src/",
"Jenssegers\\Eloquent": "src/"
}
},
"autoload-dev": {
"classmap": [
"tests/TestCase.php",
"tests/models",
"tests/seeds"
]
},
"suggest": {
"jenssegers/mongodb-session": "Add MongoDB session support to Laravel-MongoDB",
"jenssegers/mongodb-sentry": "Add Sentry support to Laravel-MongoDB"
}
}
<?php namespace Jenssegers\Mongodb\Auth;
use Illuminate\Auth\Passwords\DatabaseTokenRepository as BaseDatabaseTokenRepository;
use MongoDB\BSON\UTCDateTime;
class DatabaseTokenRepository extends BaseDatabaseTokenRepository
{
/**
* Build the record payload for the table.
*
* @param string $email
* @param string $token
* @return array
*/
protected function getPayload($email, $token)
{
return ['email' => $email, 'token' => $token, 'created_at' => new UTCDateTime(round(microtime(true) * 1000))];
}
/**
* Determine if the token has expired.
*
* @param array $token
* @return bool
*/
protected function tokenExpired($token)
{
// Convert UTCDateTime to a date string.
if ($token['created_at'] instanceof UTCDateTime) {
$date = $token['created_at']->toDateTime();
$token['created_at'] = $date->format('Y-m-d H:i:s');
} elseif (is_array($token['created_at']) and isset($token['created_at']['date'])) {
$token['created_at'] = $token['created_at']['date'];
}
return parent::tokenExpired($token);
}
}
<?php namespace Jenssegers\Mongodb\Auth;
use Illuminate\Auth\Passwords\PasswordBrokerManager as BasePasswordBrokerManager;
class PasswordBrokerManager extends BasePasswordBrokerManager
{
/**
* Create a token repository instance based on the given configuration.
*
* @param array $config
* @return \Illuminate\Auth\Passwords\TokenRepositoryInterface
*/
protected function createTokenRepository(array $config)
{
return new DatabaseTokenRepository(
$this->app['db']->connection(),
$config['table'],
$this->app['config']['app.key'],
$config['expire']
);
}
}
<?php namespace Jenssegers\Mongodb\Auth;
use Illuminate\Auth\Passwords\PasswordResetServiceProvider as BasePasswordResetServiceProvider;
class PasswordResetServiceProvider extends BasePasswordResetServiceProvider
{
/**
* Register the token repository implementation.
*
* @return void
*/
protected function registerTokenRepository()
{
$this->app->singleton('auth.password.tokens', function ($app) {
$connection = $app['db']->connection();
// The database token repository is an implementation of the token repository
// interface, and is responsible for the actual storing of auth tokens and
// their e-mail addresses. We will inject this table and hash key to it.
$table = $app['config']['auth.password.table'];
$key = $app['config']['app.key'];
$expire = $app['config']->get('auth.password.expire', 60);
return new DatabaseTokenRepository($connection, $table, $key, $expire);
});
}
/**
* Register the password broker instance.
*
* @return void
*/
protected function registerPasswordBroker()
{
$this->app->singleton('auth.password', function ($app) {
return new PasswordBrokerManager($app);
});
$this->app->bind('auth.password.broker', function ($app) {
return $app->make('auth.password')->broker();
});
}
}
<?php namespace Jenssegers\Mongodb;
use Exception;
use MongoDB\Collection as MongoCollection;
class Collection
{
/**
* The connection instance.
*
* @var Connection
*/
protected $connection;
/**
* The MongoCollection instance..
*
* @var MongoCollection
*/
protected $collection;
/**
* Constructor.
*/
public function __construct(Connection $connection, MongoCollection $collection)
{
$this->connection = $connection;
$this->collection = $collection;
}
/**
* Handle dynamic method calls.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
$start = microtime(true);
$result = call_user_func_array([$this->collection, $method], $parameters);
if ($this->connection->logging()) {
// Once we have run the query we will calculate the time that it took to run and
// then log the query, bindings, and execution time so we will report them on
// the event that the developer needs them. We'll log time in milliseconds.
$time = $this->connection->getElapsedTime($start);
$query = [];
// Convert the query paramters to a json string.
foreach ($parameters as $parameter) {
try {
$query[] = json_encode($parameter);
} catch (Exception $e) {
$query[] = '{...}';
}
}
$queryString = $this->collection->getCollectionName() . '.' . $method . '(' . implode(',', $query) . ')';
$this->connection->logQuery($queryString, [], $time);
}
return $result;
}
}
<?php namespace Jenssegers\Mongodb;
use MongoDB\Client;
class Connection extends \Illuminate\Database\Connection
{
/**
* The MongoDB database handler.
*
* @var \MongoDB\Database
*/
protected $db;
/**
* The MongoDB connection handler.
*
* @var \MongoDB\Client
*/
protected $connection;
/**
* Create a new database connection instance.
*
* @param array $config
*/
public function __construct(array $config)
{
$this->config = $config;
// Build the connection string
$dsn = $this->getDsn($config);
// You can pass options directly to the MongoDB constructor
$options = array_get($config, 'options', []);
// Create the connection
$this->connection = $this->createConnection($dsn, $config, $options);
// Select database
$this->db = $this->connection->selectDatabase($config['database']);
$this->useDefaultPostProcessor();
}
/**
* Get the default post processor instance.
*
* @return Query\Processor
*/
protected function getDefaultPostProcessor()
{
return new Query\Processor;
}
/**
* Begin a fluent query against a database collection.
*
* @param string $collection
* @return Query\Builder
*/
public function collection($collection)
{
$processor = $this->getPostProcessor();
$query = new Query\Builder($this, $processor);
return $query->from($collection);
}
/**
* Begin a fluent query against a database collection.
*
* @param string $table
* @return Query\Builder
*/
public function table($table)
{
return $this->collection($table);
}
/**
* Get a MongoDB collection.
*
* @param string $name
* @return Collection
*/
public function getCollection($name)
{
return new Collection($this, $this->db->selectCollection($name));
}
/**
* Get a schema builder instance for the connection.
*
* @return Schema\Builder
*/
public function getSchemaBuilder()
{
return new Schema\Builder($this);
}
/**
* Get the MongoDB database object.
*
* @return \MongoDB\Database
*/
public function getMongoDB()
{
return $this->db;
}
/**
* return MongoDB object.
*
* @return \MongoDB\Client
*/
public function getMongoClient()
{
return $this->connection;
}
/**
* Create a new MongoDB connection.
*
* @param string $dsn
* @param array $config
* @param array $options
* @return MongoDB
*/
protected function createConnection($dsn, array $config, array $options)
{
// By default driver options is an empty array.
$driverOptions = [];
if (isset($config['driver_options']) && is_array($config['driver_options'])) {
$driverOptions = $config['driver_options'];
}
return new Client($dsn, $options, $driverOptions);
}
/**
* Disconnect from the underlying MongoDB connection.
*/
public function disconnect()
{
unset($this->connection);
}
/**
* Create a DSN string from a configuration.
*
* @param array $config
* @return string
*/
protected function getDsn(array $config)
{
// First we will create the basic DSN setup as well as the port if it is in
// in the configuration options. This will give us the basic DSN we will
// need to establish the MongoDB and return them back for use.
extract($config);
// Check if the user passed a complete dsn to the configuration.
if (! empty($dsn)) {
return $dsn;
}
// Treat host option as array of hosts
$hosts = is_array($host) ? $host : [$host];
foreach ($hosts as &$host) {
// Check if we need to add a port to the host
if (strpos($host, ':') === false and isset($port)) {
$host = "{$host}:{$port}";
}
}
// The database name needs to be in the connection string, otherwise it will
// authenticate to the admin database, which may result in permission errors.
$auth = '';
if (! empty($username)) {
$auth .= $username;
}
if (! empty($password)) {
$auth .= ':'.$password;
}
if ($auth) {
$auth .= '@';
}
return "mongodb://" . $auth . implode(',', $hosts) . "/{$database}";
}
/**
* Get the elapsed time since a given starting point.
*
* @param int $start
* @return float
*/
public function getElapsedTime($start)
{
return parent::getElapsedTime($start);
}
/**
* Get the PDO driver name.
*
* @return string
*/
public function getDriverName()
{
return 'mongodb';
}
/**
* Dynamically pass methods to the connection.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
return call_user_func_array([$this->db, $method], $parameters);
}
}
<?php namespace Jenssegers\Mongodb\Eloquent;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Relations\Relation;
use MongoDB\Driver\Cursor;
use MongoDB\Model\BSONDocument;
class Builder extends EloquentBuilder
{
/**
* The methods that should be returned from query builder.
*
* @var array
*/
protected $passthru = [
'toSql', 'lists', 'insert', 'insertGetId', 'pluck',
'count', 'min', 'max', 'avg', 'sum', 'exists', 'push', 'pull',
];
/**
* Update a record in the database.
*
* @param array $values
* @param array $options
* @return int
*/
public function update(array $values, array $options = [])
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$relation->performUpdate($this->model, $values);
return 1;
}
return $this->query->update($this->addUpdatedAtColumn($values), $options);
}
/**
* Insert a new record into the database.
*
* @param array $values
* @return bool
*/
public function insert(array $values)
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$relation->performInsert($this->model, $values);
return true;
}
return parent::insert($values);
}
/**
* Insert a new record and get the value of the primary key.
*
* @param array $values
* @param string $sequence
* @return int
*/
public function insertGetId(array $values, $sequence = null)
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$relation->performInsert($this->model, $values);
return $this->model->getKey();
}
return parent::insertGetId($values, $sequence);
}
/**
* Delete a record from the database.
*
* @return mixed
*/
public function delete()
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$relation->performDelete($this->model);
return $this->model->getKey();
}
return parent::delete();
}
/**
* Increment a column's value by a given amount.
*
* @param string $column
* @param int $amount
* @param array $extra
* @return int
*/
public function increment($column, $amount = 1, array $extra = [])
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$value = $this->model->{$column};
// When doing increment and decrements, Eloquent will automatically
// sync the original attributes. We need to change the attribute
// temporary in order to trigger an update query.
$this->model->{$column} = null;
$this->model->syncOriginalAttribute($column);
$result = $this->model->update([$column => $value]);
return $result;
}
return parent::increment($column, $amount, $extra);
}
/**
* Decrement a column's value by a given amount.
*
* @param string $column
* @param int $amount
* @param array $extra
* @return int
*/
public function decrement($column, $amount = 1, array $extra = [])
{
// Intercept operations on embedded models and delegate logic
// to the parent relation instance.
if ($relation = $this->model->getParentRelation()) {
$value = $this->model->{$column};
// When doing increment and decrements, Eloquent will automatically
// sync the original attributes. We need to change the attribute
// temporary in order to trigger an update query.
$this->model->{$column} = null;
$this->model->syncOriginalAttribute($column);
return $this->model->update([$column => $value]);
}
return parent::decrement($column, $amount, $extra);
}
/**
* Add the "has" condition where clause to the query.
*
* @param \Illuminate\Database\Eloquent\Builder $hasQuery
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
* @param string $operator
* @param int $count
* @param string $boolean
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function addHasWhere(EloquentBuilder $hasQuery, Relation $relation, $operator, $count, $boolean)
{
$query = $hasQuery->getQuery();
// Get the number of related objects for each possible parent.
$relationCount = array_count_values($query->lists($relation->getHasCompareKey()));
// Remove unwanted related objects based on the operator and count.
$relationCount = array_filter($relationCount, function ($counted) use ($count, $operator) {
// If we are comparing to 0, we always need all results.
if ($count == 0) {
return true;
}
switch ($operator) {
case '>=':
case '<':
return $counted >= $count;
case '>':
case '<=':
return $counted > $count;
case '=':
case '!=':
return $counted == $count;
}
});
// If the operator is <, <= or !=, we will use whereNotIn.
$not = in_array($operator, ['<', '<=', '!=']);
// If we are comparing to 0, we need an additional $not flip.
if ($count == 0) {
$not = !$not;
}
// All related ids.
$relatedIds = array_keys($relationCount);
// Add whereIn to the query.
return $this->whereIn($this->model->getKeyName(), $relatedIds, $boolean, $not);
}
/**
* Create a raw database expression.
*
* @param closure $expression
* @return mixed
*/
public function raw($expression = null)
{
// Get raw results from the query builder.
$results = $this->query->raw($expression);
// Convert MongoCursor results to a collection of models.
if ($results instanceof Cursor) {
$results = iterator_to_array($results, false);
return $this->model->hydrate($results);
}
// Convert Mongo BSONDocument to a single object.
elseif ($results instanceof BSONDocument) {
$results = $results->getArrayCopy();
return $this->model->newFromBuilder((array) $results);
}
// The result is a single object.
elseif (is_array($results) and array_key_exists('_id', $results)) {
return $this->model->newFromBuilder((array) $results);
}
return $results;
}
}
<?php namespace Jenssegers\Mongodb\Eloquent;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Support\Str;
use Jenssegers\Mongodb\Relations\BelongsTo;
use Jenssegers\Mongodb\Relations\BelongsToMany;
use Jenssegers\Mongodb\Relations\HasMany;
use Jenssegers\Mongodb\Relations\HasOne;
use Jenssegers\Mongodb\Relations\MorphTo;
trait HybridRelations
{
/**
* Define a one-to-one relationship.
*
* @param string $related
* @param string $foreignKey
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function hasOne($related, $foreignKey = null, $localKey = null)
{
// Check if it is a relation with an original model.
if (! is_subclass_of($related, 'Jenssegers\Mongodb\Eloquent\Model')) {
return parent::hasOne($related, $foreignKey, $localKey);
}
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
$localKey = $localKey ?: $this->getKeyName();
return new HasOne($instance->newQuery(), $this, $foreignKey, $localKey);
}
/**
* Define a polymorphic one-to-one relationship.
*
* @param string $related
* @param string $name
* @param string $type
* @param string $id
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\MorphOne
*/
public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
{
// Check if it is a relation with an original model.
if (! is_subclass_of($related, 'Jenssegers\Mongodb\Eloquent\Model')) {
return parent::morphOne($related, $name, $type, $id, $localKey);
}
$instance = new $related;
list($type, $id) = $this->getMorphs($name, $type, $id);
$table = $instance->getTable();
$localKey = $localKey ?: $this->getKeyName();
return new MorphOne($instance->newQuery(), $this, $type, $id, $localKey);
}
/**
* Define a one-to-many relationship.
*
* @param string $related
* @param string $foreignKey
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function hasMany($related, $foreignKey = null, $localKey = null)
{
// Check if it is a relation with an original model.
if (! is_subclass_of($related, 'Jenssegers\Mongodb\Eloquent\Model')) {
return parent::hasMany($related, $foreignKey, $localKey);
}
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
$localKey = $localKey ?: $this->getKeyName();
return new HasMany($instance->newQuery(), $this, $foreignKey, $localKey);
}
/**
* Define a polymorphic one-to-many relationship.
*
* @param string $related
* @param string $name
* @param string $type
* @param string $id
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
{
// Check if it is a relation with an original model.
if (! is_subclass_of($related, 'Jenssegers\Mongodb\Eloquent\Model')) {
return parent::morphMany($related, $name, $type, $id, $localKey);
}
$instance = new $related;
// Here we will gather up the morph type and ID for the relationship so that we
// can properly query the intermediate table of a relation. Finally, we will
// get the table and create the relationship instances for the developers.
list($type, $id) = $this->getMorphs($name, $type, $id);
$table = $instance->getTable();
$localKey = $localKey ?: $this->getKeyName();
return new MorphMany($instance->newQuery(), $this, $type, $id, $localKey);
}
/**
* Define an inverse one-to-one or many relationship.
*
* @param string $related
* @param string $foreignKey
* @param string $otherKey
* @param string $relation
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function belongsTo($related, $foreignKey = null, $otherKey = null, $relation = null)
{
// If no relation name was given, we will use this debug backtrace to extract
// the calling method's name and use that as the relationship name as most
// of the time this will be what we desire to use for the relationships.
if (is_null($relation)) {
list($current, $caller) = debug_backtrace(false, 2);
$relation = $caller['function'];
}
// Check if it is a relation with an original model.
if (! is_subclass_of($related, 'Jenssegers\Mongodb\Eloquent\Model')) {
return parent::belongsTo($related, $foreignKey, $otherKey, $relation);
}
// If no foreign key was supplied, we can use a backtrace to guess the proper
// foreign key name by using the name of the relationship function, which
// when combined with an "_id" should conventionally match the columns.
if (is_null($foreignKey)) {
$foreignKey = Str::snake($relation) . '_id';
}
$instance = new $related;
// Once we have the foreign key names, we'll just create a new Eloquent query
// for the related models and returns the relationship instance which will
// actually be responsible for retrieving and hydrating every relations.
$query = $instance->newQuery();
$otherKey = $otherKey ?: $instance->getKeyName();
return new BelongsTo($query, $this, $foreignKey, $otherKey, $relation);
}
/**
* Define a polymorphic, inverse one-to-one or many relationship.
*
* @param string $name
* @param string $type
* @param string $id
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function morphTo($name = null, $type = null, $id = null)
{
// If no name is provided, we will use the backtrace to get the function name
// since that is most likely the name of the polymorphic interface. We can
// use that to get both the class and foreign key that will be utilized.
if (is_null($name)) {
list($current, $caller) = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$name = Str::snake($caller['function']);
}
list($type, $id) = $this->getMorphs($name, $type, $id);
// If the type value is null it is probably safe to assume we're eager loading
// the relationship. When that is the case we will pass in a dummy query as
// there are multiple types in the morph and we can't use single queries.
if (is_null($class = $this->$type)) {
return new MorphTo(
$this->newQuery(), $this, $id, null, $type, $name
);
}
// If we are not eager loading the relationship we will essentially treat this
// as a belongs-to style relationship since morph-to extends that class and
// we will pass in the appropriate values so that it behaves as expected.
else {
$class = $this->getActualClassNameForMorph($class);
$instance = new $class;
return new MorphTo(
$instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name
);
}
}
/**
* Define a many-to-many relationship.
*
* @param string $related
* @param string $collection
* @param string $foreignKey
* @param string $otherKey
* @param string $relation
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function belongsToMany($related, $collection = null, $foreignKey = null, $otherKey = null, $relation = null)
{
// If no relationship name was passed, we will pull backtraces to get the
// name of the calling function. We will use that function name as the
// title of this relation since that is a great convention to apply.
if (is_null($relation)) {
$relation = $this->getBelongsToManyCaller();
}
// Check if it is a relation with an original model.
if (! is_subclass_of($related, 'Jenssegers\Mongodb\Eloquent\Model')) {
return parent::belongsToMany($related, $collection, $foreignKey, $otherKey, $relation);
}
// First, we'll need to determine the foreign key and "other key" for the
// relationship. Once we have determined the keys we'll make the query
// instances as well as the relationship instances we need for this.
$foreignKey = $foreignKey ?: $this->getForeignKey() . 's';
$instance = new $related;
$otherKey = $otherKey ?: $instance->getForeignKey() . 's';
// If no table name was provided, we can guess it by concatenating the two
// models using underscores in alphabetical order. The two model names
// are transformed to snake case from their default CamelCase also.
if (is_null($collection)) {
$collection = $instance->getTable();
}
// Now we're ready to create a new query builder for the related model and
// the relationship instances for the relation. The relations will set
// appropriate query constraint and entirely manages the hydrations.
$query = $instance->newQuery();
return new BelongsToMany($query, $this, $collection, $foreignKey, $otherKey, $relation);
}
}
<?php namespace Jenssegers\Mongodb\Eloquent;
trait SoftDeletes
{
use \Illuminate\Database\Eloquent\SoftDeletes;
/**
* Get the fully qualified "deleted at" column.
*
* @return string
*/
public function getQualifiedDeletedAtColumn()
{
return $this->getDeletedAtColumn();
}
}
<?php namespace Jenssegers\Mongodb;
use Illuminate\Support\ServiceProvider;
use Jenssegers\Mongodb\Eloquent\Model;
use Jenssegers\Mongodb\Queue\MongoConnector;
class MongodbServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application events.
*/
public function boot()
{
Model::setConnectionResolver($this->app['db']);
Model::setEventDispatcher($this->app['events']);
}
/**
* Register the service provider.
*/
public function register()
{
// Add database driver.
$this->app->resolving('db', function ($db) {
$db->extend('mongodb', function ($config) {
return new Connection($config);
});
});
// Add connector for queue support.
$this->app->resolving('queue', function ($queue) {
$queue->addConnector('mongodb', function () {
return new MongoConnector($this->app['db']);
});
});
}
}
<?php namespace Jenssegers\Mongodb\Query;
use Illuminate\Database\Query\Grammars\Grammar as BaseGrammar;
class Grammar extends BaseGrammar
{
}
<?php namespace Jenssegers\Mongodb\Query;
use Illuminate\Database\Query\Processors\Processor as BaseProcessor;
class Processor extends BaseProcessor
{
}
<?php namespace Jenssegers\Mongodb\Queue;
use Illuminate\Database\ConnectionResolverInterface;
use Illuminate\Queue\Connectors\ConnectorInterface;
use Illuminate\Support\Arr;
class MongoConnector implements ConnectorInterface
{
/**
* Database connections.
*
* @var \Illuminate\Database\ConnectionResolverInterface
*/
protected $connections;
/**
* Create a new connector instance.
*
* @param \Illuminate\Database\ConnectionResolverInterface $connections
* @return void
*/
public function __construct(ConnectionResolverInterface $connections)
{
$this->connections = $connections;
}
/**
* Establish a queue connection.
*
* @param array $config
* @return \Illuminate\Contracts\Queue\Queue
*/
public function connect(array $config)
{
return new MongoQueue(
$this->connections->connection(Arr::get($config, 'connection')),
$config['table'],
$config['queue'],
Arr::get($config, 'expire', 60)
);
}
}
<?php namespace Jenssegers\Mongodb\Queue;
use Carbon\Carbon;
use Illuminate\Queue\DatabaseQueue;
class MongoQueue extends DatabaseQueue
{
/**
* Get the next available job for the queue.
*
* @param string|null $queue
* @return \StdClass|null
*/
protected function getNextAvailableJob($queue)
{
$job = $this->database->table($this->table)
->lockForUpdate()
->where('queue', $this->getQueue($queue))
->where('reserved', 0)
->where('available_at', '<=', $this->getTime())
->orderBy('id', 'asc')
->first();
if ($job) {
$job = (object) $job;
$job->id = $job->_id;
}
return $job ?: null;
}
/**
* Release the jobs that have been reserved for too long.
*
* @param string $queue
* @return void
*/
protected function releaseJobsThatHaveBeenReservedTooLong($queue)
{
$expired = Carbon::now()->subSeconds($this->expire)->getTimestamp();
$reserved = $this->database->collection($this->table)
->where('queue', $this->getQueue($queue))
->where('reserved', 1)
->where('reserved_at', '<=', $expired)->get();
foreach ($reserved as $job) {
$attempts = $job['attempts'] + 1;
$this->releaseJob($job['_id'], $attempts);
}
}
}
<?php namespace Jenssegers\Mongodb\Relations;
class BelongsTo extends \Illuminate\Database\Eloquent\Relations\BelongsTo
{
/**
* Set the base constraints on the relation query.
*/
public function addConstraints()
{
if (static::$constraints) {
// For belongs to relationships, which are essentially the inverse of has one
// or has many relationships, we need to actually query on the primary key
// of the related models matching on the foreign key that's on a parent.
$this->query->where($this->otherKey, '=', $this->parent->{$this->foreignKey});
}
}
/**
* Set the constraints for an eager load of the relation.
*
* @param array $models
*/
public function addEagerConstraints(array $models)
{
// We'll grab the primary key name of the related models since it could be set to
// a non-standard name and not "id". We will then construct the constraint for
// our eagerly loading query so it returns the proper models from execution.
$key = $this->otherKey;
$this->query->whereIn($key, $this->getEagerModelKeys($models));
}
}
<?php namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany as EloquentBelongsToMany;
class BelongsToMany extends EloquentBelongsToMany
{
/**
* Hydrate the pivot table relationship on the models.
*
* @param array $models
*/
protected function hydratePivotRelation(array $models)
{
// Do nothing.
}
/**
* Set the select clause for the relation query.
*
* @param array $columns
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
protected function getSelectColumns(array $columns = ['*'])
{
return $columns;
}
/**
* Set the base constraints on the relation query.
*/
public function addConstraints()
{
if (static::$constraints) {
$this->setWhere();
}
}
/**
* Set the where clause for the relation query.
*
* @return $this
*/
protected function setWhere()
{
$foreign = $this->getForeignKey();
$this->query->where($foreign, '=', $this->parent->getKey());
return $this;
}
/**
* Save a new model and attach it to the parent model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param array $joining
* @param bool $touch
* @return \Illuminate\Database\Eloquent\Model
*/
public function save(Model $model, array $joining = [], $touch = true)
{
$model->save(['touch' => false]);
$this->attach($model, $joining, $touch);
return $model;
}
/**
* Create a new instance of the related model.
*
* @param array $attributes
* @param array $joining
* @param bool $touch
* @return \Illuminate\Database\Eloquent\Model
*/
public function create(array $attributes, array $joining = [], $touch = true)
{
$instance = $this->related->newInstance($attributes);
// Once we save the related model, we need to attach it to the base model via
// through intermediate table so we'll use the existing "attach" method to
// accomplish this which will insert the record and any more attributes.
$instance->save(['touch' => false]);
$this->attach($instance, $joining, $touch);
return $instance;
}
/**
* Sync the intermediate tables with a list of IDs or collection of models.
*
* @param array $ids
* @param bool $detaching
* @return array
*/
public function sync($ids, $detaching = true)
{
$changes = [
'attached' => [], 'detached' => [], 'updated' => [],
];
if ($ids instanceof Collection) {
$ids = $ids->modelKeys();
}
// First we need to attach any of the associated models that are not currently
// in this joining table. We'll spin through the given IDs, checking to see
// if they exist in the array of current ones, and if not we will insert.
$current = $this->parent->{$this->otherKey} ?: [];
// See issue #256.
if ($current instanceof Collection) {
$current = $ids->modelKeys();
}
$records = $this->formatSyncList($ids);
$detach = array_diff($current, array_keys($records));
// We need to make sure we pass a clean array, so that it is not interpreted
// as an associative array.
$detach = array_values($detach);
// Next, we will take the differences of the currents and given IDs and detach
// all of the entities that exist in the "current" array but are not in the
// the array of the IDs given to the method which will complete the sync.
if ($detaching and count($detach) > 0) {
$this->detach($detach);
$changes['detached'] = (array) array_map(function ($v) {
return is_numeric($v) ? (int) $v : (string) $v;
}, $detach);
}
// Now we are finally ready to attach the new records. Note that we'll disable
// touching until after the entire operation is complete so we don't fire a
// ton of touch operations until we are totally done syncing the records.
$changes = array_merge(
$changes, $this->attachNew($records, $current, false)
);
if (count($changes['attached']) || count($changes['updated'])) {
$this->touchIfTouching();
}
return $changes;
}
/**
* Update an existing pivot record on the table.
*
* @param mixed $id
* @param array $attributes
* @param bool $touch
*/
public function updateExistingPivot($id, array $attributes, $touch = true)
{
// Do nothing, we have no pivot table.
}
/**
* Attach a model to the parent.
*
* @param mixed $id
* @param array $attributes
* @param bool $touch
*/
public function attach($id, array $attributes = [], $touch = true)
{
if ($id instanceof Model) {
$model = $id;
$id = $model->getKey();
// Attach the new parent id to the related model.
$model->push($this->foreignKey, $this->parent->getKey(), true);
} else {
$query = $this->newRelatedQuery();
$query->whereIn($this->related->getKeyName(), (array) $id);
// Attach the new parent id to the related model.
$query->push($this->foreignKey, $this->parent->getKey(), true);
}
// Attach the new ids to the parent model.
$this->parent->push($this->otherKey, (array) $id, true);
if ($touch) {
$this->touchIfTouching();
}
}
/**
* Detach models from the relationship.
*
* @param int|array $ids
* @param bool $touch
* @return int
*/
public function detach($ids = [], $touch = true)
{
if ($ids instanceof Model) {
$ids = (array) $ids->getKey();
}
$query = $this->newRelatedQuery();
// If associated IDs were passed to the method we will only delete those
// associations, otherwise all of the association ties will be broken.
// We'll return the numbers of affected rows when we do the deletes.
$ids = (array) $ids;
// Detach all ids from the parent model.
$this->parent->pull($this->otherKey, $ids);
// Prepare the query to select all related objects.
if (count($ids) > 0) {
$query->whereIn($this->related->getKeyName(), $ids);
}
// Remove the relation to the parent.
$query->pull($this->foreignKey, $this->parent->getKey());
if ($touch) {
$this->touchIfTouching();
}
return count($ids);
}
/**
* Build model dictionary keyed by the relation's foreign key.
*
* @param \Illuminate\Database\Eloquent\Collection $results
* @return array
*/
protected function buildDictionary(Collection $results)
{
$foreign = $this->foreignKey;
// First we will build a dictionary of child models keyed by the foreign key
// of the relation so that we will easily and quickly match them to their
// parents without having a possibly slow inner loops for every models.
$dictionary = [];
foreach ($results as $result) {
foreach ($result->$foreign as $item) {
$dictionary[$item][] = $result;
}
}
return $dictionary;
}
/**
* Create a new query builder for the related model.
*
* @return \Illuminate\Database\Query\Builder
*/
protected function newPivotQuery()
{
return $this->newRelatedQuery();
}
/**
* Create a new query builder for the related model.
*
* @return \Illuminate\Database\Query\Builder
*/
public function newRelatedQuery()
{
return $this->related->newQuery();
}
/**
* Get the fully qualified foreign key for the relation.
*
* @return string
*/
public function getForeignKey()
{
return $this->foreignKey;
}
}
<?php namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use MongoDB\BSON\ObjectID;
class EmbedsMany extends EmbedsOneOrMany
{
/**
* Initialize the relation on a set of models.
*
* @param array $models
* @param string $relation
*/
public function initRelation(array $models, $relation)
{
foreach ($models as $model) {
$model->setRelation($relation, $this->related->newCollection());
}
return $models;
}
/**
* Get the results of the relationship.
*
* @return \Illuminate\Database\Eloquent\Collection
*/
public function getResults()
{
return $this->toCollection($this->getEmbedded());
}
/**
* Save a new model and attach it to the parent model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
public function performInsert(Model $model)
{
// Generate a new key if needed.
if ($model->getKeyName() == '_id' and ! $model->getKey()) {
$model->setAttribute('_id', new ObjectID);
}
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save();
}
// Push the new model to the database.
$result = $this->getBaseQuery()->push($this->localKey, $model->getAttributes(), true);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Save an existing model and attach it to the parent model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return Model|bool
*/
public function performUpdate(Model $model)
{
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save();
}
// Get the correct foreign key value.
$foreignKey = $this->getForeignKeyValue($model);
// Use array dot notation for better update behavior.
$values = array_dot($model->getDirty(), $this->localKey . '.$.');
// Update document in database.
$result = $this->getBaseQuery()->where($this->localKey . '.' . $model->getKeyName(), $foreignKey)
->update($values);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Delete an existing model and detach it from the parent model.
*
* @param Model $model
* @return int
*/
public function performDelete(Model $model)
{
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->dissociate($model);
return $this->parent->save();
}
// Get the correct foreign key value.
$foreignKey = $this->getForeignKeyValue($model);
$result = $this->getBaseQuery()->pull($this->localKey, [$model->getKeyName() => $foreignKey]);
if ($result) {
$this->dissociate($model);
}
return $result;
}
/**
* Associate the model instance to the given parent, without saving it to the database.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
public function associate(Model $model)
{
if (! $this->contains($model)) {
return $this->associateNew($model);
} else {
return $this->associateExisting($model);
}
}
/**
* Dissociate the model instance from the given parent, without saving it to the database.
*
* @param mixed $ids
* @return int
*/
public function dissociate($ids = [])
{
$ids = $this->getIdsArrayFrom($ids);
$records = $this->getEmbedded();
$primaryKey = $this->related->getKeyName();
// Remove the document from the parent model.
foreach ($records as $i => $record) {
if (in_array($record[$primaryKey], $ids)) {
unset($records[$i]);
}
}
$this->setEmbedded($records);
// We return the total number of deletes for the operation. The developers
// can then check this number as a boolean type value or get this total count
// of records deleted for logging, etc.
return count($ids);
}
/**
* Destroy the embedded models for the given IDs.
*
* @param mixed $ids
* @return int
*/
public function destroy($ids = [])
{
$count = 0;
$ids = $this->getIdsArrayFrom($ids);
// Get all models matching the given ids.
$models = $this->getResults()->only($ids);
// Pull the documents from the database.
foreach ($models as $model) {
if ($model->delete()) {
$count++;
}
}
return $count;
}
/**
* Delete all embedded models.
*
* @return int
*/
public function delete()
{
// Overwrite the local key with an empty array.
$result = $this->query->update([$this->localKey => []]);
if ($result) {
$this->setEmbedded([]);
}
return $result;
}
/**
* Destroy alias.
*
* @param mixed $ids
* @return int
*/
public function detach($ids = [])
{
return $this->destroy($ids);
}
/**
* Save alias.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
public function attach(Model $model)
{
return $this->save($model);
}
/**
* Associate a new model instance to the given parent, without saving it to the database.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
protected function associateNew($model)
{
// Create a new key if needed.
if (! $model->getAttribute('_id')) {
$model->setAttribute('_id', new ObjectID);
}
$records = $this->getEmbedded();
// Add the new model to the embedded documents.
$records[] = $model->getAttributes();
return $this->setEmbedded($records);
}
/**
* Associate an existing model instance to the given parent, without saving it to the database.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
protected function associateExisting($model)
{
// Get existing embedded documents.
$records = $this->getEmbedded();
$primaryKey = $this->related->getKeyName();
$key = $model->getKey();
// Replace the document in the parent model.
foreach ($records as &$record) {
if ($record[$primaryKey] == $key) {
$record = $model->getAttributes();
break;
}
}
return $this->setEmbedded($records);
}
/**
* Get a paginator for the "select" statement.
*
* @param int $perPage
* @return \Illuminate\Pagination\Paginator
*/
public function paginate($perPage = null)
{
$page = Paginator::resolveCurrentPage();
$perPage = $perPage ?: $this->related->getPerPage();
$results = $this->getEmbedded();
$total = count($results);
$start = ($page - 1) * $perPage;
$sliced = array_slice($results, $start, $perPage);
return new LengthAwarePaginator($sliced, $total, $perPage, $page, [
'path' => Paginator::resolveCurrentPath(),
]);
}
/**
* Get the embedded records array.
*
* @return array
*/
protected function getEmbedded()
{
return parent::getEmbedded() ?: [];
}
/**
* Set the embedded records array.
*
* @param array $models
*/
protected function setEmbedded($models)
{
if (! is_array($models)) {
$models = [$models];
}
return parent::setEmbedded(array_values($models));
}
/**
* Handle dynamic method calls to the relationship.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
if (method_exists('Illuminate\Database\Eloquent\Collection', $method)) {
return call_user_func_array([$this->getResults(), $method], $parameters);
}
return parent::__call($method, $parameters);
}
}
<?php namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Model;
use MongoDB\BSON\ObjectID;
class EmbedsOne extends EmbedsOneOrMany
{
/**
* Initialize the relation on a set of models.
*
* @param array $models
* @param string $relation
*/
public function initRelation(array $models, $relation)
{
foreach ($models as $model) {
$model->setRelation($relation, null);
}
return $models;
}
/**
* Get the results of the relationship.
*
* @return \Illuminate\Database\Eloquent\Model
*/
public function getResults()
{
return $this->toModel($this->getEmbedded());
}
/**
* Save a new model and attach it to the parent model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
public function performInsert(Model $model)
{
// Generate a new key if needed.
if ($model->getKeyName() == '_id' and ! $model->getKey()) {
$model->setAttribute('_id', new ObjectID);
}
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save();
}
$result = $this->getBaseQuery()->update([$this->localKey => $model->getAttributes()]);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Save an existing model and attach it to the parent model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model|bool
*/
public function performUpdate(Model $model)
{
if ($this->isNested()) {
$this->associate($model);
return $this->parent->save();
}
// Use array dot notation for better update behavior.
$values = array_dot($model->getDirty(), $this->localKey . '.');
$result = $this->getBaseQuery()->update($values);
// Attach the model to its parent.
if ($result) {
$this->associate($model);
}
return $result ? $model : false;
}
/**
* Delete an existing model and detach it from the parent model.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return int
*/
public function performDelete(Model $model)
{
// For deeply nested documents, let the parent handle the changes.
if ($this->isNested()) {
$this->dissociate($model);
return $this->parent->save();
}
// Overwrite the local key with an empty array.
$result = $this->getBaseQuery()->update([$this->localKey => null]);
// Detach the model from its parent.
if ($result) {
$this->dissociate();
}
return $result;
}
/**
* Attach the model to its parent.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @return \Illuminate\Database\Eloquent\Model
*/
public function associate(Model $model)
{
return $this->setEmbedded($model->getAttributes());
}
/**
* Detach the model from its parent.
*
* @return \Illuminate\Database\Eloquent\Model
*/
public function dissociate()
{
return $this->setEmbedded(null);
}
/**
* Delete all embedded models.
*
* @return int
*/
public function delete()
{
$model = $this->getResults();
return $this->performDelete($model);
}
}
<?php namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasMany as EloquentHasMany;
class HasMany extends EloquentHasMany
{
/**
* Add the constraints for a relationship count query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Builder $parent
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getRelationCountQuery(Builder $query, Builder $parent)
{
$foreignKey = $this->getHasCompareKey();
return $query->select($this->getHasCompareKey())->where($this->getHasCompareKey(), 'exists', true);
}
/**
* Add the constraints for a relationship query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Builder $parent
* @param array|mixed $columns
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*'])
{
$query->select($columns);
$key = $this->wrap($this->getQualifiedParentKeyName());
return $query->where($this->getHasCompareKey(), 'exists', true);
}
/**
* Get the plain foreign key.
*
* @return string
*/
public function getPlainForeignKey()
{
return $this->getForeignKey();
}
}
<?php namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\HasOne as EloquentHasOne;
class HasOne extends EloquentHasOne
{
/**
* Add the constraints for a relationship count query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Builder $parent
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getRelationCountQuery(Builder $query, Builder $parent)
{
$foreignKey = $this->getHasCompareKey();
return $query->select($this->getHasCompareKey())->where($this->getHasCompareKey(), 'exists', true);
}
/**
* Add the constraints for a relationship query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Database\Eloquent\Builder $parent
* @param array|mixed $columns
* @return \Illuminate\Database\Eloquent\Builder
*/
public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*'])
{
$query->select($columns);
$key = $this->wrap($this->getQualifiedParentKeyName());
return $query->where($this->getHasCompareKey(), 'exists', true);
}
/**
* Get the plain foreign key.
*
* @return string
*/
public function getPlainForeignKey()
{
return $this->getForeignKey();
}
}
<?php namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Relations\MorphTo as EloquentMorphTo;
class MorphTo extends EloquentMorphTo
{
/**
* Set the base constraints on the relation query.
*/
public function addConstraints()
{
if (static::$constraints) {
// For belongs to relationships, which are essentially the inverse of has one
// or has many relationships, we need to actually query on the primary key
// of the related models matching on the foreign key that's on a parent.
$this->query->where($this->otherKey, '=', $this->parent->{$this->foreignKey});
}
}
/**
* Get all of the relation results for a type.
*
* @param string $type
* @return \Illuminate\Database\Eloquent\Collection
*/
protected function getResultsByType($type)
{
$instance = $this->createModelByType($type);
$key = $instance->getKeyName();
$query = $instance->newQuery();
$query = $this->useWithTrashed($query);
return $query->whereIn($key, $this->gatherKeysByType($type)->all())->get();
}
}
<?php namespace Jenssegers\Mongodb\Schema;
use Closure;
use Illuminate\Database\Connection;
class Blueprint extends \Illuminate\Database\Schema\Blueprint
{
/**
* The MongoConnection object for this blueprint.
*
* @var MongoConnection
*/
protected $connection;
/**
* The MongoCollection object for this blueprint.
*
* @var MongoCollection
*/
protected $collection;
/**
* Fluent columns.
*
* @var array
*/
protected $columns = [];
/**
* Create a new schema blueprint.
*
* @param string $table
* @param Closure $callback
*/
public function __construct(Connection $connection, $collection)
{
$this->connection = $connection;
$this->collection = $connection->getCollection($collection);
}
/**
* Specify an index for the collection.
*
* @param string|array $columns
* @param array $options
* @return Blueprint
*/
public function index($columns = null, $options = [])
{
$columns = $this->fluent($columns);
// Columns are passed as a default array.
if (is_array($columns) && is_int(key($columns))) {
// Transform the columns to the required array format.
$transform = [];
foreach ($columns as $column) {
$transform[$column] = 1;
}
$columns = $transform;
}
$this->collection->createIndex($columns, $options);
return $this;
}
/**
* Specify the primary key(s) for the table.
*
* @param string|array $columns
* @param array $options
* @return \Illuminate\Support\Fluent
*/
public function primary($columns = null, $options = [])
{
return $this->unique($columns, $options);
}
/**
* Indicate that the given index should be dropped.
*
* @param string|array $columns
* @return Blueprint
*/
public function dropIndex($columns = null)
{
$columns = $this->fluent($columns);
// Columns are passed as a default array.
if (is_array($columns) && is_int(key($columns))) {
// Transform the columns to the required array format.
$transform = [];
foreach ($columns as $column) {
$transform[$column] = $column . '_1';
}
$columns = $transform;
}
foreach ($columns as $column) {
$this->collection->dropIndex($column);
}
return $this;
}
/**
* Specify a unique index for the collection.
*
* @param string|array $columns
* @param array $options
* @return Blueprint
*/
public function unique($columns = null, $options = [])
{
$columns = $this->fluent($columns);
$options['unique'] = true;
$this->index($columns, $options);
return $this;
}
/**
* Specify a non blocking index for the collection.
*
* @param string|array $columns
* @return Blueprint
*/
public function background($columns = null)
{
$columns = $this->fluent($columns);
$this->index($columns, ['background' => true]);
return $this;
}
/**
* Specify a sparse index for the collection.
*
* @param string|array $columns
* @param array $options
* @return Blueprint
*/
public function sparse($columns = null, $options = [])
{
$columns = $this->fluent($columns);
$options['sparse'] = true;
$this->index($columns, $options);
return $this;
}
/**
* Specify the number of seconds after wich a document should be considered expired based,
* on the given single-field index containing a date.
*
* @param string|array $columns
* @param int $seconds
* @return Blueprint
*/
public function expire($columns, $seconds)
{
$columns = $this->fluent($columns);
$this->index($columns, ['expireAfterSeconds' => $seconds]);
return $this;
}
/**
* Indicate that the table needs to be created.
*
* @return bool
*/
public function create()
{
$collection = $this->collection->getCollectionName();
$db = $this->connection->getMongoDB();
// Ensure the collection is created.
$db->createCollection($collection);
}
/**
* Indicate that the collection should be dropped.
*
* @return bool
*/
public function drop()
{
$this->collection->drop();
}
/**
* Add a new column to the blueprint.
*
* @param string $type
* @param string $name
* @param array $parameters
* @return Blueprint
*/
protected function addColumn($type, $name, array $parameters = [])
{
$this->fluent($name);
return $this;
}
/**
* Allow fluent columns.
*
* @param string|array $columns
* @return string|array
*/
protected function fluent($columns = null)
{
if (is_null($columns)) {
return $this->columns;
} elseif (is_string($columns)) {
return $this->columns = [$columns];
} else {
return $this->columns = $columns;
}
}
/**
* Allows the use of unsupported schema methods.
*
* @return Blueprint
*/
public function __call($method, $args)
{
// Dummy.
return $this;
}
}
<?php namespace Jenssegers\Mongodb\Schema;
use Closure;
use Jenssegers\Mongodb\Connection;
class Builder extends \Illuminate\Database\Schema\Builder
{
/**
* Create a new database Schema manager.
*
* @param Connection $connection
*/
public function __construct(Connection $connection)
{
$this->connection = $connection;
}
/**
* Determine if the given table has a given column.
*
* @param string $table
* @param string $column
* @return bool
*/
public function hasColumn($table, $column)
{
return true;
}
/**
* Determine if the given table has given columns.
*
* @param string $table
* @param array $columns
* @return bool
*/
public function hasColumns($table, array $columns)
{
return true;
}
/**
* Determine if the given collection exists.
*
* @param string $collection
* @return bool
*/
public function hasCollection($collection)
{
$db = $this->connection->getMongoDB();
foreach ($db->listCollections() as $collectionFromMongo) {
if ($collectionFromMongo->getName() == $collection) {
return true;
}
}
return false;
}
/**
* Determine if the given collection exists.
*
* @param string $collection
* @return bool
*/
public function hasTable($collection)
{
return $this->hasCollection($collection);
}
/**
* Modify a collection on the schema.
*
* @param string $collection
* @param Closure $callback
* @return bool
*/
public function collection($collection, Closure $callback)
{
$blueprint = $this->createBlueprint($collection);
if ($callback) {
$callback($blueprint);
}
}
/**
* Modify a collection on the schema.
*
* @param string $collection
* @param Closure $callback
* @return bool
*/
public function table($collection, Closure $callback)
{
return $this->collection($collection, $callback);
}
/**
* Create a new collection on the schema.
*
* @param string $collection
* @param Closure $callback
* @return bool
*/
public function create($collection, Closure $callback = null)
{
$blueprint = $this->createBlueprint($collection);
$blueprint->create();
if ($callback) {
$callback($blueprint);
}
}
/**
* Drop a collection from the schema.
*
* @param string $collection
* @return bool
*/
public function drop($collection)
{
$blueprint = $this->createBlueprint($collection);
return $blueprint->drop();
}
/**
* Create a new Blueprint.
*
* @param string $collection
* @return Schema\Blueprint
*/
protected function createBlueprint($collection, Closure $callback = null)
{
return new Blueprint($this->connection, $collection);
}
}
---
name: Bug Report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
<!--
You are about to open an issue for the MongoDB PHP library. If you instead
intended to report an issue with the MongoDB PHP extension, please do so via its
repository[^1].
If you've identified a security vulnerability in a driver or any other MongoDB
project, please create a vulnerability report[^2].
[^1]: https://github.com/mongodb/mongo-php-driver
[^2]: https://docs.mongodb.org/manual/tutorial/create-a-vulnerability-report
-->
### Bug Report
<!--
Briefly describe the issue. Feel free to cross-reference your report with any
other related GitHub or JIRA issues for additional context. Before reporting an
issue, check that you are using the most recent version of the driver.
-->
### Environment
<!--
What operating system and PHP version are you using? Mention if PHP was
installed through a third-party bundle (e.g. MAMP, XAMPP) and report its version
if applicable.
What version of MongoDB are you using? Include details about the topology (e.g.
replica set, sharded cluster) and how you are connecting to the database (e.g.
TLS connections, authentication). If possible, share your connection string and
additional URI options (be sure to redact any auth credentials). Please specify
whether you are self-hosting the database or using a cloud provider, such as
MongoDB Atlas.
Include version information for the extension, libmongoc, and libbson. This may
be collected by grepping phpinfo() output:
php -i | grep -E 'mongodb|libmongoc|libbson'
In some cases, it may be helpful to provide all phpinfo() output (e.g. `php -i`)
and/or list all installed extensions (e.g. `php -m`).
Include version information for the library. This may be
collected by running the following from your project's root directory:
composer show mongodb/mongodb
-->
### Test Script
<!--
If possible, attach a complete PHP script that can be executed on its own to
reproduce the issue. Clarify whether this script can be run from the CLI or if
it can must be run through a web SAPI.
If the error only presents itself in a web SAPI, note whether the issue can be
reproduced with PHP's built-in web server[^3]. If not, please share your web
server version and any relevant configuration details in the Environment section
above.
[^3]: http://php.net/manual/en/features.commandline.webserver.php
-->
### Expected and Actual Behavior
<!--
How did the script fail to perform the expected task? Feel free to include debug
and/or `var_dump()` output if that helps explain the error.
If the observed behavior is an unexpected exception, please include its full
message and any relevant backtrace information. If you encountered a
segmentation fault, please include a GDB backtrace[^4].
[^4]: https://bugs.php.net/bugs-generating-backtrace.php
-->
### Debug Log
<!--
If the issue relates to internal driver behavior (e.g. connection issues),
please include a debug log[^5]. This may be generated by setting the
`mongodb.debug` INI option to "stderr" or a directory (useful for web SAPIs).
[^5]: https://www.php.net/manual/en/mongodb.configuration.php#ini.mongodb.debug
-->
# Composer
composer.phar
composer.lock
vendor/
# PHPUnit
phpunit.phar
phpunit.xml
.phpunit.result.cache
# phpcs
.phpcs-cache
phpcs.xml
mongocryptd.pid
<?php
// Since doctrine/coding-standard requires PHP 7, we can't add it as a dependency
// yet. This autoload file adds more information to the phpcs error message,
// telling the user how they can fix the error presented to them by phpcs.
if (! file_exists(__DIR__ . '/../vendor/doctrine/coding-standard')) {
echo <<<ERRORMESSAGE
==============================================================================
ERROR: Doctrine coding standard is not installed. To rectify this, please run:
composer require --dev doctrine/coding-standard=^6.0
==============================================================================
ERRORMESSAGE;
}
language: php
dist: xenial
addons:
apt:
packages:
- gdb
- libcurl3
- libgssapi-krb5-2
- libkrb5-dbg
- libldap-2.4-2
- libpcap0.8
- libsasl2-2
- snmp
- openssl
cache:
directories:
- ${HOME}/.cache/pip
- ${HOME}/.composer/cache/files
- ${HOME}/php-ext
env:
global:
- DRIVER_VERSION=1.7.0
- SERVER_DISTRO=enterprise-ubuntu1604
- SERVER_VERSION=4.2.0
- DEPLOYMENT=STANDALONE
- COMPOSER_OPTIONS=
jobs:
include:
- stage: Smoke Testing
php: "7.3"
env:
- CHECKS=phpunit
- stage: Smoke Testing
php: "7.1"
before_install: []
before_script:
- .travis/install-extension.sh
- composer require --no-update doctrine/coding-standard=^6.0
- composer install --no-interaction --no-progress --no-suggest ${COMPOSER_OPTIONS}
script: vendor/bin/phpcs
after_script: []
after_failure: []
env:
- CHECKS=phpcs
# Test remaining supported PHP versions
- stage: Test
php: "5.6"
- stage: Test
php: "7.0"
- stage: Test
php: "7.1"
- stage: Test
php: "7.2"
- stage: Test
php: "7.4"
# Test against lowest supported dependencies
- stage: Test
php: "5.6"
env:
- COMPOSER_OPTIONS=--prefer-lowest
# Test older standalone server versions (3.0-4.0)
- stage: Test
php: "7.0"
dist: trusty
env:
- SERVER_DISTRO=enterprise-ubuntu1404
- SERVER_VERSION=3.0.15
- DEPLOYMENT=STANDALONE_OLD
- stage: Test
php: "7.0"
env:
- SERVER_VERSION=3.2.22
- DEPLOYMENT=STANDALONE_OLD
- stage: Test
php: "7.0"
env:
- SERVER_VERSION=3.4.21
- DEPLOYMENT=STANDALONE_OLD
- stage: Test
php: "7.0"
env:
- SERVER_VERSION=3.6.13
- stage: Test
php: "7.3"
env:
- SERVER_VERSION=4.0.12
# Test other server configurations
- stage: Test
php: "7.3"
env:
- DEPLOYMENT=STANDALONE_AUTH
- stage: Test
php: "7.3"
env:
- DEPLOYMENT=STANDALONE_SSL
- stage: Test
php: "7.3"
env:
- SERVER_VERSION=3.6.13
- DEPLOYMENT=REPLICASET
- stage: Test
php: "7.3"
env:
- DEPLOYMENT=REPLICASET
- stage: Test
php: "7.3"
env:
- DEPLOYMENT=SHARDED_CLUSTER
- stage: Test
php: "7.3"
env:
- DEPLOYMENT=SHARDED_CLUSTER_RS
# Test next patch release for driver
- stage: Test
php: "7.3"
env:
- DRIVER_BRANCH="v1.7"
# Test next minor release for driver
- stage: Test
php: "7.3"
env:
- DRIVER_BRANCH="master"
before_install:
- pip install "mongo-orchestration>=0.6.7,<1.0" --user `whoami`
- export SERVER_FILENAME=mongodb-linux-x86_64-${SERVER_DISTRO}-${SERVER_VERSION}
- wget -qO- https://downloads.mongodb.com/linux/${SERVER_FILENAME}.tgz | tar xz
- export PATH=${PWD}/${SERVER_FILENAME}/bin:${PATH}
- mongod --version
- mongo-orchestration --version
- export MO_PATH=`python -c 'import mongo_orchestration; from os import path; print(path.dirname(mongo_orchestration.__file__));'`
before_script:
- mongo-orchestration start
- .travis/setup_mo.sh
- .travis/install-extension.sh
- php --ri mongodb
- composer update --no-interaction --no-progress --no-suggest --prefer-dist --prefer-stable ${COMPOSER_OPTIONS}
- ulimit -c
- ulimit -c unlimited -S
script:
- export MONGODB_URI=`cat /tmp/uri.txt`
- echo $MONGODB_URI
- vendor/bin/phpunit -v
before_cache:
- rm -f ${HOME}/.cache/pip/log/debug.log
after_failure:
- find . -name 'core*' -exec ${TRAVIS_BUILD_DIR}/.travis/debug-core.sh {} \;
after_script:
- mongo-orchestration stop
#!/bin/sh
if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
# https://www.ics.uci.edu/~pattis/common/handouts/macmingweclipse/allexperimental/mac-gdb-install.html
echo "Cannot debug core files on macOS: ${1}"
exit 1
fi
PHP_BINARY=`which php`
gdb -batch -ex "bt full" -ex "quit" "${PHP_BINARY}" "${1}"
#!/bin/sh
INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
# tpecl is a helper to compile and cache php extensions
tpecl () {
local ext_name=$1
local ext_so=$2
local ext_dir=$(php -r "echo ini_get('extension_dir');")
local ext_cache=~/php-ext/$(basename $ext_dir)/$ext_name
if [[ -e $ext_cache/$ext_so ]]; then
echo extension = $ext_cache/$ext_so >> $INI
else
mkdir -p $ext_cache
echo yes | pecl install -f $ext_name &&
cp $ext_dir/$ext_so $ext_cache
fi
}
if [ "x${DRIVER_BRANCH}" != "x" ]; then
echo "Compiling driver branch ${DRIVER_BRANCH}"
mkdir -p /tmp/compile
git clone https://github.com/mongodb/mongo-php-driver /tmp/compile/mongo-php-driver
cd /tmp/compile/mongo-php-driver
git checkout ${DRIVER_BRANCH}
git submodule update --init
phpize
./configure --enable-mongodb-developer-flags
make all -j20 > /dev/null
make install
echo "extension=mongodb.so" >> `php --ini | grep "Scan for additional .ini files in" | sed -e "s|.*:\s*||"`/mongodb.ini
elif [ "x${DRIVER_VERSION}" != "x" ]; then
echo "Installing driver version ${DRIVER_VERSION} from PECL"
tpecl mongodb-${DRIVER_VERSION} mongodb.so
fi
#!/bin/bash
# Copyright 2012-2014 MongoDB, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
function eval_params {
local params=$(sed -e 's|["]|\\\"|g' $1)
echo $(eval echo \"$params\")
}
function r {
echo $1| awk -F'/' '{print $(NF-1)}'| sed 's/standalone/servers/'
}
function a {
echo $(cd $(dirname $1); pwd)/$(basename $1)
}
function id {
local id_line=$(grep id $1 | head -n 1)
echo $(expr "$id_line" : '.*: *"\(.*\)" *,*')
}
function get {
echo "GET $1 $(curl --header 'Accept: application/json' --include --silent --request GET $1)"
}
function post {
echo "POST $1 $(curl --header 'Accept: application/json' --include --silent --request POST --data "$2" $1)"
}
function delete {
echo "DELETE $1 $(curl --header 'Accept: application/json' --include --silent --request DELETE $1)"
}
function code {
expr "$1" : '.*HTTP/1.[01] \([0-9]*\)'
}
function usage {
echo "usage: $0 configurations/cluster/file.json action"
echo "cluster: servers|replica_sets|sharded_clusters"
echo "action: start|status|stop"
exit 1
}
SSL_FILES=$(a ./ssl-files)
BASE_URL=${MONGO_ORCHESTRATION:-'http://localhost:8889'}
if [ $# -ne 2 ]; then usage; fi
if [ ! -f "$1" ]; then echo "configuration file '$1' not found"; exit 1; fi
ID=$(id $1)
if [ ! "$ID" ]; then echo "id field not found in configuration file '$1'"; exit 1; fi
R=$(r $1)
GET=$(get $BASE_URL/$R/$ID)
HTTP_CODE=$(code "$GET")
EXIT_CODE=0
case $2 in
start)
if [ "$HTTP_CODE" != "200" ]
then
WORKSPACE=${TRAVIS_BUILD_DIR}/orchestrations
rm -fr $WORKSPACE
mkdir $WORKSPACE
LOGPATH=$WORKSPACE
DBPATH=$WORKSPACE
POST_DATA=$(eval_params $1)
echo "DBPATH=$DBPATH"
echo "LOGPATH=$LOGPATH"
echo "POST_DATA='$POST_DATA'"
echo
POST=$(post $BASE_URL/$R "$POST_DATA")
echo "$POST"
HTTP_CODE=$(code "$POST")
if [ "$HTTP_CODE" != 200 ]; then EXIT_CODE=1; fi
else
echo "$GET"
fi
;;
stop)
if [ "$HTTP_CODE" == "200" ]
then
DELETE=$(delete $BASE_URL/$R/$ID)
echo "$DELETE"
HTTP_CODE=$(code "$DELETE")
if [ "$HTTP_CODE" != 204 ]; then EXIT_CODE=1; fi
else
echo "$GET"
fi
;;
status)
if [ "$HTTP_CODE" == "200" ]
then
echo "$GET"
else
echo "$GET"
EXIT_CODE=1
fi
;;
*)
usage
;;
esac
exit $EXIT_CODE
#!/bin/bash
echo Loading MO for $DEPLOYMENT
if [[ -z $TRAVIS_BUILD_DIR ]]; then
export TRAVIS_BUILD_DIR=`pwd`;
fi
case $DEPLOYMENT in
SHARDED_CLUSTER)
${TRAVIS_BUILD_DIR}/.travis/mo.sh ${TRAVIS_BUILD_DIR}/mongo-orchestration/sharded_clusters/cluster.json start > /tmp/mo-result.json
cat /tmp/mo-result.json | tail -n 1 | php -r 'echo json_decode(file_get_contents("php://stdin"))->mongodb_uri, "/?retryWrites=false";' > /tmp/uri.txt
;;
SHARDED_CLUSTER_RS)
${TRAVIS_BUILD_DIR}/.travis/mo.sh ${TRAVIS_BUILD_DIR}/mongo-orchestration/sharded_clusters/cluster_replset.json start > /tmp/mo-result.json
cat /tmp/mo-result.json | tail -n 1 | php -r 'echo json_decode(file_get_contents("php://stdin"))->mongodb_uri;' > /tmp/uri.txt
;;
STANDALONE_AUTH)
${TRAVIS_BUILD_DIR}/.travis/mo.sh ${TRAVIS_BUILD_DIR}/mongo-orchestration/standalone/standalone-auth.json start > /tmp/mo-result.json
cat /tmp/mo-result.json | tail -n 1 | php -r 'echo json_decode(file_get_contents("php://stdin"))->mongodb_auth_uri;' > /tmp/uri.txt
;;
STANDALONE_OLD)
${TRAVIS_BUILD_DIR}/.travis/mo.sh ${TRAVIS_BUILD_DIR}/mongo-orchestration/standalone/standalone-old.json start > /tmp/mo-result.json
cat /tmp/mo-result.json | tail -n 1 | php -r 'echo json_decode(file_get_contents("php://stdin"))->mongodb_uri;' > /tmp/uri.txt
;;
STANDALONE_SSL)
${TRAVIS_BUILD_DIR}/.travis/mo.sh ${TRAVIS_BUILD_DIR}/mongo-orchestration/standalone/standalone-ssl.json start > /tmp/mo-result.json
cat /tmp/mo-result.json | tail -n 1 | php -r 'echo json_decode(file_get_contents("php://stdin"))->mongodb_uri, "/?ssl=true&sslallowinvalidcertificates=true";' > /tmp/uri.txt
;;
REPLICASET)
${TRAVIS_BUILD_DIR}/.travis/mo.sh ${TRAVIS_BUILD_DIR}/mongo-orchestration/replica_sets/replicaset.json start > /tmp/mo-result.json
cat /tmp/mo-result.json | tail -n 1 | php -r 'echo json_decode(file_get_contents("php://stdin"))->mongodb_uri;' > /tmp/uri.txt
;;
REPLICASET_SINGLE)
${TRAVIS_BUILD_DIR}/.travis/mo.sh ${TRAVIS_BUILD_DIR}/mongo-orchestration/replica_sets/replicaset-one-node.json start > /tmp/mo-result.json
cat /tmp/mo-result.json | tail -n 1 | php -r 'echo json_decode(file_get_contents("php://stdin"))->mongodb_uri;' > /tmp/uri.txt
;;
REPLICASET_OLD)
${TRAVIS_BUILD_DIR}/.travis/mo.sh ${TRAVIS_BUILD_DIR}/mongo-orchestration/replica_sets/replicaset-old.json start > /tmp/mo-result.json
cat /tmp/mo-result.json | tail -n 1 | php -r 'echo json_decode(file_get_contents("php://stdin"))->mongodb_uri;' > /tmp/uri.txt
;;
*)
${TRAVIS_BUILD_DIR}/.travis/mo.sh ${TRAVIS_BUILD_DIR}/mongo-orchestration/standalone/standalone.json start > /tmp/mo-result.json
cat /tmp/mo-result.json | tail -n 1 | php -r 'echo json_decode(file_get_contents("php://stdin"))->mongodb_uri;' > /tmp/uri.txt
;;
esac
echo -n "MongoDB Test URI: "
cat /tmp/uri.txt
echo
echo "Raw MO Response:"
cat /tmp/mo-result.json
echo
# Contributing to the PHP Library for MongoDB
## Initializing the Repository
Developers who would like to contribute to the library will need to clone it and
initialize the project dependencies with [Composer](https://getcomposer.org/):
```
$ git clone https://github.com/mongodb/mongo-php-library.git
$ cd mongo-php-library
$ composer update
```
In addition to installing project dependencies, Composer will check that the
required extension version is installed. Directions for installing the extension
may be found [here](http://php.net/manual/en/mongodb.installation.php).
Installation directions for Composer may be found in its
[Getting Started](https://getcomposer.org/doc/00-intro.md) guide.
## Testing
The library's test suite uses [PHPUnit](https://phpunit.de/), which should be
installed as a development dependency by Composer.
The test suite may be executed with:
```
$ vendor/bin/phpunit
```
The `phpunit.xml.dist` file is used as the default configuration file for the
test suite. In addition to various PHPUnit options, it defines required
`MONGODB_URI` and `MONGODB_DATABASE` environment variables. You may customize
this configuration by creating your own `phpunit.xml` file based on the
`phpunit.xml.dist` file we provide.
## Checking coding standards
The library's code is checked using [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer),
which is installed as a development dependency by Composer. Due to the PHP
requirement, the base version of the coding standard is not installed and needs
to be added manually if you plan to contributing code:
```
$ composer require --dev doctrine/coding-standard=^6.0
```
Once the coding standard has been installed, you can check the code for style
errors:
```
$ vendor/bin/phpcs
```
To automatically fix all fixable errors, use the `phpcbf` binary:
```
$ vendor/bin/phpcbf
```
## Documentation
Documentation for the library lives in the `docs/` directory and is built with
tools in the related
[mongodb/docs-php-library](https://github.com/mongodb/docs-php-library)
repository. The tools repository is already configured to reference our sources.
That said, any changes to the documentation should be tested locally before
committing. Follow the following steps to build the docs locally with the tools
repository:
* Clone the
[mongodb/docs-php-library](https://github.com/mongodb/docs-php-library) tools
repository.
* Install [giza](https://pypi.python.org/pypi/giza/), as noted in the tools
README.
* Sync your working copy of the documentation to the `source/` directory with
`rsync -a --delete /path/to/mongo-php-library/docs/ source/`.
* Build the documentation with `giza make publish`. You can suppress
informational log messages with the `--level warning` option.
* Generated documentation may be found in the `build/master/html` directory.
## Releasing
The follow steps outline the release process for a maintenance branch (e.g.
releasing the `vX.Y` branch as X.Y.Z).
### Ensure PHP version compatibility
Ensure that the library test suite completes on supported versions of PHP.
### Transition JIRA issues and version
All issues associated with the release version should be in the "Closed" state
and have a resolution of "Fixed". Issues with other resolutions (e.g.
"Duplicate", "Works as Designed") should be removed from the release version so
that they do not appear in the release notes.
Check the corresponding ".x" fix version to see if it contains any issues that
are resolved as "Fixed" and should be included in this release version.
Update the version's release date and status from the
[Manage Versions](https://jira.mongodb.org/plugins/servlet/project-config/PHPLIB/versions)
page.
### Update version info
The PHP library uses [semantic versioning](http://semver.org/). Do not break
backwards compatibility in a non-major release or your users will kill you.
Before proceeding, ensure that the `master` branch is up-to-date with all code
changes in this maintenance branch. This is important because we will later
merge the ensuing release commits up to master with `--strategy=ours`, which
will ignore changes from the merged commits.
### Tag release
The maintenance branch's HEAD will be the target for our release tag:
```
$ git tag -a -m "Release X.Y.Z" X.Y.Z
```
### Push tags
```
$ git push --tags
```
### Merge the maintenance branch up to master
```
$ git checkout master
$ git merge vX.Y --strategy=ours
$ git push
```
The `--strategy=ours` option ensures that all changes from the merged commits
will be ignored.
### Publish release notes
The following template should be used for creating GitHub release notes via
[this form](https://github.com/mongodb/mongo-php-library/releases/new).
```
The PHP team is happy to announce that version X.Y.Z of the MongoDB PHP library is now available. This library is a high-level abstraction for the [`mongodb`](http://php.net/mongodb) extension.
**Release Highlights**
<one or more paragraphs describing important changes in this release>
A complete list of resolved issues in this release may be found at:
$JIRA_URL
**Documentation**
Documentation for this library may be found at:
https://docs.mongodb.com/php-library/
**Feedback**
If you encounter any bugs or issues with this library, please report them via this form:
https://jira.mongodb.org/secure/CreateIssue.jspa?pid=12483&issuetype=1
**Installation**
This library may be installed or upgraded with:
composer require mongodb/mongodb
Installation instructions for the `mongodb` extension may be found in the [PHP.net documentation](http://php.net/manual/en/mongodb.installation.php).
```
The URL for the list of resolved JIRA issues will need to be updated with each
release. You may obtain the list from
[this form](https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=12483).
If commits from community contributors were included in this release, append the
following section:
```
**Thanks**
Thanks for our community contributors for this release:
* [$CONTRIBUTOR_NAME](https://github.com/$GITHUB_USERNAME)
```
Release announcements should also be sent to the `mongodb-user@googlegroups.com`
and `mongodb-announce@googlegroups.com` mailing lists.
Consider announcing each release on Twitter. Significant releases should also be
announced via [@MongoDB](http://twitter.com/mongodb) as well.
.PHONY: composer test
COMPOSER_ARGS=update --no-interaction --prefer-source
composer:
@command -v composer >/dev/null 2>&1; \
if test $$? -eq 0; then \
composer $(COMPOSER_ARGS); \
elif test -r composer.phar; then \
php composer.phar $(COMPOSER_ARGS); \
else \
echo >&2 "Cannot find composer; aborting."; \
false; \
fi
test: composer
vendor/bin/phpunit
# MongoDB PHP Library
[![Build Status](https://api.travis-ci.org/mongodb/mongo-php-library.png?branch=master)](https://travis-ci.org/mongodb/mongo-php-library)
This library provides a high-level abstraction around the lower-level
[PHP driver](https://github.com/mongodb/mongo-php-driver) (`mongodb` extension).
While the extension provides a limited API for executing commands, queries, and
write operations, this library implements an API similar to that of the
[legacy PHP driver](https://php.net/manual/en/book.mongo.php). It contains
abstractions for client, database, and collection objects, and provides methods
for CRUD operations and common commands (e.g. index and collection management).
If you are developing an application with MongoDB, you should consider using
this library, or another high-level abstraction, instead of the extension alone.
Additional information about the architecture of this library and the `mongodb`
extension may be found in
[Architecture Overview](https://php.net/manual/en/mongodb.overview.php).
## Documentation
- https://docs.mongodb.com/php-library/
- https://docs.mongodb.com/ecosystem/drivers/php/
## Installation
The preferred method of installing this library is with
[Composer](https://getcomposer.org/) by running the following from your project
root:
$ composer require mongodb/mongodb
Additional installation instructions may be found in the
[library documentation](https://docs.mongodb.com/php-library/current/tutorial/install-php-library/).
Since this library is a high-level abstraction for the driver, it also requires
that the `mongodb` extension be installed:
$ pecl install mongodb
$ echo "extension=mongodb.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
Additional installation instructions for the extension may be found in its
[PHP.net documentation](https://php.net/manual/en/mongodb.installation.php).
## Reporting Issues
Issues pertaining to the library should be reported in the
[PHPLIB](https://jira.mongodb.org/secure/CreateIssue!default.jspa?project-field=PHPLIB)
project in MongoDB's JIRA. Extension-related issues should be reported in the
[PHPC](https://jira.mongodb.org/secure/CreateIssue!default.jspa?project-field=PHPC)
project.
For general questions and support requests, please use one of MongoDB's
[Technical Support](https://docs.mongodb.com/manual/support/) channels.
### Security Vulnerabilities
If you've identified a security vulnerability in a driver or any other MongoDB
project, please report it according to the instructions in
[Create a Vulnerability Report](https://docs.mongodb.org/manual/tutorial/create-a-vulnerability-report).
## Development
Development is tracked in the
[PHPLIB](https://jira.mongodb.org/projects/PHPLIB/summary) project in MongoDB's
JIRA. Documentation for contributing to this project may be found in
[CONTRIBUTING.md](CONTRIBUTING.md).
{
"name": "mongodb/mongodb",
"description": "MongoDB driver library",
"keywords": ["database", "driver", "mongodb", "persistence"],
"homepage": "https://jira.mongodb.org/browse/PHPLIB",
"license": "Apache-2.0",
"authors": [
{ "name": "Andreas Braun", "email": "andreas.braun@mongodb.com" },
{ "name": "Jeremy Mikola", "email": "jmikola@gmail.com" },
{ "name": "Katherine Walker", "email": "katherine.walker@mongodb.com" }
],
"require": {
"php": "^5.6 || ^7.0",
"ext-hash": "*",
"ext-json": "*",
"ext-mongodb": "^1.7"
},
"require-dev": {
"phpunit/phpunit": "^5.7.27 || ^6.4 || ^8.3",
"sebastian/comparator": "^1.0 || ^2.0 || ^3.0",
"squizlabs/php_codesniffer": "^3.4",
"symfony/phpunit-bridge": "^4.4@dev"
},
"autoload": {
"psr-4": { "MongoDB\\": "src/" },
"files": [ "src/functions.php" ]
},
"autoload-dev": {
"psr-4": { "MongoDB\\Tests\\": "tests/" }
},
"extra": {
"branch-alias": {
"dev-master": "1.6.x-dev"
}
}
}
arg_name: option
name: readConcern
type: :php:`MongoDB\\Driver\\ReadConcern <class.mongodb-driver-readconcern>`
description: |
:manual:`Read concern </reference/read-concern>` to use for the operation.
Defaults to the client's read concern.
This is not supported for server versions prior to 3.2 and will result in an
exception at execution time if used.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: readPreference
type: :php:`MongoDB\\Driver\\ReadPreference <class.mongodb-driver-readpreference>`
description: |
:manual:`Read preference </reference/read-preference>` to use for the
operation. Defaults to the client's read preference.
interface: phpmethod
operation: ~
optional: true
---
source:
file: apiargs-common-option.yaml
ref: typeMap
---
arg_name: option
name: writeConcern
type: :php:`MongoDB\\Driver\\WriteConcern <class.mongodb-driver-writeconcern>`
description: |
:manual:`Write concern </reference/write-concern>` to use for the operation.
Defaults to the client's write concern.
interface: phpmethod
operation: ~
optional: true
...
arg_name: option
name: typeMap
type: array
description: |
Default :php:`type map
<manual/en/mongodb.persistence.deserialization.php#mongodb.persistence.typemaps>`
to apply to cursors, which determines how BSON documents are converted to PHP
values. The |php-library| uses the following type map by default:
.. code-block:: php
[
'array' => 'MongoDB\Model\BSONArray',
'document' => 'MongoDB\Model\BSONDocument',
'root' => 'MongoDB\Model\BSONDocument',
]
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: allow_invalid_hostname
type: boolean
description: |
Disables hostname validation if ``true``. Defaults to ``false``.
Allowing invalid hostnames may expose the driver to a `man-in-the-middle
attack <https://en.wikipedia.org/wiki/Man-in-the-middle_attack>`_.
.. deprecated:: 1.6
This option has been deprecated. Use the ``tlsAllowInvalidHostnames`` URI
option instead.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: ca_dir
type: string
description: |
Path to a correctly hashed certificate directory. The system certificate store
will be used by default.
Falls back to the deprecated ``capath`` SSL context option if not specified.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: ca_file
type: string
description: |
Path to a certificate authority file. The system certificate store will be
used by default.
Falls back to the deprecated ``cafile`` SSL context option if not specified.
.. deprecated:: 1.6
This option has been deprecated. Use the ``tlsCAFile`` URI option instead.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: crl_file
type: string
description: |
Path to a certificate revocation list file.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: pem_file
type: string
description: |
Path to a PEM encoded certificate to use for client authentication.
Falls back to the deprecated ``local_cert`` SSL context option if not
specified.
.. deprecated:: 1.6
This option has been deprecated. Use the ``tlsCertificateKeyFile`` URI
option instead.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: pem_pwd
type: string
description: |
Passphrase for the PEM encoded certificate (if applicable).
Falls back to the deprecated ``passphrase`` SSL context option if not
specified.
.. deprecated:: 1.6
This option has been deprecated. Use the ``tlsCertificateKeyFilePassword``
URI option instead.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: weak_cert_validation
type: boolean
description: |
Disables certificate validation ``true``. Defaults to ``false``.
Falls back to the deprecated ``allow_self_signed`` SSL context option if not
specified.
.. deprecated:: 1.6
This option has been deprecated. Use the ``tlsAllowInvalidCertificates``
URI option instead.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: context
type: resource
description: |
:php:`SSL context options <manual/en/context.ssl.php>` to be used as fallbacks
for other driver options (as specified). Note that the driver does not consult
the default stream context.
This option is supported for backwards compatibility, but should be considered
deprecated.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: autoEncryption
type: array
description: |
Options to configure client-side field-level encryption in the driver. The
encryption options are documented in the :php:`extension documentation
<manual/en/mongodb-driver-manager.construct.php#mongodb-driver-manager.construct-driveroptions>`.
For the ``keyVaultClient`` option, you may pass a :phpclass:`MongoDB\\Client`
instance, which will be unwrapped to provide a :php:`MongoDB\\Driver\\Manager <class.mongodb-driver-manager>`
to the extension.
interface: phpmethod
operation: ~
optional: true
...
arg_name: param
name: $uri
type: string
description: |
The URI of the standalone, replica set, or sharded cluster to which to
connect. Refer to :manual:`Connection String URI Format
</reference/connection-string>` in the MongoDB manual for more information.
Defaults to ``"mongodb://127.0.0.1:27017"`` if unspecified.
Any special characters in the URI components need to be encoded according to
`RFC 3986 <http://www.faqs.org/rfcs/rfc3986.html>`_. This is particularly
relevant to the username and password, which can often include special
characters such as ``@``, ``:``, or ``%``. When connecting via a Unix domain
socket, the socket path may contain special characters such as slashes and
must be encoded. The :php:`rawurlencode() <rawurlencode>` function may be used
to encode constituent parts of the URI.
interface: phpmethod
operation: ~
optional: true
---
arg_name: param
name: $uriOptions
type: array
description: |
Specifies additional URI options, such as authentication credentials or query
string parameters. The options specified in ``$uriOptions`` take precedence
over any analogous options present in the ``$uri`` string and do not need to
be encoded according to `RFC 3986 <http://www.faqs.org/rfcs/rfc3986.html>`_.
Refer to the :php:`MongoDB\\Driver\\Manager::__construct()
<mongodb-driver-manager.construct>` extension reference and :manual:`MongoDB
connection string </reference/connection-string>` documentation for accepted
options.
interface: phpmethod
operation: ~
optional: true
---
arg_name: param
name: $driverOptions
type: array
description: |
Specify driver-specific options, such as SSL options. In addition to any
options supported by the :php:`extension <mongodb-driver-manager>`, the
|php-library| allows you to specify a default :php:`type map
<manual/en/mongodb.persistence.deserialization.php#mongodb.persistence.typemaps>`
to apply to the cursors it creates.
interface: phpmethod
operation: ~
optional: true
...
source:
file: apiargs-common-option.yaml
ref: session
post: |
.. versionadded:: 1.3
---
source:
file: apiargs-common-option.yaml
ref: typeMap
post: |
This will be used for the returned command result document.
---
source:
file: apiargs-MongoDBClient-common-option.yaml
ref: writeConcern
post: |
This is not supported for server versions prior to 3.4 and will result in an
exception at execution time if used.
...
source:
file: apiargs-common-param.yaml
ref: $databaseName
replacement:
action: " to drop"
---
source:
file: apiargs-common-param.yaml
ref: $options
...
source:
file: apiargs-common-param.yaml
ref: $databaseName
replacement:
action: " to select"
...
arg_name: option
name: filter
type: array|object
description: |
A query expression to filter the list of databases.
You can specify a query expression for database fields (e.g. ``name``,
``sizeOnDisk``, ``empty``).
.. versionadded:: 1.3
interface: phpmethod
operation: ~
optional: true
---
source:
file: apiargs-common-option.yaml
ref: maxTimeMS
---
source:
file: apiargs-common-option.yaml
ref: session
post: |
.. versionadded:: 1.3
...
source:
file: apiargs-common-option.yaml
ref: readConcern
replacement:
resource: "collection"
parent: "client"
---
source:
file: apiargs-common-option.yaml
ref: readPreference
replacement:
resource: "collection"
parent: "client"
---
source:
file: apiargs-common-option.yaml
ref: typeMap
replacement:
parent: "client"
---
source:
file: apiargs-common-option.yaml
ref: writeConcern
replacement:
resource: "collection"
parent: "client"
...
source:
file: apiargs-common-param.yaml
ref: $databaseName
replacement:
action: " containing the collection to select"
---
source:
file: apiargs-common-param.yaml
ref: $collectionName
replacement:
action: " to select"
---
source:
file: apiargs-common-param.yaml
ref: $options
...
source:
file: apiargs-common-option.yaml
ref: readConcern
replacement:
resource: "database"
parent: "client"
---
source:
file: apiargs-common-option.yaml
ref: readPreference
replacement:
resource: "database"
parent: "client"
---
source:
file: apiargs-common-option.yaml
ref: typeMap
replacement:
parent: "client"
---
source:
file: apiargs-common-option.yaml
ref: writeConcern
replacement:
resource: "database"
parent: "client"
...
source:
file: apiargs-common-param.yaml
ref: $databaseName
replacement:
action: " to select"
---
source:
file: apiargs-common-param.yaml
ref: $options
...
---
source:
file: apiargs-method-watch-option.yaml
ref: batchSize
---
source:
file: apiargs-common-option.yaml
ref: collation
---
source:
file: apiargs-method-watch-option.yaml
ref: fullDocument
---
source:
file: apiargs-method-watch-option.yaml
ref: maxAwaitTimeMS
---
source:
file: apiargs-MongoDBClient-common-option.yaml
ref: readConcern
---
source:
file: apiargs-MongoDBClient-common-option.yaml
ref: readPreference
post: |
This is used for both the initial change stream aggregation and for
server selection during an automatic resume.
---
source:
file: apiargs-method-watch-option.yaml
ref: resumeAfter
---
source:
file: apiargs-common-option.yaml
ref: session
---
source:
file: apiargs-method-watch-option.yaml
ref: startAfter
post: |
.. versionadded: 1.5
---
source:
file: apiargs-method-watch-option.yaml
ref: startAtOperationTime
---
source:
file: apiargs-MongoDBClient-common-option.yaml
ref: typeMap
...
source:
file: apiargs-method-watch-param.yaml
ref: $pipeline
---
source:
file: apiargs-method-watch-param.yaml
ref: $options
...
arg_name: option
name: arrayFilters
type: array
description: |
An array of filter documents that determines which array elements to modify
for an update operation on an array field.
This is not supported for server versions prior to 3.6 and will result in an
exception at execution time if used.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: bypassDocumentValidation
type: boolean
description: |
If ``true``, allows the write operation to circumvent document level
validation. Defaults to ``false``.
This option is available in MongoDB 3.2+ and is ignored for older server
versions, which do not support document level validation.
interface: phpmethod
operation: ~
optional: true
---
source:
file: apiargs-common-option.yaml
ref: collation
post: |
If the collation is unspecified but the collection has a default collation,
the operation uses the collation specified for the collection. If no
collation is specified for the collection or for the operation, MongoDB uses
the simple binary comparison used in prior versions for string comparisons.
---
arg_name: option
name: readConcern
type: :php:`MongoDB\\Driver\\ReadConcern <class.mongodb-driver-readconcern>`
description: |
:manual:`Read concern </reference/read-concern>` to use for the operation.
Defaults to the collection's read concern.
This is not supported for server versions prior to 3.2 and will result in an
exception at execution time if used.
It is not possible to specify a :manual:`read concern
</reference/read-concern>` for individual operations as part of a
transaction. Instead, set the ``readConcern`` option when starting the
transaction with :php:`startTransaction <mongodb-driver-session.starttransaction>`.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: readPreference
type: :php:`MongoDB\\Driver\\ReadPreference <class.mongodb-driver-readpreference>`
description: |
:manual:`Read preference </reference/read-preference>` to use for the
operation. Defaults to the collection's read preference.
interface: phpmethod
operation: ~
optional: true
---
source:
file: apiargs-common-option.yaml
ref: typeMap
replacement:
parent: "collection"
---
arg_name: option
name: writeConcern
type: :php:`MongoDB\\Driver\\WriteConcern <class.mongodb-driver-writeconcern>`
description: |
:manual:`Write concern </reference/write-concern>` to use for the operation.
Defaults to the collection's write concern.
It is not possible to specify a :manual:`write concern
</reference/write-concern>` for individual operations as part of a
transaction. Instead, set the ``writeConcern`` option when starting the
transaction with :php:`startTransaction <mongodb-driver-session.starttransaction>`.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: upsert
type: boolean
description: |
If set to ``true``, creates a new document when no document matches the query
criteria. The default value is ``false``, which does not insert a new
document when no match is found.
interface: phpmethod
operation: ~
optional: true
...
arg_name: param
name: $filter
type: array|object
description: |
The filter criteria that specifies the documents{{action}}.
interface: phpmethod
operation: ~
optional: false
replacement:
action: ""
---
arg_name: param
name: $replacement
type: array|object
description: |
The replacement document.
interface: phpmethod
operation: ~
optional: false
---
arg_name: param
name: $update
type: array|object
description: |
Specifies the field and value combinations to update and any relevant update
operators. ``$update`` uses MongoDB's :method:`update operators
</reference/operator/update>`. Starting with MongoDB 4.2, an `aggregation
pipeline <https://docs.mongodb.com/master/reference/command/update/#update-with-an-aggregation-pipeline>`_
can be passed as this parameter.
interface: phpmethod
operation: ~
optional: false
...
source:
file: apiargs-aggregate-option.yaml
ref: allowDiskUse
---
source:
file: apiargs-aggregate-option.yaml
ref: batchSize
---
source:
file: apiargs-aggregate-option.yaml
ref: bypassDocumentValidation
---
source:
file: apiargs-aggregate-option.yaml
ref: comment
post: |
.. versionadded:: 1.3
---
source:
file: apiargs-aggregate-option.yaml
ref: explain
post: |
.. versionadded:: 1.4
---
source:
file: apiargs-common-option.yaml
ref: hint
post: |
.. versionadded:: 1.3
---
source:
file: apiargs-common-option.yaml
ref: maxTimeMS
---
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: readConcern
---
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: readPreference
---
source:
file: apiargs-common-option.yaml
ref: session
post: |
.. versionadded:: 1.3
---
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: typeMap
---
arg_name: option
name: useCursor
type: boolean
description: |
Indicates whether the command will request that the server provide results
using a cursor. The default is ``true``.
.. note::
MongoDB 3.6+ no longer supports returning results without a cursor (excluding
when the explain option is used) and specifying false for this option will
result in a server error.
interface: phpmethod
operation: ~
optional: true
---
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: writeConcern
post: |
This only applies when a :ref:`$out <agg-out>` or :ref:`$merge <agg-merge>`
stage is specified.
This is not supported for server versions prior to 3.4 and will result in an
exception at execution time if used.
...
arg_name: param
name: $pipeline
type: array
description: |
Specifies an :manual:`aggregation pipeline </core/aggregation-pipeline>`
operation.
interface: phpmethod
operation: ~
optional: false
---
source:
file: apiargs-common-param.yaml
ref: $options
...
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: bypassDocumentValidation
---
arg_name: option
name: ordered
type: boolean
description: |
If ``true``: when a single write fails, the operation will stop without
performing the remaining writes and throw an exception.
If ``false``: when a single write fails, the operation will continue with the
remaining writes, if any, and throw an exception.
The default is ``true``.
interface: phpmethod
operation: ~
optional: true
---
source:
file: apiargs-common-option.yaml
ref: session
post: |
.. versionadded:: 1.3
---
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: writeConcern
...
arg_name: param
name: $operations
type: array
description: |
An array containing the write operations to perform.
:phpmethod:`MongoDB\\Collection::bulkWrite()` supports
:phpmethod:`deleteMany() <MongoDB\\Collection::deleteMany>`,
:phpmethod:`deleteOne() <MongoDB\\Collection::deleteOne>`,
:phpmethod:`insertOne() <MongoDB\\Collection::insertOne>`,
:phpmethod:`replaceOne() <MongoDB\\Collection::replaceOne>`,
:phpmethod:`updateMany() <MongoDB\\Collection::updateMany>`, and
:phpmethod:`updateOne() <MongoDB\\Collection::updateOne>` operations in the
following array structure:
.. code-block:: php
[
[ 'deleteMany' => [ $filter ] ],
[ 'deleteOne' => [ $filter ] ],
[ 'insertOne' => [ $document ] ],
[ 'replaceOne' => [ $filter, $replacement, $options ] ],
[ 'updateMany' => [ $filter, $update, $options ] ],
[ 'updateOne' => [ $filter, $update, $options ] ],
]
Arguments correspond to the respective operation methods. However, the
``writeConcern`` option is specified as a top-level option to
:phpmethod:`MongoDB\\Collection::bulkWrite()` instead of each individual
operation.
interface: phpmethod
operation: ~
optional: true
---
source:
file: apiargs-common-param.yaml
ref: $options
...
source:
file: apiargs-common-option.yaml
ref: readConcern
replacement:
resource: "collection"
parent: "manager"
---
source:
file: apiargs-common-option.yaml
ref: readPreference
replacement:
resource: "collection"
parent: "manager"
---
source:
file: apiargs-MongoDBClient-method-construct-driverOptions.yaml
ref: typeMap
---
source:
file: apiargs-common-option.yaml
ref: writeConcern
replacement:
resource: "collection"
parent: "manager"
...
source:
file: apiargs-common-param.yaml
ref: $manager
---
source:
file: apiargs-common-param.yaml
ref: $databaseName
---
source:
file: apiargs-common-param.yaml
ref: $collectionName
---
source:
file: apiargs-common-param.yaml
ref: $options
...
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: collation
---
arg_name: option
name: hint
type: string|array|object
description: |
The index to use. Specify either the index name as a string or the index key
pattern as a document. If specified, then the query system will only consider
plans using the hinted index.
.. versionchanged:: 1.2
If a document is provided, it is passed to the command as-is. Previously,
the library would convert the key pattern to an index name.
interface: phpmethod
operation: ~
optional: true
---
arg_name: option
name: limit
type: integer
description: |
The maximum number of matching documents to return.
interface: phpmethod
operation: ~
optional: true
---
source:
file: apiargs-common-option.yaml
ref: maxTimeMS
---
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: readConcern
---
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: readPreference
---
source:
file: apiargs-common-option.yaml
ref: session
post: |
.. versionadded:: 1.3
---
arg_name: option
name: skip
type: integer
description: |
The number of matching documents to skip before returning results.
interface: phpmethod
operation: ~
optional: true
...
This diff could not be displayed because it is too large.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment