Unverified Commit 1ffc7a27 authored by Divine's avatar Divine Committed by GitHub

Merge branch 'pr_1491' into pr/17

parents 929120f1 4d81b402
exclude_paths:
- '.github/**'
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
\ No newline at end of file
github: jenssegers
open_collective: laravel-mongodb
---
name: "Bug report"
about: 'Report errors or unexpected behavior.'
---
- Laravel-mongodb Version: #.#.#
- PHP Version: #.#.#
- Database Driver & Version:
### Description:
### Steps to reproduce
1.
2.
3.
### Expected behaviour
Tell us what should happen
### Actual behaviour
Tell us what happens instead
<details><summary><b>Logs</b>:</summary>
Insert log.txt here (if necessary)
</details>
---
name: Feature request
about: Suggest an idea.
title: "[Feature Request] "
---
### Is your feature request related to a problem?
A clear and concise description of what the problem is.
### Describe the solution you'd like
A clear and concise description of what you want to happen.
### Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
### Additional context
Add any other context or screenshots about the feature request here.
---
name: Question
about: Ask a question.
title: "[Question] "
labels: 'question'
assignees: ''
---
name: CI
on:
push:
branches:
tags:
pull_request:
jobs:
build:
runs-on: ${{matrix.os}}
strategy:
matrix:
php: ['7.1', '7.2', '7.3', '7.4']
os: ['ubuntu-latest']
mongodb: ['3.6', '4.0', '4.2']
services:
mongo:
image: mongo:${{ matrix.mongodb }}
ports:
- 27017:27017
mysql:
image: mysql:5.7
ports:
- 3307:3306
env:
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
MYSQL_DATABASE: 'unittest'
MYSQL_ROOT_PASSWORD:
name: PHP v${{ matrix.php }} with Mongo v${{ matrix.mongodb }}
steps:
- uses: actions/checkout@v1
- name: Show PHP version
run: php${{ matrix.php }} -v && composer -V
- name: Show Docker version
run: if [[ "$DEBUG" == "true" ]]; then docker version && env; fi
env:
DEBUG: ${{secrets.DEBUG}}
- name: Download Composer cache dependencies from cache
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache Composer dependencies
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ matrix.os }}-composer-
- name: Install dependencies
run: |
composer install --no-interaction
- name: Run tests
run: |
./vendor/bin/phpunit --coverage-clover coverage.xml
env:
MONGO_HOST: 0.0.0.0
MYSQL_HOST: 0.0.0.0
MYSQL_PORT: 3307
- name: Send coveralls
run: vendor/bin/coveralls coverage.xml
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
...@@ -7,3 +7,4 @@ composer.lock ...@@ -7,3 +7,4 @@ composer.lock
*.sublime-workspace *.sublime-workspace
*.project *.project
.idea/ .idea/
.phpunit.result.cache
preset: laravel
sudo: required
dist: trusty
language: php
php:
- "7.2"
- "7.1"
services:
- docker
install:
# Update docker-engine using Ubuntu 'trusty' apt repo
- >
curl -sSL "https://get.docker.com/gpg" |
sudo -E apt-key add -
- >
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" |
sudo tee -a /etc/apt/sources.list
- sudo apt-get update
- >
sudo apt-get -o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" --assume-yes install docker-engine --allow-unauthenticated
- docker version
# Update docker-compose via pip
- sudo pip install docker-compose
- docker-compose version
- docker-compose up --build -d
- docker ps -a
script:
- docker-compose up --exit-code-from php
ARG PHP_VERSION=7.2
ARG COMPOSER_VERSION=1.8
FROM composer:${COMPOSER_VERSION}
FROM php:${PHP_VERSION}-cli
RUN apt-get update && \
apt-get install -y autoconf pkg-config libssl-dev git libzip-dev zlib1g-dev && \
pecl install mongodb && docker-php-ext-enable mongodb && \
pecl install xdebug && docker-php-ext-enable xdebug && \
docker-php-ext-install -j$(nproc) pdo_mysql zip
COPY --from=composer /usr/bin/composer /usr/local/bin/composer
WORKDIR /code
Laravel MongoDB Laravel MongoDB
=============== ===============
[![Latest Stable Version](http://img.shields.io/github/release/jenssegers/laravel-mongodb.svg)](https://packagist.org/packages/jenssegers/mongodb) [![Total Downloads](http://img.shields.io/packagist/dm/jenssegers/mongodb.svg)](https://packagist.org/packages/jenssegers/mongodb) [![Build Status](http://img.shields.io/travis/jenssegers/laravel-mongodb.svg)](https://travis-ci.org/jenssegers/laravel-mongodb) [![Coverage Status](http://img.shields.io/coveralls/jenssegers/laravel-mongodb.svg)](https://coveralls.io/r/jenssegers/laravel-mongodb?branch=master) [![Donate](https://img.shields.io/badge/donate-paypal-blue.svg)](https://www.paypal.me/jenssegers) [![Latest Stable Version](http://img.shields.io/github/release/jenssegers/laravel-mongodb.svg)](https://packagist.org/packages/jenssegers/mongodb)
[![Total Downloads](http://img.shields.io/packagist/dm/jenssegers/mongodb.svg)](https://packagist.org/packages/jenssegers/mongodb)
An Eloquent model and Query builder with support for MongoDB, using the original Laravel API. *This library extends the original Laravel classes, so it uses exactly the same methods.* [![Build Status](https://img.shields.io/github/workflow/status/jenssegers/laravel-mongodb/CI)](https://github.com/jenssegers/laravel-mongodb/actions)
[![codecov](https://codecov.io/gh/jenssegers/laravel-mongodb/branch/master/graph/badge.svg)](https://codecov.io/gh/jenssegers/laravel-mongodb/branch/master)
Table of contents [![Donate](https://img.shields.io/badge/donate-paypal-blue.svg)](https://www.paypal.me/jenssegers)
-----------------
* [Installation](#installation) This package adds functionalities to the Eloquent model and Query builder for MongoDB, using the original Laravel API. *This library extends the original Laravel classes, so it uses exactly the same methods.*
* [Upgrading](#upgrading)
* [Configuration](#configuration) - [Laravel MongoDB](#laravel-mongodb)
* [Eloquent](#eloquent) - [Installation](#installation)
* [Optional: Alias](#optional-alias) - [Laravel version Compatibility](#laravel-version-compatibility)
* [Query Builder](#query-builder) - [Laravel](#laravel)
* [Schema](#schema) - [Lumen](#lumen)
* [Extensions](#extensions) - [Non-Laravel projects](#non-laravel-projects)
* [Troubleshooting](#troubleshooting) - [Testing](#testing)
* [Examples](#examples) - [Database Testing](#database-testing)
- [Configuration](#configuration)
- [Eloquent](#eloquent)
- [Extending the base model](#extending-the-base-model)
- [Soft Deletes](#soft-deletes)
- [Dates](#dates)
- [Basic Usage](#basic-usage)
- [MongoDB-specific operators](#mongodb-specific-operators)
- [MongoDB-specific Geo operations](#mongodb-specific-geo-operations)
- [Inserts, updates and deletes](#inserts-updates-and-deletes)
- [MongoDB specific operations](#mongodb-specific-operations)
- [Relationships](#relationships)
- [Basic Usage](#basic-usage-1)
- [belongsToMany and pivots](#belongstomany-and-pivots)
- [EmbedsMany Relationship](#embedsmany-relationship)
- [EmbedsOne Relationship](#embedsone-relationship)
- [Query Builder](#query-builder)
- [Basic Usage](#basic-usage-2)
- [Available operations](#available-operations)
- [Schema](#schema)
- [Basic Usage](#basic-usage-3)
- [Geospatial indexes](#geospatial-indexes)
- [Extending](#extending)
- [Cross-Database Relationships](#cross-database-relationships)
- [Authentication](#authentication)
- [Queues](#queues)
- [Upgrading](#upgrading)
- [Upgrading from version 2 to 3](#upgrading-from-version-2-to-3)
Installation Installation
------------ ------------
Make sure you have the MongoDB PHP driver installed. You can find installation instructions at http://php.net/manual/en/mongodb.installation.php Make sure you have the MongoDB PHP driver installed. You can find installation instructions at http://php.net/manual/en/mongodb.installation.php
**WARNING**: The old mongo PHP driver is not supported anymore in versions >= 3.0.
Installation using composer:
```
composer require jenssegers/mongodb
```
### Laravel version Compatibility ### Laravel version Compatibility
Laravel | Package Laravel | Package
...@@ -43,13 +61,26 @@ composer require jenssegers/mongodb ...@@ -43,13 +61,26 @@ composer require jenssegers/mongodb
5.4.x | 3.2.x 5.4.x | 3.2.x
5.5.x | 3.3.x 5.5.x | 3.3.x
5.6.x | 3.4.x 5.6.x | 3.4.x
5.7.x | 3.4.x
5.8.x | 3.5.x
6.0.x | 3.6.x
And add the service provider in `config/app.php`: Install the package via Composer:
```bash
$ composer require jenssegers/mongodb
```
### Laravel
In case your Laravel version does NOT autoload the packages, add the service provider to `config/app.php`:
```php ```php
Jenssegers\Mongodb\MongodbServiceProvider::class, Jenssegers\Mongodb\MongodbServiceProvider::class,
``` ```
### Lumen
For usage with [Lumen](http://lumen.laravel.com), add the service provider in `bootstrap/app.php`. In this file, you will also need to enable Eloquent. You must however ensure that your call to `$app->withEloquent();` is **below** where you have registered the `MongodbServiceProvider`: For usage with [Lumen](http://lumen.laravel.com), add the service provider in `bootstrap/app.php`. In this file, you will also need to enable Eloquent. You must however ensure that your call to `$app->withEloquent();` is **below** where you have registered the `MongodbServiceProvider`:
```php ```php
...@@ -58,346 +89,284 @@ $app->register(Jenssegers\Mongodb\MongodbServiceProvider::class); ...@@ -58,346 +89,284 @@ $app->register(Jenssegers\Mongodb\MongodbServiceProvider::class);
$app->withEloquent(); $app->withEloquent();
``` ```
The service provider will register a mongodb database extension with the original database manager. There is no need to register additional facades or objects. When using mongodb connections, Laravel will automatically provide you with the corresponding mongodb objects. The service provider will register a MongoDB database extension with the original database manager. There is no need to register additional facades or objects.
When using MongoDB connections, Laravel will automatically provide you with the corresponding MongoDB objects.
### Non-Laravel projects
For usage outside Laravel, check out the [Capsule manager](https://github.com/illuminate/database/blob/master/README.md) and add: For usage outside Laravel, check out the [Capsule manager](https://github.com/illuminate/database/blob/master/README.md) and add:
```php ```php
$capsule->getDatabaseManager()->extend('mongodb', function($config) $capsule->getDatabaseManager()->extend('mongodb', function($config, $name) {
{ $config['name'] = $name;
return new Jenssegers\Mongodb\Connection($config); return new Jenssegers\Mongodb\Connection($config);
}); });
``` ```
Upgrading Testing
--------- -------
#### Upgrading from version 2 to 3
In this new major release which supports the new mongodb PHP extension, we also moved the location of the Model class and replaced the MySQL model class with a trait.
Please change all `Jenssegers\Mongodb\Model` references to `Jenssegers\Mongodb\Eloquent\Model` either at the top of your model files, or your registered alias.
```php To run the test for this package, run:
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class User extends Eloquent {} ```
docker-compose up
``` ```
If you are using hybrid relations, your MySQL classes should now extend the original Eloquent model class `Illuminate\Database\Eloquent\Model` instead of the removed `Jenssegers\Eloquent\Model`. Instead use the new `Jenssegers\Mongodb\Eloquent\HybridRelations` trait. This should make things more clear as there is only one single model class in this package. Database Testing
-------
```php
use Jenssegers\Mongodb\Eloquent\HybridRelations;
class User extends Eloquent {
use HybridRelations;
protected $connection = 'mysql'; To reset the database after each test, add:
} ```php
use Illuminate\Foundation\Testing\DatabaseMigrations;
``` ```
Embedded relations now return an `Illuminate\Database\Eloquent\Collection` rather than a custom Collection class. If you were using one of the special methods that were available, convert them to Collection operations. Also inside each test classes, add:
```php ```php
$books = $user->books()->sortBy('title'); use DatabaseMigrations;
``` ```
Testing Keep in mind that these traits are not yet supported:
------- - `use Database Transactions;`
- `use RefreshDatabase;`
To run the test for this package, run:
```
docker-compose up
```
Configuration Configuration
------------- -------------
You can use MongoDB either as the main database, either as a side database. To do so, add a new `mongodb` connection to `config/database.php`:
Change your default database connection name in `config/database.php`:
```php
'default' => env('DB_CONNECTION', 'mongodb'),
```
And add a new mongodb connection:
```php ```php
'mongodb' => [ 'mongodb' => [
'driver' => 'mongodb', 'driver' => 'mongodb',
'host' => env('DB_HOST', 'localhost'), 'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', 27017), 'port' => env('DB_PORT', 27017),
'database' => env('DB_DATABASE'), 'database' => env('DB_DATABASE', 'homestead'),
'username' => env('DB_USERNAME'), 'username' => env('DB_USERNAME', 'homestead'),
'password' => env('DB_PASSWORD'), 'password' => env('DB_PASSWORD', 'secret'),
'options' => [ 'options' => [
'database' => 'admin' // sets the authentication database required by mongo 3 // here you can pass more settings to the Mongo Driver Manager
] // see https://www.php.net/manual/en/mongodb-driver-manager.construct.php under "Uri Options" for a list of complete parameters that you can use
'database' => env('DB_AUTHENTICATION_DATABASE', 'admin'), // required with Mongo 3+
],
], ],
``` ```
You can connect to multiple servers or replica sets with the following configuration: For multiple servers or replica set configurations, set the host to an array and specify each server host:
```php ```php
'mongodb' => [ 'mongodb' => [
'driver' => 'mongodb', 'driver' => 'mongodb',
'host' => ['server1', 'server2'], 'host' => ['server1', 'server2', ...],
'port' => env('DB_PORT', 27017), ...
'database' => env('DB_DATABASE'), 'options' => [
'username' => env('DB_USERNAME'), 'replicaSet' => 'rs0',
'password' => env('DB_PASSWORD'), ],
'options' => [
'replicaSet' => 'replicaSetName'
]
], ],
``` ```
Alternatively, you can use MongoDB connection string: If you wish to use a connection string instead of full key-value params, you can set it so. Check the documentation on MongoDB's URI format: https://docs.mongodb.com/manual/reference/connection-string/
```php ```php
'mongodb' => [ 'mongodb' => [
'driver' => 'mongodb', 'driver' => 'mongodb',
'dsn' => env('DB_DSN'), 'dsn' => env('DB_DSN'),
'database' => env('DB_DATABASE'), 'database' => env('DB_DATABASE', 'homestead'),
], ],
``` ```
Please refer to MongoDB official docs for its URI format: https://docs.mongodb.com/manual/reference/connection-string/
Eloquent Eloquent
-------- --------
### Extending the base model
This package includes a MongoDB enabled Eloquent class that you can use to define models for corresponding collections. This package includes a MongoDB enabled Eloquent class that you can use to define models for corresponding collections.
```php ```php
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model;
class User extends Eloquent {}
```
Note that we did not tell Eloquent which collection to use for the `User` model. Just like the original Eloquent, the lower-case, plural name of the class will be used as the collection name unless another name is explicitly specified. You may specify a custom collection (alias for table) by defining a `collection` property on your model:
```php
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class User extends Eloquent {
protected $collection = 'users_collection';
class Book extends Model
{
//
} }
``` ```
**NOTE:** Eloquent will also assume that each collection has a primary key column named id. You may define a `primaryKey` property to override this convention. Likewise, you may define a `connection` property to override the name of the database connection that should be used when utilizing the model. Just like a normal model, the MongoDB model class will know which collection to use based on the model name. For `Book`, the collection `books` will be used.
```php To change the collection, pass the `$collection` property:
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class MyModel extends Eloquent { ```php
use Jenssegers\Mongodb\Eloquent\Model;
protected $connection = 'mongodb';
class Book extends Model
{
protected $collection = 'my_books_collection';
} }
``` ```
Everything else (should) work just like the original Eloquent model. Read more about the Eloquent on http://laravel.com/docs/eloquent **NOTE:** MongoDB documents are automatically stored with a unique ID that is stored in the `_id` property. If you wish to use your own ID, substitute the `$primaryKey` property and set it to your own primary key attribute name.
### Optional: Alias
You may also register an alias for the MongoDB model by adding the following to the alias array in `config/app.php`:
```php ```php
'Moloquent' => Jenssegers\Mongodb\Eloquent\Model::class, use Jenssegers\Mongodb\Eloquent\Model;
```
This will allow you to use the registered alias like: class Book extends Model
{
protected $primaryKey = 'id';
}
```php // Mongo will also create _id, but the 'id' property will be used for primary key actions like find().
class MyModel extends Moloquent {} Book::create(['id' => 1, 'title' => 'The Fault in Our Stars']);
``` ```
Query Builder Likewise, you may define a `connection` property to override the name of the database connection that should be used when utilizing the model.
-------------
The database driver plugs right into the original query builder. When using mongodb connections, you will be able to build fluent queries to perform database operations. For your convenience, there is a `collection` alias for `table` as well as some additional mongodb specific operators/operations.
```php ```php
$users = DB::collection('users')->get(); use Jenssegers\Mongodb\Eloquent\Model;
$user = DB::collection('users')->where('name', 'John')->first();
```
If you did not change your default database connection, you will need to specify it when querying.
```php class Book extends Model
$user = DB::connection('mongodb')->collection('users')->get(); {
protected $connection = 'mongodb';
}
``` ```
Read more about the query builder on http://laravel.com/docs/queries ### Soft Deletes
Schema When soft deleting a model, it is not actually removed from your database. Instead, a deleted_at timestamp is set on the record.
------
The database driver also has (limited) schema builder support. You can easily manipulate collections and set indexes: To enable soft deletes for a model, apply the `Jenssegers\Mongodb\Eloquent\SoftDeletes` Trait to the model:
```php ```php
Schema::create('users', function($collection) use Jenssegers\Mongodb\Eloquent\SoftDeletes;
class User extends Model
{ {
$collection->index('name'); use SoftDeletes;
$collection->unique('email'); protected $dates = ['deleted_at'];
}); }
``` ```
Supported operations are: For more information check [Laravel Docs about Soft Deleting](http://laravel.com/docs/eloquent#soft-deleting).
- create and drop
- collection
- hasCollection
- index and dropIndex (compound indexes supported as well)
- unique
- background, sparse, expire, geospatial (MongoDB specific)
All other (unsupported) operations are implemented as dummy pass-through methods, because MongoDB does not use a predefined schema. Read more about the schema builder on http://laravel.com/docs/schema ### Dates
### Geospatial indexes
Geospatial indexes are handy for querying location-based documents. They come in two forms: `2d` and `2dsphere`. Use the schema builder to add these to a collection.
To add a `2d` index: Eloquent allows you to work with Carbon or DateTime objects instead of MongoDate objects. Internally, these dates will be converted to MongoDate objects when saved to the database.
```php ```php
Schema::create('users', function($collection) use Jenssegers\Mongodb\Eloquent\Model;
{
$collection->geospatial('name', '2d');
});
```
To add a `2dsphere` index:
```php class User extends Model
Schema::create('users', function($collection)
{ {
$collection->geospatial('name', '2dsphere'); protected $dates = ['birthday'];
}); }
``` ```
Extensions This allows you to execute queries like this:
----------
### Auth
If you want to use Laravel's native Auth functionality, register this included service provider:
```php ```php
'Jenssegers\Mongodb\Auth\PasswordResetServiceProvider', $users = User::where(
'birthday', '>',
new DateTime('-18 years')
)->get();
``` ```
This service provider will slightly modify the internal DatabaseReminderRepository to add support for MongoDB based password reminders. If you don't use password reminders, you don't have to register this service provider and everything else should work just fine. ### Basic Usage
### Queues
If you want to use MongoDB as your database backend, change the the driver in `config/queue.php`: **Retrieving all models**
```php ```php
'connections' => [ $users = User::all();
'database' => [
'driver' => 'mongodb',
'table' => 'jobs',
'queue' => 'default',
'expire' => 60,
],
``` ```
If you want to use MongoDB to handle failed jobs, change the database in `config/queue.php`: **Retrieving a record by primary key**
```php ```php
'failed' => [ $user = User::find('517c43667db388101e00000f');
'database' => 'mongodb',
'table' => 'failed_jobs',
],
``` ```
And add the service provider in `config/app.php`: **Where**
```php ```php
Jenssegers\Mongodb\MongodbQueueServiceProvider::class, $posts =
Post::where('author.name', 'John')
->take(10)
->get();
``` ```
### Sentry **OR Statements**
If you want to use this library with [Sentry](https://cartalyst.com/manual/sentry), then check out https://github.com/jenssegers/Laravel-MongoDB-Sentry
### Sessions
The MongoDB session driver is available in a separate package, check out https://github.com/jenssegers/Laravel-MongoDB-Session
Examples
--------
### Basic Usage
**Retrieving All Models**
```php ```php
$users = User::all(); $posts =
Post::where('votes', '>', 0)
->orWhere('is_approved', true)
->get();
``` ```
**Retrieving A Record By Primary Key** **AND statements**
```php ```php
$user = User::find('517c43667db388101e00000f'); $users =
User::where('age', '>', 18)
->where('name', '!=', 'John')
->get();
``` ```
**Wheres** **whereIn**
```php ```php
$users = User::where('votes', '>', 100)->take(10)->get(); $users = User::whereIn('age', [16, 18, 20])->get();
``` ```
**Or Statements** When using `whereNotIn` objects will be returned if the field is non-existent. Combine with `whereNotNull('age')` to leave out those documents.
```php **whereBetween**
$users = User::where('votes', '>', 100)->orWhere('name', 'John')->get();
```
**And Statements**
```php ```php
$users = User::where('votes', '>', 100)->where('name', '=', 'John')->get(); $posts = Post::whereBetween('votes', [1, 100])->get();
``` ```
**Using Where In With An Array** **whereNull**
```php ```php
$users = User::whereIn('age', [16, 18, 20])->get(); $users = User::whereNull('age')->get();
``` ```
When using `whereNotIn` objects will be returned if the field is non existent. Combine with `whereNotNull('age')` to leave out those documents. **Advanced wheres**
**Using Where Between**
```php ```php
$users = User::whereBetween('votes', [1, 100])->get(); $users =
User::where('name', 'John')
->orWhere(function ($query) {
return $query
->where('votes', '>', 100)
->where('title', '<>', 'Admin');
})->get();
``` ```
**Where null** **orderBy**
```php ```php
$users = User::whereNull('updated_at')->get(); $users = User::orderBy('age', 'desc')->get();
``` ```
**Order By** **Offset & Limit (skip & take)**
```php ```php
$users = User::orderBy('name', 'desc')->get(); $users =
User::skip(10)
->take(5)
->get();
``` ```
**Offset & Limit** **groupBy**
Selected columns that are not grouped will be aggregated with the `$last` function.
```php ```php
$users = User::skip(10)->take(5)->get(); $users =
Users::groupBy('title')
->get(['title', 'name']);
``` ```
**Distinct** **Distinct**
...@@ -406,45 +375,36 @@ Distinct requires a field for which to return the distinct values. ...@@ -406,45 +375,36 @@ Distinct requires a field for which to return the distinct values.
```php ```php
$users = User::distinct()->get(['name']); $users = User::distinct()->get(['name']);
// or
// Equivalent to:
$users = User::distinct('name')->get(); $users = User::distinct('name')->get();
``` ```
Distinct can be combined with **where**: Distinct can be combined with **where**:
```php ```php
$users = User::where('active', true)->distinct('name')->get(); $users =
``` User::where('active', true)
->distinct('name')
**Advanced Wheres** ->get();
```php
$users = User::where('name', '=', 'John')->orWhere(function($query)
{
$query->where('votes', '>', 100)
->where('title', '<>', 'Admin');
})
->get();
``` ```
**Group By** **Like**
Selected columns that are not grouped will be aggregated with the $last function.
```php ```php
$users = Users::groupBy('title')->get(['title', 'name']); $spamComments = Comment::where('body', 'like', '%spam%')->get();
``` ```
**Aggregation** **Aggregation**
*Aggregations are only available for MongoDB versions greater than 2.2.* **Aggregations are only available for MongoDB versions greater than 2.2.x**
```php ```php
$total = Order::count(); $total = Product::count();
$price = Order::max('price'); $price = Product::max('price');
$price = Order::min('price'); $price = Product::min('price');
$price = Order::avg('price'); $price = Product::avg('price');
$total = Order::sum('price'); $total = Product::sum('price');
``` ```
Aggregations can be combined with **where**: Aggregations can be combined with **where**:
...@@ -453,62 +413,41 @@ Aggregations can be combined with **where**: ...@@ -453,62 +413,41 @@ Aggregations can be combined with **where**:
$sold = Orders::where('sold', true)->sum('price'); $sold = Orders::where('sold', true)->sum('price');
``` ```
Aggregations can be also used on subdocuments: Aggregations can be also used on sub-documents:
```php ```php
$total = Order::max('suborder.price'); $total = Order::max('suborder.price');
...
``` ```
**NOTE**: this aggreagtion only works with single subdocuments (like embedsOne) not subdocument arrays (like embedsMany) **NOTE**: This aggregation only works with single sub-documents (like `EmbedsOne`) not subdocument arrays (like `EmbedsMany`).
**Like**
```php
$user = Comment::where('body', 'like', '%spam%')->get();
```
**Incrementing or decrementing a value of a column** **Incrementing/Decrementing the value of a column**
Perform increments or decrements (default 1) on specified attributes: Perform increments or decrements (default 1) on specified attributes:
```php ```php
User::where('name', 'John Doe')->increment('age'); Cat::where('name', 'Kitty')->increment('age');
User::where('name', 'Jaques')->decrement('weight', 50);
Car::where('name', 'Toyota')->decrement('weight', 50);
``` ```
The number of updated objects is returned: The number of updated objects is returned:
```php ```php
$count = User->increment('age'); $count = User::increment('age');
``` ```
You may also specify additional columns to update: You may also specify additional columns to update:
```php ```php
User::where('age', '29')->increment('age', 1, ['group' => 'thirty something']); Cat::where('age', 3)
User::where('bmi', 30)->decrement('bmi', 1, ['category' => 'overweight']); ->increment('age', 1, ['group' => 'Kitty Club']);
```
**Soft deleting**
When soft deleting a model, it is not actually removed from your database. Instead, a deleted_at timestamp is set on the record. To enable soft deletes for a model, apply the SoftDeletingTrait to the model: Car::where('weight', 300)
->decrement('weight', 100, ['latest_change' => 'carbon fiber']);
```php
use Jenssegers\Mongodb\Eloquent\SoftDeletes;
class User extends Eloquent {
use SoftDeletes;
protected $dates = ['deleted_at'];
}
``` ```
For more information check http://laravel.com/docs/eloquent#soft-deleting ### MongoDB-specific operators
### MongoDB specific operators
**Exists** **Exists**
...@@ -531,7 +470,7 @@ User::where('roles', 'all', ['moderator', 'author'])->get(); ...@@ -531,7 +470,7 @@ User::where('roles', 'all', ['moderator', 'author'])->get();
Selects documents if the array field is a specified size. Selects documents if the array field is a specified size.
```php ```php
User::where('tags', 'size', 3)->get(); Post::where('tags', 'size', 3)->get();
``` ```
**Regex** **Regex**
...@@ -539,19 +478,21 @@ User::where('tags', 'size', 3)->get(); ...@@ -539,19 +478,21 @@ User::where('tags', 'size', 3)->get();
Selects documents where values match a specified regular expression. Selects documents where values match a specified regular expression.
```php ```php
User::where('name', 'regex', new \MongoDB\BSON\Regex("/.*doe/i"))->get(); use MongoDB\BSON\Regex;
User::where('name', 'regex', new Regex('.*doe', 'i'))->get();
``` ```
**NOTE:** you can also use the Laravel regexp operations. These are a bit more flexible and will automatically convert your regular expression string to a MongoDB\BSON\Regex object. **NOTE:** you can also use the Laravel regexp operations. These are a bit more flexible and will automatically convert your regular expression string to a `MongoDB\BSON\Regex` object.
```php ```php
User::where('name', 'regexp', '/.*doe/i'))->get(); User::where('name', 'regexp', '/.*doe/i')->get();
``` ```
And the inverse: The inverse of regexp:
```php ```php
User::where('name', 'not regexp', '/.*doe/i'))->get(); User::where('name', 'not regexp', '/.*doe/i')->get();
``` ```
**Type** **Type**
...@@ -570,245 +511,306 @@ Performs a modulo operation on the value of a field and selects documents with a ...@@ -570,245 +511,306 @@ Performs a modulo operation on the value of a field and selects documents with a
User::where('age', 'mod', [10, 0])->get(); User::where('age', 'mod', [10, 0])->get();
``` ```
**Near** ### MongoDB-specific Geo operations
**NOTE:** Specify coordinates in this order: `longitude, latitude`. **Near**
```php ```php
$users = User::where('location', 'near', [ $bars = Bar::where('location', 'near', [
'$geometry' => [ '$geometry' => [
'type' => 'Point', 'type' => 'Point',
'coordinates' => [ 'coordinates' => [
-0.1367563, -0.1367563, // longitude
51.5100913, 51.5100913, // latitude
], ],
], ],
'$maxDistance' => 50, '$maxDistance' => 50,
]); ])->get();
``` ```
**GeoWithin** **GeoWithin**
```php ```php
$users = User::where('location', 'geoWithin', [ $bars = Bar::where('location', 'geoWithin', [
'$geometry' => [ '$geometry' => [
'type' => 'Polygon', 'type' => 'Polygon',
'coordinates' => [[ 'coordinates' => [
[
-0.1450383,
51.5069158,
],
[
-0.1367563,
51.5100913,
],
[
-0.1270247,
51.5013233,
],
[ [
-0.1450383, [-0.1450383, 51.5069158],
51.5069158, [-0.1367563, 51.5100913],
[-0.1270247, 51.5013233],
[-0.1450383, 51.5069158],
], ],
]], ],
], ],
]); ])->get();
``` ```
**GeoIntersects** **GeoIntersects**
```php ```php
$locations = Location::where('location', 'geoIntersects', [ $bars = Bar::where('location', 'geoIntersects', [
'$geometry' => [ '$geometry' => [
'type' => 'LineString', 'type' => 'LineString',
'coordinates' => [ 'coordinates' => [
[ [-0.144044, 51.515215],
-0.144044, [-0.129545, 51.507864],
51.515215,
],
[
-0.129545,
51.507864,
],
], ],
], ],
]); ])->get();
``` ```
### Inserts, updates and deletes
Inserting, updating and deleting records works just like the original Eloquent. Please check [Laravel Docs' Eloquent section](https://laravel.com/docs/6.x/eloquent).
**Where** Here, only the MongoDB-specific operations are specified.
Matches documents that satisfy a JavaScript expression. For more information check http://docs.mongodb.org/manual/reference/operator/query/where/#op._S_where
### Inserts, updates and deletes ### MongoDB specific operations
Inserting, updating and deleting records works just like the original Eloquent. **Raw Expressions**
**Saving a new model** These expressions will be injected directly into the query.
```php ```php
$user = new User; User::whereRaw([
$user->name = 'John'; 'age' => ['$gt' => 30, '$lt' => 40],
$user->save(); ])->get();
``` ```
You may also use the create method to save a new model in a single line: You can also perform raw expressions on the internal MongoCollection object. If this is executed on the model class, it will return a collection of models.
If this is executed on the query builder, it will return the original response.
**Cursor timeout**
To prevent `MongoCursorTimeout` exceptions, you can manually set a timeout value that will be applied to the cursor:
```php ```php
User::create(['name' => 'John']); DB::collection('users')->timeout(-1)->get();
``` ```
**Updating a model** **Upsert**
To update a model, you may retrieve it, change an attribute, and use the save method. Update or insert a document. Additional options for the update method are passed directly to the native update method.
```php ```php
$user = User::first(); // Query Builder
$user->email = 'john@foo.com'; DB::collection('users')
$user->save(); ->where('name', 'John')
->update($data, ['upsert' => true]);
// Eloquent
$user->update($data, ['upsert' => true]);
``` ```
*There is also support for upsert operations, check https://github.com/jenssegers/laravel-mongodb#mongodb-specific-operations* **Projections**
**Deleting a model** You can apply projections to your queries using the `project` method.
To delete a model, simply call the delete method on the instance: ```php
DB::collection('items')
->project(['tags' => ['$slice' => 1]])
->get();
DB::collection('items')
->project(['tags' => ['$slice' => [3, 7]]])
->get();
```
**Projections with Pagination**
```php ```php
$user = User::first(); $limit = 25;
$user->delete(); $projections = ['id', 'name'];
DB::collection('items')
->paginate($limit, $projections);
``` ```
Or deleting a model by its key: **Push**
Add items to an array.
```php ```php
User::destroy('517c43667db388101e00000f'); DB::collection('users')
->where('name', 'John')
->push('items', 'boots');
$user->push('items', 'boots');
``` ```
For more information about model manipulation, check http://laravel.com/docs/eloquent#insert-update-delete ```php
DB::collection('users')
->where('name', 'John')
->push('messages', [
'from' => 'Jane Doe',
'message' => 'Hi John',
]);
### Dates $user->push('messages', [
'from' => 'Jane Doe',
'message' => 'Hi John',
]);
```
Eloquent allows you to work with Carbon/DateTime objects instead of MongoDate objects. Internally, these dates will be converted to MongoDate objects when saved to the database. If you wish to use this functionality on non-default date fields you will need to manually specify them as described here: http://laravel.com/docs/eloquent#date-mutators If you **DON'T** want duplicate items, set the third parameter to `true`:
```php
DB::collection('users')
->where('name', 'John')
->push('items', 'boots', true);
Example: $user->push('items', 'boots', true);
```
**Pull**
Remove an item from an array.
```php ```php
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; DB::collection('users')
->where('name', 'John')
->pull('items', 'boots');
class User extends Eloquent { $user->pull('items', 'boots');
```
protected $dates = ['birthday']; ```php
DB::collection('users')
->where('name', 'John')
->pull('messages', [
'from' => 'Jane Doe',
'message' => 'Hi John',
]);
} $user->pull('messages', [
'from' => 'Jane Doe',
'message' => 'Hi John',
]);
``` ```
Which allows you to execute queries like: **Unset**
Remove one or more fields from a document.
```php ```php
$users = User::where('birthday', '>', new DateTime('-18 years'))->get(); DB::collection('users')
->where('name', 'John')
->unset('note');
$user->unset('note');
``` ```
### Relations Relationships
-------------
Supported relations are: ### Basic Usage
The only available relationships are:
- hasOne - hasOne
- hasMany - hasMany
- belongsTo - belongsTo
- belongsToMany - belongsToMany
The MongoDB-specific relationships are:
- embedsOne - embedsOne
- embedsMany - embedsMany
Example: Here is a small example:
```php ```php
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model;
class User extends Eloquent {
class User extends Model
{
public function items() public function items()
{ {
return $this->hasMany('Item'); return $this->hasMany(Item::class);
} }
} }
``` ```
And the inverse relation: The inverse relation of `hasMany` is `belongsTo`:
```php ```php
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model;
class Item extends Eloquent {
class Item extends Model
{
public function user() public function user()
{ {
return $this->belongsTo('User'); return $this->belongsTo(User::class);
} }
} }
``` ```
The belongsToMany relation will not use a pivot "table", but will push id's to a __related_ids__ attribute instead. This makes the second parameter for the belongsToMany method useless. If you want to define custom keys for your relation, set it to `null`: ### belongsToMany and pivots
```php The belongsToMany relation will not use a pivot "table" but will push id's to a __related_ids__ attribute instead. This makes the second parameter for the belongsToMany method useless.
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class User extends Eloquent { If you want to define custom keys for your relation, set it to `null`:
```php
use Jenssegers\Mongodb\Eloquent\Mode;
class User extends Model
{
public function groups() public function groups()
{ {
return $this->belongsToMany('Group', null, 'user_ids', 'group_ids'); return $this->belongsToMany(
Group::class, null, 'user_ids', 'group_ids'
);
} }
} }
``` ```
### EmbedsMany Relationship
Other relations are not yet supported, but may be added in the future. Read more about these relations on http://laravel.com/docs/eloquent#relationships If you want to embed models, rather than referencing them, you can use the `embedsMany` relation. This relation is similar to the `hasMany` relation but embeds the models inside the parent object.
### EmbedsMany Relations
If you want to embed models, rather than referencing them, you can use the `embedsMany` relation. This relation is similar to the `hasMany` relation, but embeds the models inside the parent object.
**REMEMBER**: these relations return Eloquent collections, they don't return query builder objects! **REMEMBER**: These relations return Eloquent collections, they don't return query builder objects!
```php ```php
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model;
class User extends Eloquent {
class User extends Model
{
public function books() public function books()
{ {
return $this->embedsMany('Book'); return $this->embedsMany(Book::class);
} }
} }
``` ```
You access the embedded models through the dynamic property: You can access the embedded models through the dynamic property:
```php ```php
$books = User::first()->books; $user = User::first();
foreach ($user->books as $book) {
//
}
``` ```
The inverse relation is auto*magically* available, you don't need to define this reverse relation. The inverse relation is auto*magically* available. You don't need to define this reverse relation.
```php ```php
$book = Book::first();
$user = $book->user; $user = $book->user;
``` ```
Inserting and updating embedded models works similar to the `hasMany` relation: Inserting and updating embedded models works similar to the `hasMany` relation:
```php ```php
$book = new Book(['title' => 'A Game of Thrones']); $book = $user->books()->save(
new Book(['title' => 'A Game of Thrones'])
$user = User::first(); );
$book = $user->books()->save($book);
// or // or
$book = $user->books()->create(['title' => 'A Game of Thrones']) $book =
$user->books()
->create(['title' => 'A Game of Thrones']);
``` ```
You can update embedded models using their `save` method (available since release 2.0.0): You can update embedded models using their `save` method (available since release 2.0.0):
...@@ -817,69 +819,78 @@ You can update embedded models using their `save` method (available since releas ...@@ -817,69 +819,78 @@ You can update embedded models using their `save` method (available since releas
$book = $user->books()->first(); $book = $user->books()->first();
$book->title = 'A Game of Thrones'; $book->title = 'A Game of Thrones';
$book->save(); $book->save();
``` ```
You can remove an embedded model by using the `destroy` method on the relation, or the `delete` method on the model (available since release 2.0.0): You can remove an embedded model by using the `destroy` method on the relation, or the `delete` method on the model (available since release 2.0.0):
```php ```php
$book = $user->books()->first();
$book->delete(); $book->delete();
// or
// Similar operation
$user->books()->destroy($book); $user->books()->destroy($book);
``` ```
If you want to add or remove an embedded model, without touching the database, you can use the `associate` and `dissociate` methods. To eventually write the changes to the database, save the parent object: If you want to add or remove an embedded model, without touching the database, you can use the `associate` and `dissociate` methods.
To eventually write the changes to the database, save the parent object:
```php ```php
$user->books()->associate($book); $user->books()->associate($book);
$user->save(); $user->save();
``` ```
Like other relations, embedsMany assumes the local key of the relationship based on the model name. You can override the default local key by passing a second argument to the embedsMany method: Like other relations, embedsMany assumes the local key of the relationship based on the model name. You can override the default local key by passing a second argument to the embedsMany method:
```php ```php
return $this->embedsMany('Book', 'local_key'); use Jenssegers\Mongodb\Eloquent\Model;
class User extends Model
{
public function books()
{
return $this->embedsMany(Book::class, 'local_key');
}
}
``` ```
Embedded relations will return a Collection of embedded items instead of a query builder. Check out the available operations here: https://laravel.com/docs/master/collections Embedded relations will return a Collection of embedded items instead of a query builder. Check out the available operations here: https://laravel.com/docs/master/collections
### EmbedsOne Relations
The embedsOne relation is similar to the EmbedsMany relation, but only embeds a single model. ### EmbedsOne Relationship
```php The embedsOne relation is similar to the embedsMany relation, but only embeds a single model.
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Book extends Eloquent { ```php
use Jenssegers\Mongodb\Eloquent\Model;
class Book extends Model
{
public function author() public function author()
{ {
return $this->embedsOne('Author'); return $this->embedsOne(Author::class);
} }
} }
``` ```
You access the embedded models through the dynamic property: You can access the embedded models through the dynamic property:
```php ```php
$author = Book::first()->author; $book = Book::first();
$author = $book->author;
``` ```
Inserting and updating embedded models works similar to the `hasOne` relation: Inserting and updating embedded models works similar to the `hasOne` relation:
```php ```php
$author = new Author(['name' => 'John Doe']); $author = $book->author()->save(
new Author(['name' => 'John Doe'])
$book = Books::first(); );
$author = $book->author()->save($author); // Similar
// or $author =
$author = $book->author()->create(['name' => 'John Doe']); $book->author()
->create(['name' => 'John Doe']);
``` ```
You can update the embedded model using the `save` method (available since release 2.0.0): You can update the embedded model using the `save` method (available since release 2.0.0):
...@@ -895,178 +906,231 @@ You can replace the embedded model with a new model like this: ...@@ -895,178 +906,231 @@ You can replace the embedded model with a new model like this:
```php ```php
$newAuthor = new Author(['name' => 'Jane Doe']); $newAuthor = new Author(['name' => 'Jane Doe']);
$book->author()->save($newAuthor); $book->author()->save($newAuthor);
``` ```
### MySQL Relations Query Builder
-------------
### Basic Usage
The database driver plugs right into the original query builder.
When using MongoDB connections, you will be able to build fluent queries to perform database operations.
If you're using a hybrid MongoDB and SQL setup, you're in luck! The model will automatically return a MongoDB- or SQL-relation based on the type of the related model. Of course, if you want this functionality to work both ways, your SQL-models will need use the `Jenssegers\Mongodb\Eloquent\HybridRelations` trait. Note that this functionality only works for hasOne, hasMany and belongsTo relations. For your convenience, there is a `collection` alias for `table` as well as some additional MongoDB specific operators/operations.
Example SQL-based User model:
```php ```php
use Jenssegers\Mongodb\Eloquent\HybridRelations; $books = DB::collection('books')->get();
class User extends Eloquent { $hungerGames =
DB::collection('books')
->where('name', 'Hunger Games')
->first();
```
use HybridRelations; If you are familiar with [Eloquent Queries](http://laravel.com/docs/queries), there is the same functionality.
protected $connection = 'mysql'; ### Available operations
To see the available operations, check the [Eloquent](#eloquent) section.
public function messages() Schema
{ ------
return $this->hasMany('Message'); The database driver also has (limited) schema builder support. You can easily manipulate collections and set indexes.
}
} ### Basic Usage
```php
Schema::create('users', function ($collection) {
$collection->index('name');
$collection->unique('email');
});
``` ```
And the Mongodb-based Message model: You can also pass all the parameters specified [in the MongoDB docs](https://docs.mongodb.com/manual/reference/method/db.collection.createIndex/#options-for-all-index-types) to the `$options` parameter:
```php ```php
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; Schema::create('users', function ($collection) {
$collection->index(
'username',
null,
null,
[
'sparse' => true,
'unique' => true,
'background' => true,
]
);
});
```
class Message extends Eloquent { Inherited operations:
- create and drop
- collection
- hasCollection
- index and dropIndex (compound indexes supported as well)
- unique
protected $connection = 'mongodb'; MongoDB specific operations:
- background
- sparse
- expire
- geospatial
public function user() All other (unsupported) operations are implemented as dummy pass-through methods because MongoDB does not use a predefined schema.
{
return $this->belongsTo('User');
}
} Read more about the schema builder on [Laravel Docs](https://laravel.com/docs/6.0/migrations#tables)
```
### Raw Expressions ### Geospatial indexes
These expressions will be injected directly into the query. Geospatial indexes are handy for querying location-based documents.
They come in two forms: `2d` and `2dsphere`. Use the schema builder to add these to a collection.
```php ```php
User::whereRaw(['age' => array('$gt' => 30, '$lt' => 40)])->get(); Schema::create('bars', function ($collection) {
$collection->geospatial('location', '2d');
});
``` ```
You can also perform raw expressions on the internal MongoCollection object. If this is executed on the model class, it will return a collection of models. If this is executed on the query builder, it will return the original response. To add a `2dsphere` index:
```php ```php
// Returns a collection of User models. Schema::create('bars', function ($collection) {
$models = User::raw(function($collection) $collection->geospatial('location', '2dsphere');
{
return $collection->find();
});
// Returns the original MongoCursor.
$cursor = DB::collection('users')->raw(function($collection)
{
return $collection->find();
}); });
``` ```
Optional: if you don't pass a closure to the raw method, the internal MongoCollection object will be accessible: Extending
---------
```php ### Cross-Database Relationships
$model = User::raw()->findOne(['age' => array('$lt' => 18)]);
```
The internal MongoClient and MongoDB objects can be accessed like this: If you're using a hybrid MongoDB and SQL setup, you can define relationships across them.
```php The model will automatically return a MongoDB-related or SQL-related relation based on the type of the related model.
$client = DB::getMongoClient();
$db = DB::getMongoDB();
```
### MongoDB specific operations If you want this functionality to work both ways, your SQL-models will need to use the `Jenssegers\Mongodb\Eloquent\HybridRelations` trait.
**Cursor timeout** **This functionality only works for `hasOne`, `hasMany` and `belongsTo`.**
To prevent MongoCursorTimeout exceptions, you can manually set a timeout value that will be applied to the cursor: The MySQL model should use the `HybridRelations` trait:
```php ```php
DB::collection('users')->timeout(-1)->get(); use Jenssegers\Mongodb\Eloquent\HybridRelations;
```
**Upsert** class User extends Model
{
use HybridRelations;
Update or insert a document. Additional options for the update method are passed directly to the native update method. protected $connection = 'mysql';
```php public function messages()
DB::collection('users')->where('name', 'John') {
->update($data, ['upsert' => true]); return $this->hasMany(Message::class);
}
}
``` ```
Within your MongoDB model, you should define the relationship:
**Projections** ```php
use Jenssegers\Mongodb\Eloquent\Model;
You can apply projections to your queries using the `project` method. class Message extends Model
{
protected $connection = 'mongodb';
```php public function user()
DB::collection('items')->project(['tags' => ['$slice' => 1]])->get(); {
DB::collection('items')->project(['tags' => ['$slice' => [3, 7]]])->get(); return $this->belongsTo(User::class);
}
}
``` ```
**Projections with Pagination** ### Authentication
If you want to use Laravel's native Auth functionality, register this included service provider:
```php ```php
$limit = 25; Jenssegers\Mongodb\Auth\PasswordResetServiceProvider::class,
$projections = ['id', 'name'];
DB::collection('items')->paginate($limit, $projections);
``` ```
This service provider will slightly modify the internal DatabaseReminderRepository to add support for MongoDB based password reminders.
**Push** If you don't use password reminders, you don't have to register this service provider and everything else should work just fine.
Add an items to an array. ### Queues
If you want to use MongoDB as your database backend, change the driver in `config/queue.php`:
```php ```php
DB::collection('users')->where('name', 'John')->push('items', 'boots'); 'connections' => [
DB::collection('users')->where('name', 'John')->push('messages', ['from' => 'Jane Doe', 'message' => 'Hi John']); 'database' => [
'driver' => 'mongodb',
'table' => 'jobs',
'queue' => 'default',
'expire' => 60,
],
],
``` ```
If you don't want duplicate items, set the third parameter to `true`: If you want to use MongoDB to handle failed jobs, change the database in `config/queue.php`:
```php ```php
DB::collection('users')->where('name', 'John')->push('items', 'boots', true); 'failed' => [
'driver' => env('QUEUE_FAILED_DRIVER', 'database'),
'database' => env('DB_CONNECTION', 'mongodb'),
'table' => 'failed_jobs',
],
``` ```
**Pull** Or simply set your own `QUEUE_FAILED_DRIVER` environment variable to `mongodb`
```env
QUEUE_FAILED_DRIVER=mongodb
```
Remove an item from an array. Last, add the service provider in `config/app.php`:
```php ```php
DB::collection('users')->where('name', 'John')->pull('items', 'boots'); Jenssegers\Mongodb\MongodbQueueServiceProvider::class,
DB::collection('users')->where('name', 'John')->pull('messages', ['from' => 'Jane Doe', 'message' => 'Hi John']);
``` ```
**Unset** Upgrading
---------
Remove one or more fields from a document. #### Upgrading from version 2 to 3
```php In this new major release which supports the new MongoDB PHP extension, we also moved the location of the Model class and replaced the MySQL model class with a trait.
DB::collection('users')->where('name', 'John')->unset('note');
```
You can also perform an unset on a model. Please change all `Jenssegers\Mongodb\Model` references to `Jenssegers\Mongodb\Eloquent\Model` either at the top of your model files or your registered alias.
```php ```php
$user = User::where('name', 'John')->first(); use Jenssegers\Mongodb\Eloquent\Model;
$user->unset('note');
class User extends Model
{
//
}
``` ```
### Query Caching If you are using hybrid relations, your MySQL classes should now extend the original Eloquent model class `Illuminate\Database\Eloquent\Model` instead of the removed `Jenssegers\Eloquent\Model`.
You may easily cache the results of a query using the remember method: Instead use the new `Jenssegers\Mongodb\Eloquent\HybridRelations` trait. This should make things more clear as there is only one single model class in this package.
```php ```php
$users = User::remember(10)->get(); use Jenssegers\Mongodb\Eloquent\HybridRelations;
```
class User extends Model
{
*From: http://laravel.com/docs/queries#caching-queries* use HybridRelations;
### Query Logging protected $connection = 'mysql';
}
```
By default, Laravel keeps a log in memory of all queries that have been run for the current request. However, in some cases, such as when inserting a large number of rows, this can cause the application to use excess memory. To disable the log, you may use the `disableQueryLog` method: Embedded relations now return an `Illuminate\Database\Eloquent\Collection` rather than a custom Collection class. If you were using one of the special methods that were available, convert them to Collection operations.
```php ```php
DB::connection()->disableQueryLog(); $books = $user->books()->sortBy('title')->get();
``` ```
*From: http://laravel.com/docs/database#query-logging*
{ {
"name": "jenssegers/mongodb", "name": "jenssegers/mongodb",
"description": "A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)", "description": "A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)",
"keywords": ["laravel","eloquent","mongodb","mongo","database","model","moloquent"], "keywords": [
"homepage": "https://github.com/jenssegers/laravel-mongodb", "laravel",
"authors": [ "eloquent",
{ "mongodb",
"name": "Jens Segers", "mongo",
"homepage": "https://jenssegers.com" "database",
} "model",
], "moloquent"
"license" : "MIT", ],
"require": { "homepage": "https://github.com/jenssegers/laravel-mongodb",
"illuminate/support": "^5.6", "authors": [
"illuminate/container": "^5.6", {
"illuminate/database": "^5.6", "name": "Jens Segers",
"illuminate/events": "^5.6", "homepage": "https://jenssegers.com"
"mongodb/mongodb": "^1.0.0" }
}, ],
"require-dev": { "license": "MIT",
"phpunit/phpunit": "^6.0|^7.0", "require": {
"orchestra/testbench": "^3.1", "illuminate/support": "^5.8|^6.0",
"mockery/mockery": "^1.0", "illuminate/container": "^5.8|^6.0",
"satooshi/php-coveralls": "^2.0", "illuminate/database": "^5.8|^6.0",
"doctrine/dbal": "^2.5" "illuminate/events": "^5.8|^6.0",
}, "mongodb/mongodb": "^1.4",
"autoload": { "cedx/coveralls": "^11.2"
"psr-0": { },
"Jenssegers\\Mongodb": "src/" "require-dev": {
} "phpunit/phpunit": "^6.0|^7.0|^8.0",
}, "orchestra/testbench": "^3.1|^4.0",
"autoload-dev": { "mockery/mockery": "^1.0",
"classmap": [ "doctrine/dbal": "^2.5",
"tests/TestCase.php", "phpunit/phpcov": "^6.0"
"tests/models", },
"tests/seeds" "autoload": {
] "psr-0": {
}, "Jenssegers\\Mongodb": "src/"
"suggest": { }
"jenssegers/mongodb-session": "Add MongoDB session support to Laravel-MongoDB", },
"jenssegers/mongodb-sentry": "Add Sentry support to Laravel-MongoDB" "autoload-dev": {
}, "classmap": [
"extra": { "tests/TestCase.php",
"laravel": { "tests/models",
"providers": [ "tests/seeds"
"Jenssegers\\Mongodb\\MongodbServiceProvider", ]
"Jenssegers\\Mongodb\\MongodbQueueServiceProvider" },
] "suggest": {
} "jenssegers/mongodb-session": "Add MongoDB session support to Laravel-MongoDB",
} "jenssegers/mongodb-sentry": "Add Sentry support to Laravel-MongoDB"
} },
"extra": {
"laravel": {
"providers": [
"Jenssegers\\Mongodb\\MongodbServiceProvider",
"Jenssegers\\Mongodb\\MongodbQueueServiceProvider"
]
}
}
}
version: '3' version: '3'
services: services:
tests:
php: container_name: tests
container_name: php
build: build:
context: . context: .
dockerfile: docker/Dockerfile dockerfile: Dockerfile
volumes: volumes:
- .:/code - .:/code
working_dir: /code working_dir: /code
command: docker/entrypoint.sh
depends_on: depends_on:
- mysql
- mongodb - mongodb
- mysql
mysql: mysql:
container_name: mysql container_name: mysql
image: mysql image: mysql:5.7
environment: environment:
MYSQL_ROOT_PASSWORD: MYSQL_ROOT_PASSWORD:
MYSQL_DATABASE: unittest MYSQL_DATABASE: unittest
...@@ -28,5 +26,7 @@ services: ...@@ -28,5 +26,7 @@ services:
mongodb: mongodb:
container_name: mongodb container_name: mongodb
image: mongo image: mongo
ports:
- 27017:27017
logging: logging:
driver: none driver: none
FROM php:7.1-cli
RUN pecl install xdebug
RUN apt-get update && \
apt-get install -y autoconf pkg-config libssl-dev git && \
pecl install mongodb git zlib1g-dev && docker-php-ext-enable mongodb && \
docker-php-ext-install -j$(nproc) pdo pdo_mysql zip && docker-php-ext-enable xdebug
RUN curl -sS https://getcomposer.org/installer | php \
&& mv composer.phar /usr/local/bin/ \
&& ln -s /usr/local/bin/composer.phar /usr/local/bin/composer
ENV PATH="~/.composer/vendor/bin:./vendor/bin:${PATH}"
\ No newline at end of file
#!/usr/bin/env bash
sleep 3 && composer install --prefer-source --no-interaction && php ./vendor/bin/phpunit
...@@ -7,42 +7,52 @@ ...@@ -7,42 +7,52 @@
convertNoticesToExceptions="true" convertNoticesToExceptions="true"
convertWarningsToExceptions="true" convertWarningsToExceptions="true"
processIsolation="false" processIsolation="false"
stopOnFailure="false" stopOnFailure="false">
syntaxCheck="false"
verbose="true"
>
<testsuites> <testsuites>
<testsuite name="all"> <testsuite name="all">
<directory>tests/</directory> <directory>tests/</directory>
<exclude>tests/MysqlRelationsTest.php</exclude>
</testsuite> </testsuite>
<testsuite name="schema"> <testsuite name="schema">
<directory>tests/SchemaTest.php</directory> <file>tests/SchemaTest.php</file>
</testsuite> </testsuite>
<testsuite name="seeder"> <testsuite name="seeder">
<directory>tests/SeederTest.php</directory> <file>tests/SeederTest.php</file>
</testsuite> </testsuite>
<testsuite name="cache"> <testsuite name="cache">
<directory>tests/CacheTest.php</directory> <file>tests/CacheTest.php</file>
</testsuite> </testsuite>
<testsuite name="builder"> <testsuite name="builder">
<directory>tests/QueryBuilderTest.php</directory> <file>tests/QueryBuilderTest.php</file>
<directory>tests/QueryTest.php</directory> <file>tests/QueryTest.php</file>
</testsuite> </testsuite>
<testsuite name="model"> <testsuite name="model">
<directory>tests/ModelTest.php</directory> <file>tests/ModelTest.php</file>
<directory>tests/RelationsTest.php</directory> <file>tests/RelationsTest.php</file>
</testsuite> </testsuite>
<testsuite name="relations"> <testsuite name="relations">
<directory>tests/RelationsTest.php</directory> <file>tests/RelationsTest.php</file>
<directory>tests/EmbeddedRelationsTest.php</directory> <file>tests/EmbeddedRelationsTest.php</file>
</testsuite> </testsuite>
<testsuite name="mysqlrelations"> <testsuite name="mysqlrelations">
<directory>tests/RelationsTest.php</directory> <file>tests/RelationsTest.php</file>
<directory>tests/MysqlRelationsTest.php</directory>
</testsuite> </testsuite>
<testsuite name="validation"> <testsuite name="validation">
<directory>tests/ValidationTest.php</directory> <file>tests/ValidationTest.php</file>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./src</directory>
</whitelist>
</filter>
<php>
<env name="MONGO_HOST" value="mongodb"/>
<env name="MONGO_DATABASE" value="unittest"/>
<env name="MONGO_PORT" value="27017"/>
<env name="MYSQL_HOST" value="mysql"/>
<env name="MYSQL_PORT" value="3306"/>
<env name="MYSQL_DATABASE" value="unittest"/>
<env name="MYSQL_USERNAME" value="root"/>
<env name="QUEUE_CONNECTION" value="database"/>
</php>
</phpunit> </phpunit>
...@@ -14,25 +14,46 @@ class DatabaseTokenRepository extends BaseDatabaseTokenRepository ...@@ -14,25 +14,46 @@ class DatabaseTokenRepository extends BaseDatabaseTokenRepository
*/ */
protected function getPayload($email, $token) protected function getPayload($email, $token)
{ {
return ['email' => $email, 'token' => $token, 'created_at' => new UTCDateTime(time() * 1000)]; return [
'email' => $email,
'token' => $this->hasher->make($token),
'created_at' => new UTCDateTime(time() * 1000),
];
} }
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected function tokenExpired($token) protected function tokenExpired($createdAt)
{
$createdAt = $this->convertDateTime($createdAt);
return parent::tokenExpired($createdAt);
}
/**
* @inheritdoc
*/
protected function tokenRecentlyCreated($createdAt)
{
$createdAt = $this->convertDateTime($createdAt);
return parent::tokenRecentlyCreated($createdAt);
}
private function convertDateTime($createdAt)
{ {
// Convert UTCDateTime to a date string. // Convert UTCDateTime to a date string.
if ($token['created_at'] instanceof UTCDateTime) { if ($createdAt instanceof UTCDateTime) {
$date = $token['created_at']->toDateTime(); $date = $createdAt->toDateTime();
$date->setTimezone(new DateTimeZone(date_default_timezone_get())); $date->setTimezone(new DateTimeZone(date_default_timezone_get()));
$token['created_at'] = $date->format('Y-m-d H:i:s'); $createdAt = $date->format('Y-m-d H:i:s');
} elseif (is_array($token['created_at']) && isset($token['created_at']['date'])) { } elseif (is_array($createdAt) && isset($createdAt['date'])) {
$date = new DateTime($token['created_at']['date'], new DateTimeZone(isset($token['created_at']['timezone']) ? $token['created_at']['timezone'] : 'UTC')); $date = new DateTime($createdAt['date'], new DateTimeZone(isset($createdAt['timezone']) ? $createdAt['timezone'] : 'UTC'));
$date->setTimezone(new DateTimeZone(date_default_timezone_get())); $date->setTimezone(new DateTimeZone(date_default_timezone_get()));
$token['created_at'] = $date->format('Y-m-d H:i:s'); $createdAt = $date->format('Y-m-d H:i:s');
} }
return parent::tokenExpired($token); return $createdAt;
} }
} }
...@@ -11,23 +11,12 @@ class PasswordBrokerManager extends BasePasswordBrokerManager ...@@ -11,23 +11,12 @@ class PasswordBrokerManager extends BasePasswordBrokerManager
*/ */
protected function createTokenRepository(array $config) protected function createTokenRepository(array $config)
{ {
$laravel = app(); return new DatabaseTokenRepository(
$this->app['db']->connection(),
if (version_compare($laravel::VERSION, '5.4', '>=')) { $this->app['hash'],
return new DatabaseTokenRepository( $config['table'],
$this->app['db']->connection(), $this->app['config']['app.key'],
$this->app['hash'], $config['expire']
$config['table'], );
$this->app['config']['app.key'],
$config['expire']
);
} else {
return new DatabaseTokenRepository(
$this->app['db']->connection(),
$config['table'],
$this->app['config']['app.key'],
$config['expire']
);
}
} }
} }
...@@ -8,7 +8,6 @@ class PasswordResetServiceProvider extends BasePasswordResetServiceProvider ...@@ -8,7 +8,6 @@ class PasswordResetServiceProvider extends BasePasswordResetServiceProvider
{ {
/** /**
* Register the token repository implementation. * Register the token repository implementation.
*
* @return void * @return void
*/ */
protected function registerTokenRepository() protected function registerTokenRepository()
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace Jenssegers\Mongodb\Auth; namespace Jenssegers\Mongodb\Auth;
use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\MustVerifyEmail;
use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
...@@ -15,5 +16,5 @@ class User extends Model implements ...@@ -15,5 +16,5 @@ class User extends Model implements
AuthorizableContract, AuthorizableContract,
CanResetPasswordContract CanResetPasswordContract
{ {
use Authenticatable, Authorizable, CanResetPassword; use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
} }
...@@ -10,14 +10,12 @@ class Collection ...@@ -10,14 +10,12 @@ class Collection
{ {
/** /**
* The connection instance. * The connection instance.
*
* @var Connection * @var Connection
*/ */
protected $connection; protected $connection;
/** /**
* The MongoCollection instance.. * The MongoCollection instance..
*
* @var MongoCollection * @var MongoCollection
*/ */
protected $collection; protected $collection;
...@@ -34,9 +32,8 @@ class Collection ...@@ -34,9 +32,8 @@ class Collection
/** /**
* Handle dynamic method calls. * Handle dynamic method calls.
* * @param string $method
* @param string $method * @param array $parameters
* @param array $parameters
* @return mixed * @return mixed
*/ */
public function __call($method, $parameters) public function __call($method, $parameters)
......
...@@ -10,22 +10,19 @@ class Connection extends BaseConnection ...@@ -10,22 +10,19 @@ class Connection extends BaseConnection
{ {
/** /**
* The MongoDB database handler. * The MongoDB database handler.
*
* @var \MongoDB\Database * @var \MongoDB\Database
*/ */
protected $db; protected $db;
/** /**
* The MongoDB connection handler. * The MongoDB connection handler.
*
* @var \MongoDB\Client * @var \MongoDB\Client
*/ */
protected $connection; protected $connection;
/** /**
* Create a new database connection instance. * Create a new database connection instance.
* * @param array $config
* @param array $config
*/ */
public function __construct(array $config) public function __construct(array $config)
{ {
...@@ -52,8 +49,7 @@ class Connection extends BaseConnection ...@@ -52,8 +49,7 @@ class Connection extends BaseConnection
/** /**
* Begin a fluent query against a database collection. * Begin a fluent query against a database collection.
* * @param string $collection
* @param string $collection
* @return Query\Builder * @return Query\Builder
*/ */
public function collection($collection) public function collection($collection)
...@@ -65,19 +61,18 @@ class Connection extends BaseConnection ...@@ -65,19 +61,18 @@ class Connection extends BaseConnection
/** /**
* Begin a fluent query against a database collection. * Begin a fluent query against a database collection.
* * @param string $table
* @param string $table * @param string|null $as
* @return Query\Builder * @return Query\Builder
*/ */
public function table($table) public function table($table, $as = null)
{ {
return $this->collection($table); return $this->collection($table);
} }
/** /**
* Get a MongoDB collection. * Get a MongoDB collection.
* * @param string $name
* @param string $name
* @return Collection * @return Collection
*/ */
public function getCollection($name) public function getCollection($name)
...@@ -95,7 +90,6 @@ class Connection extends BaseConnection ...@@ -95,7 +90,6 @@ class Connection extends BaseConnection
/** /**
* Get the MongoDB database object. * Get the MongoDB database object.
*
* @return \MongoDB\Database * @return \MongoDB\Database
*/ */
public function getMongoDB() public function getMongoDB()
...@@ -105,7 +99,6 @@ class Connection extends BaseConnection ...@@ -105,7 +99,6 @@ class Connection extends BaseConnection
/** /**
* return MongoDB object. * return MongoDB object.
*
* @return \MongoDB\Client * @return \MongoDB\Client
*/ */
public function getMongoClient() public function getMongoClient()
...@@ -113,12 +106,19 @@ class Connection extends BaseConnection ...@@ -113,12 +106,19 @@ class Connection extends BaseConnection
return $this->connection; return $this->connection;
} }
/**
* {@inheritdoc}
*/
public function getDatabaseName()
{
return $this->getMongoDB()->getDatabaseName();
}
/** /**
* Create a new MongoDB connection. * Create a new MongoDB connection.
* * @param string $dsn
* @param string $dsn * @param array $config
* @param array $config * @param array $options
* @param array $options
* @return \MongoDB\Client * @return \MongoDB\Client
*/ */
protected function createConnection($dsn, array $config, array $options) protected function createConnection($dsn, array $config, array $options)
...@@ -151,19 +151,17 @@ class Connection extends BaseConnection ...@@ -151,19 +151,17 @@ class Connection extends BaseConnection
/** /**
* Determine if the given configuration array has a dsn string. * Determine if the given configuration array has a dsn string.
* * @param array $config
* @param array $config
* @return bool * @return bool
*/ */
protected function hasDsnString(array $config) protected function hasDsnString(array $config)
{ {
return isset($config['dsn']) && ! empty($config['dsn']); return isset($config['dsn']) && !empty($config['dsn']);
} }
/** /**
* Get the DSN string form configuration. * Get the DSN string form configuration.
* * @param array $config
* @param array $config
* @return string * @return string
*/ */
protected function getDsnString(array $config) protected function getDsnString(array $config)
...@@ -173,8 +171,7 @@ class Connection extends BaseConnection ...@@ -173,8 +171,7 @@ class Connection extends BaseConnection
/** /**
* Get the DSN string for a host / port configuration. * Get the DSN string for a host / port configuration.
* * @param array $config
* @param array $config
* @return string * @return string
*/ */
protected function getHostDsn(array $config) protected function getHostDsn(array $config)
...@@ -208,8 +205,7 @@ class Connection extends BaseConnection ...@@ -208,8 +205,7 @@ class Connection extends BaseConnection
/** /**
* Create a DSN string from a configuration. * Create a DSN string from a configuration.
* * @param array $config
* @param array $config
* @return string * @return string
*/ */
protected function getDsn(array $config) protected function getDsn(array $config)
...@@ -261,9 +257,8 @@ class Connection extends BaseConnection ...@@ -261,9 +257,8 @@ class Connection extends BaseConnection
/** /**
* Dynamically pass methods to the connection. * Dynamically pass methods to the connection.
* * @param string $method
* @param string $method * @param array $parameters
* @param array $parameters
* @return mixed * @return mixed
*/ */
public function __call($method, $parameters) public function __call($method, $parameters)
......
...@@ -13,7 +13,6 @@ class Builder extends EloquentBuilder ...@@ -13,7 +13,6 @@ class Builder extends EloquentBuilder
/** /**
* The methods that should be returned from query builder. * The methods that should be returned from query builder.
*
* @var array * @var array
*/ */
protected $passthru = [ protected $passthru = [
...@@ -44,7 +43,7 @@ class Builder extends EloquentBuilder ...@@ -44,7 +43,7 @@ class Builder extends EloquentBuilder
return 1; return 1;
} }
return $this->query->update($this->addUpdatedAtColumn($values), $options); return $this->toBase()->update($this->addUpdatedAtColumn($values), $options);
} }
/** /**
...@@ -177,6 +176,29 @@ class Builder extends EloquentBuilder ...@@ -177,6 +176,29 @@ class Builder extends EloquentBuilder
return $results; return $results;
} }
/**
* Add the "updated at" column to an array of values.
* TODO Remove if https://github.com/laravel/framework/commit/6484744326531829341e1ff886cc9b628b20d73e
* wiil be reverted
* Issue in laravel frawework https://github.com/laravel/framework/issues/27791
* @param array $values
* @return array
*/
protected function addUpdatedAtColumn(array $values)
{
if (!$this->model->usesTimestamps() || $this->model->getUpdatedAtColumn() === null) {
return $values;
}
$column = $this->model->getUpdatedAtColumn();
$values = array_merge(
[$column => $this->model->freshTimestampString()],
$values
);
return $values;
}
/** /**
* @return \Illuminate\Database\ConnectionInterface * @return \Illuminate\Database\ConnectionInterface
*/ */
......
...@@ -10,11 +10,10 @@ trait EmbedsRelations ...@@ -10,11 +10,10 @@ trait EmbedsRelations
{ {
/** /**
* Define an embedded one-to-many relationship. * Define an embedded one-to-many relationship.
* * @param string $related
* @param string $related * @param string $localKey
* @param string $localKey * @param string $foreignKey
* @param string $foreignKey * @param string $relation
* @param string $relation
* @return \Jenssegers\Mongodb\Relations\EmbedsMany * @return \Jenssegers\Mongodb\Relations\EmbedsMany
*/ */
protected function embedsMany($related, $localKey = null, $foreignKey = null, $relation = null) protected function embedsMany($related, $localKey = null, $foreignKey = null, $relation = null)
...@@ -22,17 +21,17 @@ trait EmbedsRelations ...@@ -22,17 +21,17 @@ trait EmbedsRelations
// If no relation name was given, we will use this debug backtrace to extract // 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 // 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. // of the time this will be what we desire to use for the relationships.
if (is_null($relation)) { if ($relation === null) {
list(, $caller) = debug_backtrace(false); list(, $caller) = debug_backtrace(false);
$relation = $caller['function']; $relation = $caller['function'];
} }
if (is_null($localKey)) { if ($localKey === null) {
$localKey = $relation; $localKey = $relation;
} }
if (is_null($foreignKey)) { if ($foreignKey === null) {
$foreignKey = Str::snake(class_basename($this)); $foreignKey = Str::snake(class_basename($this));
} }
...@@ -45,11 +44,10 @@ trait EmbedsRelations ...@@ -45,11 +44,10 @@ trait EmbedsRelations
/** /**
* Define an embedded one-to-many relationship. * Define an embedded one-to-many relationship.
* * @param string $related
* @param string $related * @param string $localKey
* @param string $localKey * @param string $foreignKey
* @param string $foreignKey * @param string $relation
* @param string $relation
* @return \Jenssegers\Mongodb\Relations\EmbedsOne * @return \Jenssegers\Mongodb\Relations\EmbedsOne
*/ */
protected function embedsOne($related, $localKey = null, $foreignKey = null, $relation = null) protected function embedsOne($related, $localKey = null, $foreignKey = null, $relation = null)
...@@ -57,17 +55,17 @@ trait EmbedsRelations ...@@ -57,17 +55,17 @@ trait EmbedsRelations
// If no relation name was given, we will use this debug backtrace to extract // 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 // 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. // of the time this will be what we desire to use for the relationships.
if (is_null($relation)) { if ($relation === null) {
list(, $caller) = debug_backtrace(false); list(, $caller) = debug_backtrace(false);
$relation = $caller['function']; $relation = $caller['function'];
} }
if (is_null($localKey)) { if ($localKey === null) {
$localKey = $relation; $localKey = $relation;
} }
if (is_null($foreignKey)) { if ($foreignKey === null) {
$foreignKey = Str::snake(class_basename($this)); $foreignKey = Str::snake(class_basename($this));
} }
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
namespace Jenssegers\Mongodb\Eloquent; namespace Jenssegers\Mongodb\Eloquent;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne; use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Jenssegers\Mongodb\Helpers\EloquentBuilder; use Jenssegers\Mongodb\Helpers\EloquentBuilder;
...@@ -11,15 +10,15 @@ use Jenssegers\Mongodb\Relations\BelongsToMany; ...@@ -11,15 +10,15 @@ use Jenssegers\Mongodb\Relations\BelongsToMany;
use Jenssegers\Mongodb\Relations\HasMany; use Jenssegers\Mongodb\Relations\HasMany;
use Jenssegers\Mongodb\Relations\HasOne; use Jenssegers\Mongodb\Relations\HasOne;
use Jenssegers\Mongodb\Relations\MorphTo; use Jenssegers\Mongodb\Relations\MorphTo;
use Jenssegers\Mongodb\Relations\MorphMany;
trait HybridRelations trait HybridRelations
{ {
/** /**
* Define a one-to-one relationship. * Define a one-to-one relationship.
* * @param string $related
* @param string $related * @param string $foreignKey
* @param string $foreignKey * @param string $localKey
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\HasOne * @return \Illuminate\Database\Eloquent\Relations\HasOne
*/ */
public function hasOne($related, $foreignKey = null, $localKey = null) public function hasOne($related, $foreignKey = null, $localKey = null)
...@@ -40,12 +39,11 @@ trait HybridRelations ...@@ -40,12 +39,11 @@ trait HybridRelations
/** /**
* Define a polymorphic one-to-one relationship. * Define a polymorphic one-to-one relationship.
* * @param string $related
* @param string $related * @param string $name
* @param string $name * @param string $type
* @param string $type * @param string $id
* @param string $id * @param string $localKey
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\MorphOne * @return \Illuminate\Database\Eloquent\Relations\MorphOne
*/ */
public function morphOne($related, $name, $type = null, $id = null, $localKey = null) public function morphOne($related, $name, $type = null, $id = null, $localKey = null)
...@@ -66,10 +64,9 @@ trait HybridRelations ...@@ -66,10 +64,9 @@ trait HybridRelations
/** /**
* Define a one-to-many relationship. * Define a one-to-many relationship.
* * @param string $related
* @param string $related * @param string $foreignKey
* @param string $foreignKey * @param string $localKey
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\HasMany * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/ */
public function hasMany($related, $foreignKey = null, $localKey = null) public function hasMany($related, $foreignKey = null, $localKey = null)
...@@ -90,12 +87,11 @@ trait HybridRelations ...@@ -90,12 +87,11 @@ trait HybridRelations
/** /**
* Define a polymorphic one-to-many relationship. * Define a polymorphic one-to-many relationship.
* * @param string $related
* @param string $related * @param string $name
* @param string $name * @param string $type
* @param string $type * @param string $id
* @param string $id * @param string $localKey
* @param string $localKey
* @return \Illuminate\Database\Eloquent\Relations\MorphMany * @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/ */
public function morphMany($related, $name, $type = null, $id = null, $localKey = null) public function morphMany($related, $name, $type = null, $id = null, $localKey = null)
...@@ -121,11 +117,10 @@ trait HybridRelations ...@@ -121,11 +117,10 @@ trait HybridRelations
/** /**
* Define an inverse one-to-one or many relationship. * Define an inverse one-to-one or many relationship.
* * @param string $related
* @param string $related * @param string $foreignKey
* @param string $foreignKey * @param string $otherKey
* @param string $otherKey * @param string $relation
* @param string $relation
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/ */
public function belongsTo($related, $foreignKey = null, $otherKey = null, $relation = null) public function belongsTo($related, $foreignKey = null, $otherKey = null, $relation = null)
...@@ -133,7 +128,7 @@ trait HybridRelations ...@@ -133,7 +128,7 @@ trait HybridRelations
// If no relation name was given, we will use this debug backtrace to extract // 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 // 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. // of the time this will be what we desire to use for the relationships.
if (is_null($relation)) { if ($relation === null) {
list($current, $caller) = debug_backtrace(false, 2); list($current, $caller) = debug_backtrace(false, 2);
$relation = $caller['function']; $relation = $caller['function'];
...@@ -147,7 +142,7 @@ trait HybridRelations ...@@ -147,7 +142,7 @@ trait HybridRelations
// If no foreign key was supplied, we can use a backtrace to guess the proper // 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 // foreign key name by using the name of the relationship function, which
// when combined with an "_id" should conventionally match the columns. // when combined with an "_id" should conventionally match the columns.
if (is_null($foreignKey)) { if ($foreignKey === null) {
$foreignKey = Str::snake($relation) . '_id'; $foreignKey = Str::snake($relation) . '_id';
} }
...@@ -165,11 +160,10 @@ trait HybridRelations ...@@ -165,11 +160,10 @@ trait HybridRelations
/** /**
* Define a polymorphic, inverse one-to-one or many relationship. * Define a polymorphic, inverse one-to-one or many relationship.
* * @param string $name
* @param string $name * @param string $type
* @param string $type * @param string $id
* @param string $id * @param string $ownerKey
* @param string $ownerKey
* @return \Illuminate\Database\Eloquent\Relations\MorphTo * @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/ */
public function morphTo($name = null, $type = null, $id = null, $ownerKey = null) public function morphTo($name = null, $type = null, $id = null, $ownerKey = null)
...@@ -177,7 +171,7 @@ trait HybridRelations ...@@ -177,7 +171,7 @@ trait HybridRelations
// If no name is provided, we will use the backtrace to get the function name // 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 // 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. // use that to get both the class and foreign key that will be utilized.
if (is_null($name)) { if ($name === null) {
list($current, $caller) = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); list($current, $caller) = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$name = Str::snake($caller['function']); $name = Str::snake($caller['function']);
...@@ -188,36 +182,35 @@ trait HybridRelations ...@@ -188,36 +182,35 @@ trait HybridRelations
// If the type value is null it is probably safe to assume we're eager loading // 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 // 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. // there are multiple types in the morph and we can't use single queries.
if (is_null($class = $this->$type)) { if (($class = $this->$type) === null) {
return new MorphTo( return new MorphTo(
$this->newQuery(), $this, $id, null, $type, $name $this->newQuery(), $this, $id, $ownerKey, $type, $name
); );
} }
// If we are not eager loading the relationship we will essentially treat this // 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 // 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. // we will pass in the appropriate values so that it behaves as expected.
else { $class = $this->getActualClassNameForMorph($class);
$class = $this->getActualClassNameForMorph($class);
$instance = new $class; $instance = new $class;
return new MorphTo( $ownerKey = $ownerKey ?? $instance->getKeyName();
$instance->newQuery(), $this, $id, $instance->getKeyName(), $type, $name
); return new MorphTo(
} $instance->newQuery(), $this, $id, $ownerKey, $type, $name
);
} }
/** /**
* Define a many-to-many relationship. * Define a many-to-many relationship.
* * @param string $related
* @param string $related * @param string $collection
* @param string $collection * @param string $foreignKey
* @param string $foreignKey * @param string $otherKey
* @param string $otherKey * @param string $parentKey
* @param string $parentKey * @param string $relatedKey
* @param string $relatedKey * @param string $relation
* @param string $relation
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/ */
public function belongsToMany( public function belongsToMany(
...@@ -232,7 +225,7 @@ trait HybridRelations ...@@ -232,7 +225,7 @@ trait HybridRelations
// If no relationship name was passed, we will pull backtraces to get the // 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 // 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. // title of this relation since that is a great convention to apply.
if (is_null($relation)) { if ($relation === null) {
$relation = $this->guessBelongsToManyRelation(); $relation = $this->guessBelongsToManyRelation();
} }
...@@ -261,7 +254,7 @@ trait HybridRelations ...@@ -261,7 +254,7 @@ trait HybridRelations
// If no table name was provided, we can guess it by concatenating the two // If no table name was provided, we can guess it by concatenating the two
// models using underscores in alphabetical order. The two model names // models using underscores in alphabetical order. The two model names
// are transformed to snake case from their default CamelCase also. // are transformed to snake case from their default CamelCase also.
if (is_null($collection)) { if ($collection === null) {
$collection = $instance->getTable(); $collection = $instance->getTable();
} }
...@@ -284,7 +277,6 @@ trait HybridRelations ...@@ -284,7 +277,6 @@ trait HybridRelations
/** /**
* Get the relationship name of the belongs to many. * Get the relationship name of the belongs to many.
*
* @return string * @return string
*/ */
protected function guessBelongsToManyRelation() protected function guessBelongsToManyRelation()
...@@ -303,8 +295,8 @@ trait HybridRelations ...@@ -303,8 +295,8 @@ trait HybridRelations
{ {
if (is_subclass_of($this, \Jenssegers\Mongodb\Eloquent\Model::class)) { if (is_subclass_of($this, \Jenssegers\Mongodb\Eloquent\Model::class)) {
return new Builder($query); return new Builder($query);
} else {
return new EloquentBuilder($query);
} }
return new EloquentBuilder($query);
} }
} }
...@@ -4,11 +4,14 @@ namespace Jenssegers\Mongodb\Eloquent; ...@@ -4,11 +4,14 @@ namespace Jenssegers\Mongodb\Eloquent;
use Carbon\Carbon; use Carbon\Carbon;
use DateTime; use DateTime;
use Illuminate\Contracts\Queue\QueueableCollection;
use Illuminate\Contracts\Queue\QueueableEntity;
use Illuminate\Database\Eloquent\Model as BaseModel; use Illuminate\Database\Eloquent\Model as BaseModel;
use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Jenssegers\Mongodb\Query\Builder as QueryBuilder; use Jenssegers\Mongodb\Query\Builder as QueryBuilder;
use MongoDB\BSON\Binary;
use MongoDB\BSON\ObjectID; use MongoDB\BSON\ObjectID;
use MongoDB\BSON\UTCDateTime; use MongoDB\BSON\UTCDateTime;
...@@ -18,29 +21,31 @@ abstract class Model extends BaseModel ...@@ -18,29 +21,31 @@ abstract class Model extends BaseModel
/** /**
* The collection associated with the model. * The collection associated with the model.
*
* @var string * @var string
*/ */
protected $collection; protected $collection;
/** /**
* The primary key for the model. * The primary key for the model.
*
* @var string * @var string
*/ */
protected $primaryKey = '_id'; protected $primaryKey = '_id';
/**
* The primary key type.
* @var string
*/
protected $keyType = 'string';
/** /**
* The parent relation instance. * The parent relation instance.
*
* @var Relation * @var Relation
*/ */
protected $parentRelation; protected $parentRelation;
/** /**
* Custom accessor for the model's id. * Custom accessor for the model's id.
* * @param mixed $value
* @param mixed $value
* @return mixed * @return mixed
*/ */
public function getIdAttribute($value = null) public function getIdAttribute($value = null)
...@@ -54,6 +59,8 @@ abstract class Model extends BaseModel ...@@ -54,6 +59,8 @@ abstract class Model extends BaseModel
// Convert ObjectID to string. // Convert ObjectID to string.
if ($value instanceof ObjectID) { if ($value instanceof ObjectID) {
return (string) $value; return (string) $value;
} elseif ($value instanceof Binary) {
return (string) $value->getData();
} }
return $value; return $value;
...@@ -111,7 +118,7 @@ abstract class Model extends BaseModel ...@@ -111,7 +118,7 @@ abstract class Model extends BaseModel
*/ */
public function freshTimestamp() public function freshTimestamp()
{ {
return new UTCDateTime(time() * 1000); return new UTCDateTime(Carbon::now());
} }
/** /**
...@@ -195,6 +202,8 @@ abstract class Model extends BaseModel ...@@ -195,6 +202,8 @@ abstract class Model extends BaseModel
foreach ($attributes as $key => &$value) { foreach ($attributes as $key => &$value) {
if ($value instanceof ObjectID) { if ($value instanceof ObjectID) {
$value = (string) $value; $value = (string) $value;
} elseif ($value instanceof Binary) {
$value = (string) $value->getData();
} }
} }
...@@ -219,7 +228,7 @@ abstract class Model extends BaseModel ...@@ -219,7 +228,7 @@ abstract class Model extends BaseModel
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected function originalIsEquivalent($key, $current) public function originalIsEquivalent($key, $current)
{ {
if (!array_key_exists($key, $this->original)) { if (!array_key_exists($key, $this->original)) {
return false; return false;
...@@ -253,8 +262,7 @@ abstract class Model extends BaseModel ...@@ -253,8 +262,7 @@ abstract class Model extends BaseModel
/** /**
* Remove one or more fields. * Remove one or more fields.
* * @param mixed $columns
* @param mixed $columns
* @return int * @return int
*/ */
public function drop($columns) public function drop($columns)
...@@ -299,9 +307,8 @@ abstract class Model extends BaseModel ...@@ -299,9 +307,8 @@ abstract class Model extends BaseModel
/** /**
* Remove one or more values from an array. * Remove one or more values from an array.
* * @param string $column
* @param string $column * @param mixed $values
* @param mixed $values
* @return mixed * @return mixed
*/ */
public function pull($column, $values) public function pull($column, $values)
...@@ -318,10 +325,9 @@ abstract class Model extends BaseModel ...@@ -318,10 +325,9 @@ abstract class Model extends BaseModel
/** /**
* Append one or more values to the underlying attribute value and sync with original. * Append one or more values to the underlying attribute value and sync with original.
* * @param string $column
* @param string $column * @param array $values
* @param array $values * @param bool $unique
* @param bool $unique
*/ */
protected function pushAttributeValues($column, array $values, $unique = false) protected function pushAttributeValues($column, array $values, $unique = false)
{ {
...@@ -343,9 +349,8 @@ abstract class Model extends BaseModel ...@@ -343,9 +349,8 @@ abstract class Model extends BaseModel
/** /**
* Remove one or more values to the underlying attribute value and sync with original. * Remove one or more values to the underlying attribute value and sync with original.
* * @param string $column
* @param string $column * @param array $values
* @param array $values
*/ */
protected function pullAttributeValues($column, array $values) protected function pullAttributeValues($column, array $values)
{ {
...@@ -376,8 +381,7 @@ abstract class Model extends BaseModel ...@@ -376,8 +381,7 @@ abstract class Model extends BaseModel
/** /**
* Set the parent relation. * Set the parent relation.
* * @param \Illuminate\Database\Eloquent\Relations\Relation $relation
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation
*/ */
public function setParentRelation(Relation $relation) public function setParentRelation(Relation $relation)
{ {
...@@ -386,7 +390,6 @@ abstract class Model extends BaseModel ...@@ -386,7 +390,6 @@ abstract class Model extends BaseModel
/** /**
* Get the parent relation. * Get the parent relation.
*
* @return \Illuminate\Database\Eloquent\Relations\Relation * @return \Illuminate\Database\Eloquent\Relations\Relation
*/ */
public function getParentRelation() public function getParentRelation()
...@@ -420,6 +423,50 @@ abstract class Model extends BaseModel ...@@ -420,6 +423,50 @@ abstract class Model extends BaseModel
return $key; return $key;
} }
/**
* Get the queueable relationships for the entity.
* @return array
*/
public function getQueueableRelations()
{
$relations = [];
foreach ($this->getRelationsWithoutParent() as $key => $relation) {
if (method_exists($this, $key)) {
$relations[] = $key;
}
if ($relation instanceof QueueableCollection) {
foreach ($relation->getQueueableRelations() as $collectionValue) {
$relations[] = $key . '.' . $collectionValue;
}
}
if ($relation instanceof QueueableEntity) {
foreach ($relation->getQueueableRelations() as $entityKey => $entityValue) {
$relations[] = $key . '.' . $entityValue;
}
}
}
return array_unique($relations);
}
/**
* Get loaded relations for the instance without parent.
* @return array
*/
protected function getRelationsWithoutParent()
{
$relations = $this->getRelations();
if ($parentRelation = $this->getParentRelation()) {
unset($relations[$parentRelation->getQualifiedForeignKeyName()]);
}
return $relations;
}
/** /**
* @inheritdoc * @inheritdoc
*/ */
......
...@@ -3,30 +3,34 @@ ...@@ -3,30 +3,34 @@
namespace Jenssegers\Mongodb\Helpers; namespace Jenssegers\Mongodb\Helpers;
use Closure; use Closure;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasOneOrMany; use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
use Illuminate\Database\Eloquent\Relations\Relation;
use Jenssegers\Mongodb\Eloquent\Model; use Jenssegers\Mongodb\Eloquent\Model;
trait QueriesRelationships trait QueriesRelationships
{ {
/** /**
* Add a relationship count / exists condition to the query. * Add a relationship count / exists condition to the query.
* * @param Relation|string $relation
* @param string $relation * @param string $operator
* @param string $operator * @param int $count
* @param int $count * @param string $boolean
* @param string $boolean * @param Closure|null $callback
* @param \Closure|null $callback * @return Builder|static
* @return \Illuminate\Database\Eloquent\Builder|static
*/ */
public function has($relation, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null) public function has($relation, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null)
{ {
if (strpos($relation, '.') !== false) { if (is_string($relation)) {
return $this->hasNested($relation, $operator, $count, $boolean, $callback); if (strpos($relation, '.') !== false) {
} return $this->hasNested($relation, $operator, $count, $boolean, $callback);
}
$relation = $this->getRelationWithoutConstraints($relation); $relation = $this->getRelationWithoutConstraints($relation);
}
// If this is a hybrid relation then we can not use a normal whereExists() query that relies on a subquery // If this is a hybrid relation then we can not use a normal whereExists() query that relies on a subquery
// We need to use a `whereIn` query // We need to use a `whereIn` query
...@@ -58,25 +62,25 @@ trait QueriesRelationships ...@@ -58,25 +62,25 @@ trait QueriesRelationships
} }
/** /**
* @param $relation * @param Relation $relation
* @return bool * @return bool
*/ */
protected function isAcrossConnections($relation) protected function isAcrossConnections(Relation $relation)
{ {
return $relation->getParent()->getConnectionName() !== $relation->getRelated()->getConnectionName(); return $relation->getParent()->getConnectionName() !== $relation->getRelated()->getConnectionName();
} }
/** /**
* Compare across databases * Compare across databases
* @param $relation * @param Relation $relation
* @param string $operator * @param string $operator
* @param int $count * @param int $count
* @param string $boolean * @param string $boolean
* @param Closure|null $callback * @param Closure|null $callback
* @return mixed * @return mixed
* @throws \Exception * @throws Exception
*/ */
public function addHybridHas($relation, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null) public function addHybridHas(Relation $relation, $operator = '>=', $count = 1, $boolean = 'and', Closure $callback = null)
{ {
$hasQuery = $relation->getQuery(); $hasQuery = $relation->getQuery();
if ($callback) { if ($callback) {
...@@ -98,39 +102,16 @@ trait QueriesRelationships ...@@ -98,39 +102,16 @@ trait QueriesRelationships
} }
/** /**
* Returns key we are constraining this parent model's query with * @param Relation $relation
* @param $relation
* @return string
* @throws \Exception
*/
protected function getRelatedConstraintKey($relation)
{
if ($relation instanceof HasOneOrMany) {
return $this->model->getKeyName();
}
if ($relation instanceof BelongsTo) {
return $relation->getForeignKey();
}
if ($relation instanceof BelongsToMany && ! $this->isAcrossConnections($relation)) {
return $this->model->getKeyName();
}
throw new \Exception(class_basename($relation) . ' is not supported for hybrid query constraints.');
}
/**
* @param $relation
* @return string * @return string
*/ */
protected function getHasCompareKey($relation) protected function getHasCompareKey(Relation $relation)
{ {
if (method_exists($relation, 'getHasCompareKey')) { if (method_exists($relation, 'getHasCompareKey')) {
return $relation->getHasCompareKey(); return $relation->getHasCompareKey();
} }
return $relation instanceof HasOneOrMany ? $relation->getForeignKeyName() : $relation->getOwnerKey(); return $relation instanceof HasOneOrMany ? $relation->getForeignKeyName() : $relation->getOwnerKeyName();
} }
/** /**
...@@ -166,4 +147,27 @@ trait QueriesRelationships ...@@ -166,4 +147,27 @@ trait QueriesRelationships
// All related ids. // All related ids.
return array_keys($relationCount); return array_keys($relationCount);
} }
/**
* Returns key we are constraining this parent model's query with
* @param Relation $relation
* @return string
* @throws Exception
*/
protected function getRelatedConstraintKey(Relation $relation)
{
if ($relation instanceof HasOneOrMany) {
return $relation->getLocalKeyName();
}
if ($relation instanceof BelongsTo) {
return $relation->getForeignKeyName();
}
if ($relation instanceof BelongsToMany && !$this->isAcrossConnections($relation)) {
return $this->model->getKeyName();
}
throw new Exception(class_basename($relation) . ' is not supported for hybrid query constraints.');
}
} }
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Jenssegers\Mongodb; namespace Jenssegers\Mongodb;
use DB;
use Illuminate\Queue\QueueServiceProvider; use Illuminate\Queue\QueueServiceProvider;
use Jenssegers\Mongodb\Queue\Failed\MongoFailedJobProvider; use Jenssegers\Mongodb\Queue\Failed\MongoFailedJobProvider;
...@@ -13,7 +14,7 @@ class MongodbQueueServiceProvider extends QueueServiceProvider ...@@ -13,7 +14,7 @@ class MongodbQueueServiceProvider extends QueueServiceProvider
protected function registerFailedJobServices() protected function registerFailedJobServices()
{ {
// Add compatible queue failer if mongodb is configured. // Add compatible queue failer if mongodb is configured.
if (config('queue.failed.database') == 'mongodb') { if (DB::connection(config('queue.failed.database'))->getDriverName() == 'mongodb') {
$this->app->singleton('queue.failer', function ($app) { $this->app->singleton('queue.failer', function ($app) {
return new MongoFailedJobProvider($app['db'], config('queue.failed.database'), config('queue.failed.table')); return new MongoFailedJobProvider($app['db'], config('queue.failed.database'), config('queue.failed.table'));
}); });
......
...@@ -11,6 +11,7 @@ use Illuminate\Support\Collection; ...@@ -11,6 +11,7 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Jenssegers\Mongodb\Connection; use Jenssegers\Mongodb\Connection;
use MongoCollection; use MongoCollection;
use MongoDB\BSON\Binary;
use MongoDB\BSON\ObjectID; use MongoDB\BSON\ObjectID;
use MongoDB\BSON\Regex; use MongoDB\BSON\Regex;
use MongoDB\BSON\UTCDateTime; use MongoDB\BSON\UTCDateTime;
...@@ -19,49 +20,42 @@ class Builder extends BaseBuilder ...@@ -19,49 +20,42 @@ class Builder extends BaseBuilder
{ {
/** /**
* The database collection. * The database collection.
*
* @var MongoCollection * @var MongoCollection
*/ */
protected $collection; protected $collection;
/** /**
* The column projections. * The column projections.
*
* @var array * @var array
*/ */
public $projections; public $projections;
/** /**
* The cursor timeout value. * The cursor timeout value.
*
* @var int * @var int
*/ */
public $timeout; public $timeout;
/** /**
* The cursor hint value. * The cursor hint value.
*
* @var int * @var int
*/ */
public $hint; public $hint;
/** /**
* Custom options to add to the query. * Custom options to add to the query.
*
* @var array * @var array
*/ */
public $options = []; public $options = [];
/** /**
* Indicate if we are executing a pagination query. * Indicate if we are executing a pagination query.
*
* @var bool * @var bool
*/ */
public $paginating = false; public $paginating = false;
/** /**
* All of the available clause operators. * All of the available clause operators.
*
* @var array * @var array
*/ */
public $operators = [ public $operators = [
...@@ -109,7 +103,6 @@ class Builder extends BaseBuilder ...@@ -109,7 +103,6 @@ class Builder extends BaseBuilder
/** /**
* Operator conversion. * Operator conversion.
*
* @var array * @var array
*/ */
protected $conversion = [ protected $conversion = [
...@@ -124,7 +117,6 @@ class Builder extends BaseBuilder ...@@ -124,7 +117,6 @@ class Builder extends BaseBuilder
/** /**
* Check if we need to return Collections instead of plain arrays (laravel >= 5.3 ) * Check if we need to return Collections instead of plain arrays (laravel >= 5.3 )
*
* @var boolean * @var boolean
*/ */
protected $useCollections; protected $useCollections;
...@@ -142,7 +134,6 @@ class Builder extends BaseBuilder ...@@ -142,7 +134,6 @@ class Builder extends BaseBuilder
/** /**
* Returns true if Laravel or Lumen >= 5.3 * Returns true if Laravel or Lumen >= 5.3
*
* @return bool * @return bool
*/ */
protected function shouldUseCollections() protected function shouldUseCollections()
...@@ -152,12 +143,13 @@ class Builder extends BaseBuilder ...@@ -152,12 +143,13 @@ class Builder extends BaseBuilder
$version = filter_var(explode(')', $version)[0], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); // lumen $version = filter_var(explode(')', $version)[0], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); // lumen
return version_compare($version, '5.3', '>='); return version_compare($version, '5.3', '>=');
} }
return true;
} }
/** /**
* Set the projections. * Set the projections.
* * @param array $columns
* @param array $columns
* @return $this * @return $this
*/ */
public function project($columns) public function project($columns)
...@@ -169,8 +161,7 @@ class Builder extends BaseBuilder ...@@ -169,8 +161,7 @@ class Builder extends BaseBuilder
/** /**
* Set the cursor timeout in seconds. * Set the cursor timeout in seconds.
* * @param int $seconds
* @param int $seconds
* @return $this * @return $this
*/ */
public function timeout($seconds) public function timeout($seconds)
...@@ -182,8 +173,7 @@ class Builder extends BaseBuilder ...@@ -182,8 +173,7 @@ class Builder extends BaseBuilder
/** /**
* Set the cursor hint. * Set the cursor hint.
* * @param mixed $index
* @param mixed $index
* @return $this * @return $this
*/ */
public function hint($index) public function hint($index)
...@@ -201,6 +191,16 @@ class Builder extends BaseBuilder ...@@ -201,6 +191,16 @@ class Builder extends BaseBuilder
return $this->where('_id', '=', $this->convertKey($id))->first($columns); return $this->where('_id', '=', $this->convertKey($id))->first($columns);
} }
/**
* @inheritdoc
*/
public function value($column)
{
$result = (array) $this->first([$column]);
return Arr::get($result, $column);
}
/** /**
* @inheritdoc * @inheritdoc
*/ */
...@@ -211,8 +211,7 @@ class Builder extends BaseBuilder ...@@ -211,8 +211,7 @@ class Builder extends BaseBuilder
/** /**
* Execute the query as a fresh "select" statement. * Execute the query as a fresh "select" statement.
* * @param array $columns
* @param array $columns
* @return array|static[]|Collection * @return array|static[]|Collection
*/ */
public function getFresh($columns = []) public function getFresh($columns = [])
...@@ -220,7 +219,7 @@ class Builder extends BaseBuilder ...@@ -220,7 +219,7 @@ class Builder extends BaseBuilder
// If no columns have been specified for the select statement, we will set them // If no columns have been specified for the select statement, we will set them
// here to either the passed columns, or the standard default of retrieving // here to either the passed columns, or the standard default of retrieving
// all of the columns on the table using the "wildcard" column character. // all of the columns on the table using the "wildcard" column character.
if (is_null($this->columns)) { if ($this->columns === null) {
$this->columns = $columns; $this->columns = $columns;
} }
...@@ -233,7 +232,7 @@ class Builder extends BaseBuilder ...@@ -233,7 +232,7 @@ class Builder extends BaseBuilder
$wheres = $this->compileWheres(); $wheres = $this->compileWheres();
// Use MongoDB's aggregation framework when using grouping or aggregation functions. // Use MongoDB's aggregation framework when using grouping or aggregation functions.
if ($this->groups || $this->aggregate || $this->paginating) { if ($this->groups || $this->aggregate) {
$group = []; $group = [];
$unwinds = []; $unwinds = [];
...@@ -268,24 +267,34 @@ class Builder extends BaseBuilder ...@@ -268,24 +267,34 @@ class Builder extends BaseBuilder
$column = implode('.', $splitColumns); $column = implode('.', $splitColumns);
} }
// Translate count into sum. // Null coalense only > 7.2
if ($function == 'count') {
$aggregations = blank($this->aggregate['columns']) ? [] : $this->aggregate['columns'];
if (in_array('*', $aggregations) && $function == 'count') {
// When ORM is paginating, count doesnt need a aggregation, just a cursor operation
// elseif added to use this only in pagination
// https://docs.mongodb.com/manual/reference/method/cursor.count/
// count method returns int
$totalResults = $this->collection->count($wheres);
// Preserving format expected by framework
$results = [
[
'_id' => null,
'aggregate' => $totalResults
]
];
return $this->useCollections ? new Collection($results) : $results;
} elseif ($function == 'count') {
// Translate count into sum.
$group['aggregate'] = ['$sum' => 1]; $group['aggregate'] = ['$sum' => 1];
} // Pass other functions directly. } else {
else {
$group['aggregate'] = ['$' . $function => '$' . $column]; $group['aggregate'] = ['$' . $function => '$' . $column];
} }
} }
} }
// When using pagination, we limit the number of returned columns
// by adding a projection.
if ($this->paginating) {
foreach ($this->columns as $column) {
$this->projections[$column] = 1;
}
}
// The _id field is mandatory when using grouping. // The _id field is mandatory when using grouping.
if ($group && empty($group['_id'])) { if ($group && empty($group['_id'])) {
$group['_id'] = null; $group['_id'] = null;
...@@ -375,10 +384,12 @@ class Builder extends BaseBuilder ...@@ -375,10 +384,12 @@ class Builder extends BaseBuilder
if ($this->limit) { if ($this->limit) {
$options['limit'] = $this->limit; $options['limit'] = $this->limit;
} }
if ($this->hint) {
$options['hint'] = $this->hint;
}
if ($columns) { if ($columns) {
$options['projection'] = $columns; $options['projection'] = $columns;
} }
// if ($this->hint) $cursor->hint($this->hint);
// Fix for legacy support, converts the results to arrays instead of objects. // Fix for legacy support, converts the results to arrays instead of objects.
$options['typeMap'] = ['root' => 'array', 'document' => 'array']; $options['typeMap'] = ['root' => 'array', 'document' => 'array'];
...@@ -399,7 +410,6 @@ class Builder extends BaseBuilder ...@@ -399,7 +410,6 @@ class Builder extends BaseBuilder
/** /**
* Generate the unique cache key for the current query. * Generate the unique cache key for the current query.
*
* @return string * @return string
*/ */
public function generateCacheKey() public function generateCacheKey()
...@@ -456,7 +466,7 @@ class Builder extends BaseBuilder ...@@ -456,7 +466,7 @@ class Builder extends BaseBuilder
*/ */
public function exists() public function exists()
{ {
return !is_null($this->first()); return $this->first() !== null;
} }
/** /**
...@@ -493,11 +503,10 @@ class Builder extends BaseBuilder ...@@ -493,11 +503,10 @@ class Builder extends BaseBuilder
/** /**
* Add a "where all" clause to the query. * Add a "where all" clause to the query.
* * @param string $column
* @param string $column * @param array $values
* @param array $values * @param string $boolean
* @param string $boolean * @param bool $not
* @param bool $not
* @return $this * @return $this
*/ */
public function whereAll($column, array $values, $boolean = 'and', $not = false) public function whereAll($column, array $values, $boolean = 'and', $not = false)
...@@ -567,7 +576,7 @@ class Builder extends BaseBuilder ...@@ -567,7 +576,7 @@ class Builder extends BaseBuilder
$result = $this->collection->insertOne($values); $result = $this->collection->insertOne($values);
if (1 == (int) $result->isAcknowledged()) { if (1 == (int) $result->isAcknowledged()) {
if (is_null($sequence)) { if ($sequence === null) {
$sequence = '_id'; $sequence = '_id';
} }
...@@ -631,12 +640,6 @@ class Builder extends BaseBuilder ...@@ -631,12 +640,6 @@ class Builder extends BaseBuilder
*/ */
public function forPageAfterId($perPage = 15, $lastId = 0, $column = '_id') public function forPageAfterId($perPage = 15, $lastId = 0, $column = '_id')
{ {
// When using ObjectIDs to paginate, we need to use a hex string as the
// "minimum" ID rather than the integer zero so the '$lt' query works.
if ($column === '_id' && $lastId === 0) {
$lastId = '000000000000000000000000';
}
return parent::forPageAfterId($perPage, $lastId, $column); return parent::forPageAfterId($perPage, $lastId, $column);
} }
...@@ -645,7 +648,7 @@ class Builder extends BaseBuilder ...@@ -645,7 +648,7 @@ class Builder extends BaseBuilder
*/ */
public function pluck($column, $key = null) public function pluck($column, $key = null)
{ {
$results = $this->get(is_null($key) ? [$column] : [$column, $key]); $results = $this->get($key === null ? [$column] : [$column, $key]);
// Convert ObjectID's to strings // Convert ObjectID's to strings
if ($key == '_id') { if ($key == '_id') {
...@@ -667,7 +670,7 @@ class Builder extends BaseBuilder ...@@ -667,7 +670,7 @@ class Builder extends BaseBuilder
// If an ID is passed to the method, we will set the where clause to check // If an ID is passed to the method, we will set the where clause to check
// the ID to allow developers to simply and quickly remove a single row // the ID to allow developers to simply and quickly remove a single row
// from their database without manually specifying the where clauses. // from their database without manually specifying the where clauses.
if (!is_null($id)) { if ($id !== null) {
$this->where('_id', '=', $id); $this->where('_id', '=', $id);
} }
...@@ -683,7 +686,7 @@ class Builder extends BaseBuilder ...@@ -683,7 +686,7 @@ class Builder extends BaseBuilder
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function from($collection) public function from($collection, $as = null)
{ {
if ($collection) { if ($collection) {
$this->collection = $this->connection->getCollection($collection); $this->collection = $this->connection->getCollection($collection);
...@@ -697,18 +700,21 @@ class Builder extends BaseBuilder ...@@ -697,18 +700,21 @@ class Builder extends BaseBuilder
*/ */
public function truncate() public function truncate()
{ {
$result = $this->collection->drop(); $options = [
'typeMap' => ['root' => 'object', 'document' => 'object'],
];
$result = $this->collection->drop($options);
return (1 == (int) $result->ok); return (1 == (int) $result->ok);
} }
/** /**
* Get an array with the values of a given column. * Get an array with the values of a given column.
* * @param string $column
* @deprecated * @param string $key
* @param string $column
* @param string $key
* @return array * @return array
* @deprecated
*/ */
public function lists($column, $key = null) public function lists($column, $key = null)
{ {
...@@ -723,8 +729,10 @@ class Builder extends BaseBuilder ...@@ -723,8 +729,10 @@ class Builder extends BaseBuilder
// Execute the closure on the mongodb collection // Execute the closure on the mongodb collection
if ($expression instanceof Closure) { if ($expression instanceof Closure) {
return call_user_func($expression, $this->collection); return call_user_func($expression, $this->collection);
} // Create an expression for the given value }
elseif (!is_null($expression)) {
// Create an expression for the given value
if ($expression !== null) {
return new Expression($expression); return new Expression($expression);
} }
...@@ -734,7 +742,6 @@ class Builder extends BaseBuilder ...@@ -734,7 +742,6 @@ class Builder extends BaseBuilder
/** /**
* Append one or more values to an array. * Append one or more values to an array.
*
* @param mixed $column * @param mixed $column
* @param mixed $value * @param mixed $value
* @param bool $unique * @param bool $unique
...@@ -761,9 +768,8 @@ class Builder extends BaseBuilder ...@@ -761,9 +768,8 @@ class Builder extends BaseBuilder
/** /**
* Remove one or more values from an array. * Remove one or more values from an array.
* * @param mixed $column
* @param mixed $column * @param mixed $value
* @param mixed $value
* @return int * @return int
*/ */
public function pull($column, $value = null) public function pull($column, $value = null)
...@@ -785,8 +791,7 @@ class Builder extends BaseBuilder ...@@ -785,8 +791,7 @@ class Builder extends BaseBuilder
/** /**
* Remove one or more fields. * Remove one or more fields.
* * @param mixed $columns
* @param mixed $columns
* @return int * @return int
*/ */
public function drop($columns) public function drop($columns)
...@@ -816,9 +821,8 @@ class Builder extends BaseBuilder ...@@ -816,9 +821,8 @@ class Builder extends BaseBuilder
/** /**
* Perform an update query. * Perform an update query.
* * @param array $query
* @param array $query * @param array $options
* @param array $options
* @return int * @return int
*/ */
protected function performUpdate($query, array $options = []) protected function performUpdate($query, array $options = [])
...@@ -839,8 +843,7 @@ class Builder extends BaseBuilder ...@@ -839,8 +843,7 @@ class Builder extends BaseBuilder
/** /**
* Convert a key to ObjectID if needed. * Convert a key to ObjectID if needed.
* * @param mixed $id
* @param mixed $id
* @return mixed * @return mixed
*/ */
public function convertKey($id) public function convertKey($id)
...@@ -849,6 +852,10 @@ class Builder extends BaseBuilder ...@@ -849,6 +852,10 @@ class Builder extends BaseBuilder
return new ObjectID($id); return new ObjectID($id);
} }
if (is_string($id) && strlen($id) === 16 && preg_match('~[^\x20-\x7E\t\r\n]~', $id) > 0) {
return new Binary($id, Binary::TYPE_UUID);
}
return $id; return $id;
} }
...@@ -873,7 +880,6 @@ class Builder extends BaseBuilder ...@@ -873,7 +880,6 @@ class Builder extends BaseBuilder
/** /**
* Compile the where array. * Compile the where array.
*
* @return array * @return array
*/ */
protected function compileWheres() protected function compileWheres()
...@@ -988,9 +994,13 @@ class Builder extends BaseBuilder ...@@ -988,9 +994,13 @@ class Builder extends BaseBuilder
{ {
extract($where); extract($where);
// Replace like with a Regex instance. // Replace like or not like with a Regex instance.
if ($operator == 'like') { if (in_array($operator, ['like', 'not like'])) {
$operator = '='; if ($operator === 'not like') {
$operator = 'not';
} else {
$operator = '=';
}
// Convert to regular expression. // Convert to regular expression.
$regex = preg_replace('#(^|[^\\\])%#', '$1.*', preg_quote($value)); $regex = preg_replace('#(^|[^\\\])%#', '$1.*', preg_quote($value));
...@@ -1000,7 +1010,7 @@ class Builder extends BaseBuilder ...@@ -1000,7 +1010,7 @@ class Builder extends BaseBuilder
$regex = '^' . $regex; $regex = '^' . $regex;
} }
if (!Str::endsWith($value, '%')) { if (!Str::endsWith($value, '%')) {
$regex = $regex . '$'; $regex .= '$';
} }
$value = new Regex($regex, 'i'); $value = new Regex($regex, 'i');
...@@ -1112,14 +1122,14 @@ class Builder extends BaseBuilder ...@@ -1112,14 +1122,14 @@ class Builder extends BaseBuilder
], ],
], ],
]; ];
} else {
return [
$column => [
'$gte' => $values[0],
'$lte' => $values[1],
],
];
} }
return [
$column => [
'$gte' => $values[0],
'$lte' => $values[1],
],
];
} }
/** /**
...@@ -1133,8 +1143,7 @@ class Builder extends BaseBuilder ...@@ -1133,8 +1143,7 @@ class Builder extends BaseBuilder
/** /**
* Set custom options for the query. * Set custom options for the query.
* * @param array $options
* @param array $options
* @return $this * @return $this
*/ */
public function options(array $options) public function options(array $options)
......
...@@ -9,11 +9,9 @@ class MongoFailedJobProvider extends DatabaseFailedJobProvider ...@@ -9,11 +9,9 @@ class MongoFailedJobProvider extends DatabaseFailedJobProvider
{ {
/** /**
* Log a failed job into storage. * Log a failed job into storage.
* * @param string $connection
* @param string $connection * @param string $queue
* @param string $queue * @param string $payload
* @param string $payload
*
* @return void * @return void
*/ */
public function log($connection, $queue, $payload, $exception) public function log($connection, $queue, $payload, $exception)
...@@ -25,7 +23,6 @@ class MongoFailedJobProvider extends DatabaseFailedJobProvider ...@@ -25,7 +23,6 @@ class MongoFailedJobProvider extends DatabaseFailedJobProvider
/** /**
* Get a list of all of the failed jobs. * Get a list of all of the failed jobs.
*
* @return object[] * @return object[]
*/ */
public function all() public function all()
...@@ -42,14 +39,17 @@ class MongoFailedJobProvider extends DatabaseFailedJobProvider ...@@ -42,14 +39,17 @@ class MongoFailedJobProvider extends DatabaseFailedJobProvider
/** /**
* Get a single failed job. * Get a single failed job.
* * @param mixed $id
* @param mixed $id
* @return object * @return object
*/ */
public function find($id) public function find($id)
{ {
$job = $this->getTable()->find($id); $job = $this->getTable()->find($id);
if (!$job) {
return;
}
$job['id'] = (string) $job['_id']; $job['id'] = (string) $job['_id'];
return (object) $job; return (object) $job;
...@@ -57,8 +57,7 @@ class MongoFailedJobProvider extends DatabaseFailedJobProvider ...@@ -57,8 +57,7 @@ class MongoFailedJobProvider extends DatabaseFailedJobProvider
/** /**
* Delete a single failed job from storage. * Delete a single failed job from storage.
* * @param mixed $id
* @param mixed $id
* @return bool * @return bool
*/ */
public function forget($id) public function forget($id)
......
...@@ -10,15 +10,13 @@ class MongoConnector implements ConnectorInterface ...@@ -10,15 +10,13 @@ class MongoConnector implements ConnectorInterface
{ {
/** /**
* Database connections. * Database connections.
*
* @var \Illuminate\Database\ConnectionResolverInterface * @var \Illuminate\Database\ConnectionResolverInterface
*/ */
protected $connections; protected $connections;
/** /**
* Create a new connector instance. * Create a new connector instance.
* * @param \Illuminate\Database\ConnectionResolverInterface $connections
* @param \Illuminate\Database\ConnectionResolverInterface $connections
*/ */
public function __construct(ConnectionResolverInterface $connections) public function __construct(ConnectionResolverInterface $connections)
{ {
...@@ -27,8 +25,7 @@ class MongoConnector implements ConnectorInterface ...@@ -27,8 +25,7 @@ class MongoConnector implements ConnectorInterface
/** /**
* Establish a queue connection. * Establish a queue connection.
* * @param array $config
* @param array $config
* @return \Illuminate\Contracts\Queue\Queue * @return \Illuminate\Contracts\Queue\Queue
*/ */
public function connect(array $config) public function connect(array $config)
......
...@@ -8,7 +8,6 @@ class MongoJob extends DatabaseJob ...@@ -8,7 +8,6 @@ class MongoJob extends DatabaseJob
{ {
/** /**
* Indicates if the job has been reserved. * Indicates if the job has been reserved.
*
* @return bool * @return bool
*/ */
public function isReserved() public function isReserved()
......
...@@ -11,14 +11,12 @@ class MongoQueue extends DatabaseQueue ...@@ -11,14 +11,12 @@ class MongoQueue extends DatabaseQueue
{ {
/** /**
* The expiration time of a job. * The expiration time of a job.
*
* @var int|null * @var int|null
*/ */
protected $retryAfter = 60; protected $retryAfter = 60;
/** /**
* The connection name for the queue. * The connection name for the queue.
*
* @var string * @var string
*/ */
protected $connectionName; protected $connectionName;
...@@ -39,7 +37,7 @@ class MongoQueue extends DatabaseQueue ...@@ -39,7 +37,7 @@ class MongoQueue extends DatabaseQueue
{ {
$queue = $this->getQueue($queue); $queue = $this->getQueue($queue);
if (!is_null($this->retryAfter)) { if ($this->retryAfter !== null) {
$this->releaseJobsThatHaveBeenReservedTooLong($queue); $this->releaseJobsThatHaveBeenReservedTooLong($queue);
} }
...@@ -52,17 +50,13 @@ class MongoQueue extends DatabaseQueue ...@@ -52,17 +50,13 @@ class MongoQueue extends DatabaseQueue
/** /**
* Get the next available job for the queue and mark it as reserved. * Get the next available job for the queue and mark it as reserved.
*
* When using multiple daemon queue listeners to process jobs there * When using multiple daemon queue listeners to process jobs there
* is a possibility that multiple processes can end up reading the * is a possibility that multiple processes can end up reading the
* same record before one has flagged it as reserved. * same record before one has flagged it as reserved.
*
* This race condition can result in random jobs being run more then * This race condition can result in random jobs being run more then
* once. To solve this we use findOneAndUpdate to lock the next jobs * once. To solve this we use findOneAndUpdate to lock the next jobs
* record while flagging it as reserved at the same time. * record while flagging it as reserved at the same time.
* * @param string|null $queue
* @param string|null $queue
*
* @return \StdClass|null * @return \StdClass|null
*/ */
protected function getNextAvailableJobAndReserve($queue) protected function getNextAvailableJobAndReserve($queue)
...@@ -70,7 +64,7 @@ class MongoQueue extends DatabaseQueue ...@@ -70,7 +64,7 @@ class MongoQueue extends DatabaseQueue
$job = $this->database->getCollection($this->table)->findOneAndUpdate( $job = $this->database->getCollection($this->table)->findOneAndUpdate(
[ [
'queue' => $this->getQueue($queue), 'queue' => $this->getQueue($queue),
'reserved' => 0, 'reserved' => ['$ne' => 1],
'available_at' => ['$lte' => Carbon::now()->getTimestamp()], 'available_at' => ['$lte' => Carbon::now()->getTimestamp()],
], ],
[ [
...@@ -78,6 +72,9 @@ class MongoQueue extends DatabaseQueue ...@@ -78,6 +72,9 @@ class MongoQueue extends DatabaseQueue
'reserved' => 1, 'reserved' => 1,
'reserved_at' => Carbon::now()->getTimestamp(), 'reserved_at' => Carbon::now()->getTimestamp(),
], ],
'$inc' => [
'attempts' => 1,
],
], ],
[ [
'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER, 'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
...@@ -94,39 +91,28 @@ class MongoQueue extends DatabaseQueue ...@@ -94,39 +91,28 @@ class MongoQueue extends DatabaseQueue
/** /**
* Release the jobs that have been reserved for too long. * Release the jobs that have been reserved for too long.
* * @param string $queue
* @param string $queue
* @return void * @return void
*/ */
protected function releaseJobsThatHaveBeenReservedTooLong($queue) protected function releaseJobsThatHaveBeenReservedTooLong($queue)
{ {
$expiration = Carbon::now()->subSeconds($this->retryAfter)->getTimestamp(); $expiration = Carbon::now()->subSeconds($this->retryAfter)->getTimestamp();
$now = time();
$reserved = $this->database->collection($this->table) $reserved = $this->database->collection($this->table)
->where('queue', $this->getQueue($queue)) ->where('queue', $this->getQueue($queue))
->where(function ($query) use ($expiration, $now) { ->whereNotNull('reserved_at')
// Check for available jobs ->where('reserved_at', '<=', $expiration)
$query->where(function ($query) use ($now) { ->get();
$query->whereNull('reserved_at');
$query->where('available_at', '<=', $now);
});
// Check for jobs that are reserved but have expired
$query->orWhere('reserved_at', '<=', $expiration);
})->get();
foreach ($reserved as $job) { foreach ($reserved as $job) {
$attempts = $job['attempts'] + 1; $this->releaseJob($job['_id'], $job['attempts']);
$this->releaseJob($job['_id'], $attempts);
} }
} }
/** /**
* Release the given job ID from reservation. * Release the given job ID from reservation.
* * @param string $id
* @param string $id * @param int $attempts
* @param int $attempts
* @return void * @return void
*/ */
protected function releaseJob($id, $attempts) protected function releaseJob($id, $attempts)
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
namespace Jenssegers\Mongodb\Relations; namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class BelongsTo extends \Illuminate\Database\Eloquent\Relations\BelongsTo class BelongsTo extends \Illuminate\Database\Eloquent\Relations\BelongsTo
{ {
/** /**
* Get the key for comparing against the parent key in "has" query. * Get the key for comparing against the parent key in "has" query.
*
* @return string * @return string
*/ */
public function getHasCompareKey() public function getHasCompareKey()
...@@ -52,11 +52,21 @@ class BelongsTo extends \Illuminate\Database\Eloquent\Relations\BelongsTo ...@@ -52,11 +52,21 @@ class BelongsTo extends \Illuminate\Database\Eloquent\Relations\BelongsTo
/** /**
* Get the owner key with backwards compatible support. * Get the owner key with backwards compatible support.
*
* @return string * @return string
*/ */
public function getOwnerKey() public function getOwnerKey()
{ {
return property_exists($this, 'ownerKey') ? $this->ownerKey : $this->otherKey; return property_exists($this, 'ownerKey') ? $this->ownerKey : $this->otherKey;
} }
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
} }
...@@ -5,6 +5,7 @@ namespace Jenssegers\Mongodb\Relations; ...@@ -5,6 +5,7 @@ namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\BelongsToMany as EloquentBelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany as EloquentBelongsToMany;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
...@@ -12,7 +13,6 @@ class BelongsToMany extends EloquentBelongsToMany ...@@ -12,7 +13,6 @@ class BelongsToMany extends EloquentBelongsToMany
{ {
/** /**
* Get the key for comparing against the parent key in "has" query. * Get the key for comparing against the parent key in "has" query.
*
* @return string * @return string
*/ */
public function getHasCompareKey() public function getHasCompareKey()
...@@ -38,8 +38,7 @@ class BelongsToMany extends EloquentBelongsToMany ...@@ -38,8 +38,7 @@ class BelongsToMany extends EloquentBelongsToMany
/** /**
* Set the select clause for the relation query. * Set the select clause for the relation query.
* * @param array $columns
* @param array $columns
* @return array * @return array
*/ */
protected function getSelectColumns(array $columns = ['*']) protected function getSelectColumns(array $columns = ['*'])
...@@ -67,7 +66,6 @@ class BelongsToMany extends EloquentBelongsToMany ...@@ -67,7 +66,6 @@ class BelongsToMany extends EloquentBelongsToMany
/** /**
* Set the where clause for the relation query. * Set the where clause for the relation query.
*
* @return $this * @return $this
*/ */
protected function setWhere() protected function setWhere()
...@@ -274,7 +272,6 @@ class BelongsToMany extends EloquentBelongsToMany ...@@ -274,7 +272,6 @@ class BelongsToMany extends EloquentBelongsToMany
/** /**
* Create a new query builder for the related model. * Create a new query builder for the related model.
*
* @return \Illuminate\Database\Query\Builder * @return \Illuminate\Database\Query\Builder
*/ */
public function newRelatedQuery() public function newRelatedQuery()
...@@ -284,7 +281,6 @@ class BelongsToMany extends EloquentBelongsToMany ...@@ -284,7 +281,6 @@ class BelongsToMany extends EloquentBelongsToMany
/** /**
* Get the fully qualified foreign key for the relation. * Get the fully qualified foreign key for the relation.
*
* @return string * @return string
*/ */
public function getForeignKey() public function getForeignKey()
...@@ -311,10 +307,9 @@ class BelongsToMany extends EloquentBelongsToMany ...@@ -311,10 +307,9 @@ class BelongsToMany extends EloquentBelongsToMany
/** /**
* Format the sync list so that it is keyed by ID. (Legacy Support) * Format the sync list so that it is keyed by ID. (Legacy Support)
* The original function has been renamed to formatRecordsList since Laravel 5.3 * The original function has been renamed to formatRecordsList since Laravel 5.3
* * @param array $records
* @deprecated
* @param array $records
* @return array * @return array
* @deprecated
*/ */
protected function formatSyncList(array $records) protected function formatSyncList(array $records)
{ {
...@@ -330,11 +325,21 @@ class BelongsToMany extends EloquentBelongsToMany ...@@ -330,11 +325,21 @@ class BelongsToMany extends EloquentBelongsToMany
/** /**
* Get the related key with backwards compatible support. * Get the related key with backwards compatible support.
*
* @return string * @return string
*/ */
public function getRelatedKey() public function getRelatedKey()
{ {
return property_exists($this, 'relatedPivotKey') ? $this->relatedPivotKey : $this->relatedKey; return property_exists($this, 'relatedPivotKey') ? $this->relatedPivotKey : $this->relatedKey;
} }
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
} }
...@@ -4,6 +4,7 @@ namespace Jenssegers\Mongodb\Relations; ...@@ -4,6 +4,7 @@ namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator; use Illuminate\Pagination\Paginator;
use MongoDB\BSON\ObjectID; use MongoDB\BSON\ObjectID;
...@@ -32,8 +33,7 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -32,8 +33,7 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Save a new model and attach it to the parent model. * Save a new model and attach it to the parent model.
* * @param Model $model
* @param Model $model
* @return Model|bool * @return Model|bool
*/ */
public function performInsert(Model $model) public function performInsert(Model $model)
...@@ -62,8 +62,7 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -62,8 +62,7 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Save an existing model and attach it to the parent model. * Save an existing model and attach it to the parent model.
* * @param Model $model
* @param Model $model
* @return Model|bool * @return Model|bool
*/ */
public function performUpdate(Model $model) public function performUpdate(Model $model)
...@@ -94,8 +93,7 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -94,8 +93,7 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Delete an existing model and detach it from the parent model. * Delete an existing model and detach it from the parent model.
* * @param Model $model
* @param Model $model
* @return int * @return int
*/ */
public function performDelete(Model $model) public function performDelete(Model $model)
...@@ -121,23 +119,21 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -121,23 +119,21 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Associate the model instance to the given parent, without saving it to the database. * Associate the model instance to the given parent, without saving it to the database.
* * @param Model $model
* @param Model $model
* @return Model * @return Model
*/ */
public function associate(Model $model) public function associate(Model $model)
{ {
if (!$this->contains($model)) { if (!$this->contains($model)) {
return $this->associateNew($model); return $this->associateNew($model);
} else {
return $this->associateExisting($model);
} }
return $this->associateExisting($model);
} }
/** /**
* Dissociate the model instance from the given parent, without saving it to the database. * Dissociate the model instance from the given parent, without saving it to the database.
* * @param mixed $ids
* @param mixed $ids
* @return int * @return int
*/ */
public function dissociate($ids = []) public function dissociate($ids = [])
...@@ -165,8 +161,7 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -165,8 +161,7 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Destroy the embedded models for the given IDs. * Destroy the embedded models for the given IDs.
* * @param mixed $ids
* @param mixed $ids
* @return int * @return int
*/ */
public function destroy($ids = []) public function destroy($ids = [])
...@@ -190,7 +185,6 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -190,7 +185,6 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Delete all embedded models. * Delete all embedded models.
*
* @return int * @return int
*/ */
public function delete() public function delete()
...@@ -207,8 +201,7 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -207,8 +201,7 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Destroy alias. * Destroy alias.
* * @param mixed $ids
* @param mixed $ids
* @return int * @return int
*/ */
public function detach($ids = []) public function detach($ids = [])
...@@ -218,8 +211,7 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -218,8 +211,7 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Save alias. * Save alias.
* * @param Model $model
* @param Model $model
* @return Model * @return Model
*/ */
public function attach(Model $model) public function attach(Model $model)
...@@ -229,14 +221,13 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -229,14 +221,13 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Associate a new model instance to the given parent, without saving it to the database. * Associate a new model instance to the given parent, without saving it to the database.
* * @param Model $model
* @param Model $model
* @return Model * @return Model
*/ */
protected function associateNew($model) protected function associateNew($model)
{ {
// Create a new key if needed. // Create a new key if needed.
if (!$model->getAttribute('_id')) { if ($model->getKeyName() === '_id' && !$model->getAttribute('_id')) {
$model->setAttribute('_id', new ObjectID); $model->setAttribute('_id', new ObjectID);
} }
...@@ -250,8 +241,7 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -250,8 +241,7 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Associate an existing model instance to the given parent, without saving it to the database. * Associate an existing model instance to the given parent, without saving it to the database.
* * @param Model $model
* @param Model $model
* @return Model * @return Model
*/ */
protected function associateExisting($model) protected function associateExisting($model)
...@@ -276,8 +266,7 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -276,8 +266,7 @@ class EmbedsMany extends EmbedsOneOrMany
/** /**
* Get a paginator for the "select" statement. * Get a paginator for the "select" statement.
* * @param int $perPage
* @param int $perPage
* @return \Illuminate\Pagination\AbstractPaginator * @return \Illuminate\Pagination\AbstractPaginator
*/ */
public function paginate($perPage = null) public function paginate($perPage = null)
...@@ -328,4 +317,15 @@ class EmbedsMany extends EmbedsOneOrMany ...@@ -328,4 +317,15 @@ class EmbedsMany extends EmbedsOneOrMany
return parent::__call($method, $parameters); return parent::__call($method, $parameters);
} }
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace Jenssegers\Mongodb\Relations; namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use MongoDB\BSON\ObjectID; use MongoDB\BSON\ObjectID;
class EmbedsOne extends EmbedsOneOrMany class EmbedsOne extends EmbedsOneOrMany
...@@ -29,8 +30,7 @@ class EmbedsOne extends EmbedsOneOrMany ...@@ -29,8 +30,7 @@ class EmbedsOne extends EmbedsOneOrMany
/** /**
* Save a new model and attach it to the parent model. * Save a new model and attach it to the parent model.
* * @param Model $model
* @param Model $model
* @return Model|bool * @return Model|bool
*/ */
public function performInsert(Model $model) public function performInsert(Model $model)
...@@ -58,8 +58,7 @@ class EmbedsOne extends EmbedsOneOrMany ...@@ -58,8 +58,7 @@ class EmbedsOne extends EmbedsOneOrMany
/** /**
* Save an existing model and attach it to the parent model. * Save an existing model and attach it to the parent model.
* * @param Model $model
* @param Model $model
* @return Model|bool * @return Model|bool
*/ */
public function performUpdate(Model $model) public function performUpdate(Model $model)
...@@ -84,7 +83,6 @@ class EmbedsOne extends EmbedsOneOrMany ...@@ -84,7 +83,6 @@ class EmbedsOne extends EmbedsOneOrMany
/** /**
* Delete an existing model and detach it from the parent model. * Delete an existing model and detach it from the parent model.
*
* @return int * @return int
*/ */
public function performDelete() public function performDelete()
...@@ -108,8 +106,7 @@ class EmbedsOne extends EmbedsOneOrMany ...@@ -108,8 +106,7 @@ class EmbedsOne extends EmbedsOneOrMany
/** /**
* Attach the model to its parent. * Attach the model to its parent.
* * @param Model $model
* @param Model $model
* @return Model * @return Model
*/ */
public function associate(Model $model) public function associate(Model $model)
...@@ -119,7 +116,6 @@ class EmbedsOne extends EmbedsOneOrMany ...@@ -119,7 +116,6 @@ class EmbedsOne extends EmbedsOneOrMany
/** /**
* Detach the model from its parent. * Detach the model from its parent.
*
* @return Model * @return Model
*/ */
public function dissociate() public function dissociate()
...@@ -129,11 +125,21 @@ class EmbedsOne extends EmbedsOneOrMany ...@@ -129,11 +125,21 @@ class EmbedsOne extends EmbedsOneOrMany
/** /**
* Delete all embedded models. * Delete all embedded models.
*
* @return int * @return int
*/ */
public function delete() public function delete()
{ {
return $this->performDelete(); return $this->performDelete();
} }
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
} }
...@@ -4,6 +4,7 @@ namespace Jenssegers\Mongodb\Relations; ...@@ -4,6 +4,7 @@ namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Eloquent\Relations\Relation;
use Jenssegers\Mongodb\Eloquent\Model; use Jenssegers\Mongodb\Eloquent\Model;
...@@ -11,34 +12,30 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -11,34 +12,30 @@ abstract class EmbedsOneOrMany extends Relation
{ {
/** /**
* The local key of the parent model. * The local key of the parent model.
*
* @var string * @var string
*/ */
protected $localKey; protected $localKey;
/** /**
* The foreign key of the parent model. * The foreign key of the parent model.
*
* @var string * @var string
*/ */
protected $foreignKey; protected $foreignKey;
/** /**
* The "name" of the relationship. * The "name" of the relationship.
*
* @var string * @var string
*/ */
protected $relation; protected $relation;
/** /**
* Create a new embeds many relationship instance. * Create a new embeds many relationship instance.
* * @param Builder $query
* @param Builder $query * @param Model $parent
* @param Model $parent * @param Model $related
* @param Model $related * @param string $localKey
* @param string $localKey * @param string $foreignKey
* @param string $foreignKey * @param string $relation
* @param string $relation
*/ */
public function __construct(Builder $query, Model $parent, Model $related, $localKey, $foreignKey, $relation) public function __construct(Builder $query, Model $parent, Model $related, $localKey, $foreignKey, $relation)
{ {
...@@ -93,9 +90,7 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -93,9 +90,7 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Shorthand to get the results of the relationship. * Shorthand to get the results of the relationship.
* * @param array $columns
* @param array $columns
*
* @return Collection * @return Collection
*/ */
public function get($columns = ['*']) public function get($columns = ['*'])
...@@ -105,7 +100,6 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -105,7 +100,6 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Get the number of embedded models. * Get the number of embedded models.
*
* @return int * @return int
*/ */
public function count() public function count()
...@@ -115,8 +109,7 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -115,8 +109,7 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Attach a model instance to the parent model. * Attach a model instance to the parent model.
* * @param Model $model
* @param Model $model
* @return Model|bool * @return Model|bool
*/ */
public function save(Model $model) public function save(Model $model)
...@@ -128,8 +121,7 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -128,8 +121,7 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Attach a collection of models to the parent instance. * Attach a collection of models to the parent instance.
* * @param Collection|array $models
* @param Collection|array $models
* @return Collection|array * @return Collection|array
*/ */
public function saveMany($models) public function saveMany($models)
...@@ -143,8 +135,7 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -143,8 +135,7 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Create a new instance of the related model. * Create a new instance of the related model.
* * @param array $attributes
* @param array $attributes
* @return Model * @return Model
*/ */
public function create(array $attributes = []) public function create(array $attributes = [])
...@@ -163,8 +154,7 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -163,8 +154,7 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Create an array of new instances of the related model. * Create an array of new instances of the related model.
* * @param array $records
* @param array $records
* @return array * @return array
*/ */
public function createMany(array $records) public function createMany(array $records)
...@@ -180,8 +170,7 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -180,8 +170,7 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Transform single ID, single Model or array of Models into an array of IDs. * Transform single ID, single Model or array of Models into an array of IDs.
* * @param mixed $ids
* @param mixed $ids
* @return array * @return array
*/ */
protected function getIdsArrayFrom($ids) protected function getIdsArrayFrom($ids)
...@@ -235,8 +224,7 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -235,8 +224,7 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Get the foreign key value for the relation. * Get the foreign key value for the relation.
* * @param mixed $id
* @param mixed $id
* @return mixed * @return mixed
*/ */
protected function getForeignKeyValue($id) protected function getForeignKeyValue($id)
...@@ -251,8 +239,7 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -251,8 +239,7 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Convert an array of records to a Collection. * Convert an array of records to a Collection.
* * @param array $records
* @param array $records
* @return Collection * @return Collection
*/ */
protected function toCollection(array $records = []) protected function toCollection(array $records = [])
...@@ -272,13 +259,12 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -272,13 +259,12 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Create a related model instanced. * Create a related model instanced.
* * @param array $attributes
* @param array $attributes
* @return Model * @return Model
*/ */
protected function toModel($attributes = []) protected function toModel($attributes = [])
{ {
if (is_null($attributes)) { if ($attributes === null) {
return; return;
} }
...@@ -301,7 +287,6 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -301,7 +287,6 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Get the relation instance of the parent. * Get the relation instance of the parent.
*
* @return Relation * @return Relation
*/ */
protected function getParentRelation() protected function getParentRelation()
...@@ -331,7 +316,6 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -331,7 +316,6 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Check if this relation is nested in another relation. * Check if this relation is nested in another relation.
*
* @return bool * @return bool
*/ */
protected function isNested() protected function isNested()
...@@ -341,8 +325,7 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -341,8 +325,7 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Get the fully qualified local key name. * Get the fully qualified local key name.
* * @param string $glue
* @param string $glue
* @return string * @return string
*/ */
protected function getPathHierarchy($glue = '.') protected function getPathHierarchy($glue = '.')
...@@ -368,7 +351,6 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -368,7 +351,6 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Get the primary key value of the parent. * Get the primary key value of the parent.
*
* @return string * @return string
*/ */
protected function getParentKey() protected function getParentKey()
...@@ -378,7 +360,6 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -378,7 +360,6 @@ abstract class EmbedsOneOrMany extends Relation
/** /**
* Return update values * Return update values
*
* @param $array * @param $array
* @param string $prepend * @param string $prepend
* @return array * @return array
...@@ -388,9 +369,29 @@ abstract class EmbedsOneOrMany extends Relation ...@@ -388,9 +369,29 @@ abstract class EmbedsOneOrMany extends Relation
$results = []; $results = [];
foreach ($array as $key => $value) { foreach ($array as $key => $value) {
$results[$prepend.$key] = $value; $results[$prepend . $key] = $value;
} }
return $results; return $results;
} }
/**
* Get the foreign key for the relationship.
* @return string
*/
public function getQualifiedForeignKeyName()
{
return $this->foreignKey;
}
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
} }
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
namespace Jenssegers\Mongodb\Relations; namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\HasMany as EloquentHasMany; use Illuminate\Database\Eloquent\Relations\HasMany as EloquentHasMany;
class HasMany extends EloquentHasMany class HasMany extends EloquentHasMany
{ {
/** /**
* Get the plain foreign key. * Get the plain foreign key.
*
* @return string * @return string
*/ */
public function getForeignKeyName() public function getForeignKeyName()
...@@ -19,7 +19,6 @@ class HasMany extends EloquentHasMany ...@@ -19,7 +19,6 @@ class HasMany extends EloquentHasMany
/** /**
* Get the plain foreign key. * Get the plain foreign key.
*
* @return string * @return string
*/ */
public function getPlainForeignKey() public function getPlainForeignKey()
...@@ -29,7 +28,6 @@ class HasMany extends EloquentHasMany ...@@ -29,7 +28,6 @@ class HasMany extends EloquentHasMany
/** /**
* Get the key for comparing against the parent key in "has" query. * Get the key for comparing against the parent key in "has" query.
*
* @return string * @return string
*/ */
public function getHasCompareKey() public function getHasCompareKey()
...@@ -49,9 +47,8 @@ class HasMany extends EloquentHasMany ...@@ -49,9 +47,8 @@ class HasMany extends EloquentHasMany
/** /**
* Add the constraints for a relationship count query. * Add the constraints for a relationship count query.
* * @param Builder $query
* @param Builder $query * @param Builder $parent
* @param Builder $parent
* @return Builder * @return Builder
*/ */
public function getRelationCountQuery(Builder $query, Builder $parent) public function getRelationCountQuery(Builder $query, Builder $parent)
...@@ -63,10 +60,9 @@ class HasMany extends EloquentHasMany ...@@ -63,10 +60,9 @@ class HasMany extends EloquentHasMany
/** /**
* Add the constraints for a relationship query. * Add the constraints for a relationship query.
* * @param Builder $query
* @param Builder $query * @param Builder $parent
* @param Builder $parent * @param array|mixed $columns
* @param array|mixed $columns
* @return Builder * @return Builder
*/ */
public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*']) public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*'])
...@@ -77,4 +73,15 @@ class HasMany extends EloquentHasMany ...@@ -77,4 +73,15 @@ class HasMany extends EloquentHasMany
return $query->where($this->getHasCompareKey(), 'exists', true); return $query->where($this->getHasCompareKey(), 'exists', true);
} }
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
} }
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
namespace Jenssegers\Mongodb\Relations; namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\HasOne as EloquentHasOne; use Illuminate\Database\Eloquent\Relations\HasOne as EloquentHasOne;
class HasOne extends EloquentHasOne class HasOne extends EloquentHasOne
{ {
/** /**
* Get the key for comparing against the parent key in "has" query. * Get the key for comparing against the parent key in "has" query.
*
* @return string * @return string
*/ */
public function getForeignKeyName() public function getForeignKeyName()
...@@ -19,7 +19,6 @@ class HasOne extends EloquentHasOne ...@@ -19,7 +19,6 @@ class HasOne extends EloquentHasOne
/** /**
* Get the key for comparing against the parent key in "has" query. * Get the key for comparing against the parent key in "has" query.
*
* @return string * @return string
*/ */
public function getHasCompareKey() public function getHasCompareKey()
...@@ -29,7 +28,6 @@ class HasOne extends EloquentHasOne ...@@ -29,7 +28,6 @@ class HasOne extends EloquentHasOne
/** /**
* Get the plain foreign key. * Get the plain foreign key.
*
* @return string * @return string
*/ */
public function getPlainForeignKey() public function getPlainForeignKey()
...@@ -49,9 +47,8 @@ class HasOne extends EloquentHasOne ...@@ -49,9 +47,8 @@ class HasOne extends EloquentHasOne
/** /**
* Add the constraints for a relationship count query. * Add the constraints for a relationship count query.
* * @param Builder $query
* @param Builder $query * @param Builder $parent
* @param Builder $parent
* @return Builder * @return Builder
*/ */
public function getRelationCountQuery(Builder $query, Builder $parent) public function getRelationCountQuery(Builder $query, Builder $parent)
...@@ -63,10 +60,9 @@ class HasOne extends EloquentHasOne ...@@ -63,10 +60,9 @@ class HasOne extends EloquentHasOne
/** /**
* Add the constraints for a relationship query. * Add the constraints for a relationship query.
* * @param Builder $query
* @param Builder $query * @param Builder $parent
* @param Builder $parent * @param array|mixed $columns
* @param array|mixed $columns
* @return Builder * @return Builder
*/ */
public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*']) public function getRelationQuery(Builder $query, Builder $parent, $columns = ['*'])
...@@ -77,4 +73,15 @@ class HasOne extends EloquentHasOne ...@@ -77,4 +73,15 @@ class HasOne extends EloquentHasOne
return $query->where($this->getForeignKeyName(), 'exists', true); return $query->where($this->getForeignKeyName(), 'exists', true);
} }
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
} }
<?php
namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\MorphMany as EloquentMorphMany;
class MorphMany extends EloquentMorphMany
{
/**
* Get the name of the "where in" method for eager loading.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
*
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace Jenssegers\Mongodb\Relations; namespace Jenssegers\Mongodb\Relations;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\Relations\MorphTo as EloquentMorphTo; use Illuminate\Database\Eloquent\Relations\MorphTo as EloquentMorphTo;
class MorphTo extends EloquentMorphTo class MorphTo extends EloquentMorphTo
...@@ -35,11 +36,21 @@ class MorphTo extends EloquentMorphTo ...@@ -35,11 +36,21 @@ class MorphTo extends EloquentMorphTo
/** /**
* Get the owner key with backwards compatible support. * Get the owner key with backwards compatible support.
*
* @return string * @return string
*/ */
public function getOwnerKey() public function getOwnerKey()
{ {
return property_exists($this, 'ownerKey') ? $this->ownerKey : $this->otherKey; return property_exists($this, 'ownerKey') ? $this->ownerKey : $this->otherKey;
} }
/**
* Get the name of the "where in" method for eager loading.
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @return string
*/
protected function whereInMethod(EloquentModel $model, $key)
{
return 'whereIn';
}
} }
...@@ -8,21 +8,18 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -8,21 +8,18 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
{ {
/** /**
* The MongoConnection object for this blueprint. * The MongoConnection object for this blueprint.
*
* @var \Jenssegers\Mongodb\Connection * @var \Jenssegers\Mongodb\Connection
*/ */
protected $connection; protected $connection;
/** /**
* The MongoCollection object for this blueprint. * The MongoCollection object for this blueprint.
*
* @var \Jenssegers\Mongodb\Collection|\MongoDB\Collection * @var \Jenssegers\Mongodb\Collection|\MongoDB\Collection
*/ */
protected $collection; protected $collection;
/** /**
* Fluent columns. * Fluent columns.
*
* @var array * @var array
*/ */
protected $columns = []; protected $columns = [];
...@@ -77,6 +74,54 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -77,6 +74,54 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
* @inheritdoc * @inheritdoc
*/ */
public function dropIndex($indexOrColumns = null) public function dropIndex($indexOrColumns = null)
{
$indexOrColumns = $this->transformColumns($indexOrColumns);
$this->collection->dropIndex($indexOrColumns);
return $this;
}
/**
* Indicate that the given index should be dropped, but do not fail if it didn't exist.
*
* @param string|array $indexOrColumns
* @return Blueprint
*/
public function dropIndexIfExists($indexOrColumns = null)
{
if ($this->hasIndex($indexOrColumns)) {
$this->dropIndex($indexOrColumns);
}
return $this;
}
/**
* Check whether the given index exists.
*
* @param string|array $indexOrColumns
* @return bool
*/
public function hasIndex($indexOrColumns = null)
{
$indexOrColumns = $this->transformColumns($indexOrColumns);
foreach ($this->collection->listIndexes() as $index) {
if (is_array($indexOrColumns) && in_array($index->getName(), $indexOrColumns)) {
return true;
}
if (is_string($indexOrColumns) && $index->getName() == $indexOrColumns) {
return true;
}
}
return false;
}
/**
* @param string|array $indexOrColumns
* @return string
*/
protected function transformColumns($indexOrColumns)
{ {
if (is_array($indexOrColumns)) { if (is_array($indexOrColumns)) {
$indexOrColumns = $this->fluent($indexOrColumns); $indexOrColumns = $this->fluent($indexOrColumns);
...@@ -84,16 +129,23 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -84,16 +129,23 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
// Transform the columns to the index name. // Transform the columns to the index name.
$transform = []; $transform = [];
foreach ($indexOrColumns as $column) { foreach ($indexOrColumns as $key => $value) {
$transform[$column] = $column . '_1'; if (is_int($key)) {
// There is no sorting order, use the default.
$column = $value;
$sorting = '1';
} else {
// This is a column with sorting order e.g 'my_column' => -1.
$column = $key;
$sorting = $value;
}
$transform[$column] = $column . "_" . $sorting;
} }
$indexOrColumns = join('_', $transform); $indexOrColumns = implode('_', $transform);
} }
return $indexOrColumns;
$this->collection->dropIndex($indexOrColumns);
return $this;
} }
/** /**
...@@ -112,8 +164,7 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -112,8 +164,7 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
/** /**
* Specify a non blocking index for the collection. * Specify a non blocking index for the collection.
* * @param string|array $columns
* @param string|array $columns
* @return Blueprint * @return Blueprint
*/ */
public function background($columns = null) public function background($columns = null)
...@@ -127,9 +178,8 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -127,9 +178,8 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
/** /**
* Specify a sparse index for the collection. * Specify a sparse index for the collection.
* * @param string|array $columns
* @param string|array $columns * @param array $options
* @param array $options
* @return Blueprint * @return Blueprint
*/ */
public function sparse($columns = null, $options = []) public function sparse($columns = null, $options = [])
...@@ -145,10 +195,9 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -145,10 +195,9 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
/** /**
* Specify a geospatial index for the collection. * Specify a geospatial index for the collection.
* * @param string|array $columns
* @param string|array $columns * @param string $index
* @param string $index * @param array $options
* @param array $options
* @return Blueprint * @return Blueprint
*/ */
public function geospatial($columns = null, $index = '2d', $options = []) public function geospatial($columns = null, $index = '2d', $options = [])
...@@ -171,9 +220,8 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -171,9 +220,8 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
/** /**
* Specify the number of seconds after wich a document should be considered expired based, * Specify the number of seconds after wich a document should be considered expired based,
* on the given single-field index containing a date. * on the given single-field index containing a date.
* * @param string|array $columns
* @param string|array $columns * @param int $seconds
* @param int $seconds
* @return Blueprint * @return Blueprint
*/ */
public function expire($columns, $seconds) public function expire($columns, $seconds)
...@@ -218,9 +266,8 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -218,9 +266,8 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
/** /**
* Specify a sparse and unique index for the collection. * Specify a sparse and unique index for the collection.
* * @param string|array $columns
* @param string|array $columns * @param array $options
* @param array $options
* @return Blueprint * @return Blueprint
*/ */
public function sparse_and_unique($columns = null, $options = []) public function sparse_and_unique($columns = null, $options = [])
...@@ -237,13 +284,12 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -237,13 +284,12 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
/** /**
* Allow fluent columns. * Allow fluent columns.
* * @param string|array $columns
* @param string|array $columns
* @return string|array * @return string|array
*/ */
protected function fluent($columns = null) protected function fluent($columns = null)
{ {
if (is_null($columns)) { if ($columns === null) {
return $this->columns; return $this->columns;
} elseif (is_string($columns)) { } elseif (is_string($columns)) {
return $this->columns = [$columns]; return $this->columns = [$columns];
...@@ -254,7 +300,6 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint ...@@ -254,7 +300,6 @@ class Blueprint extends \Illuminate\Database\Schema\Blueprint
/** /**
* Allows the use of unsupported schema methods. * Allows the use of unsupported schema methods.
*
* @param $method * @param $method
* @param $args * @param $args
* @return Blueprint * @return Blueprint
......
...@@ -33,8 +33,7 @@ class Builder extends \Illuminate\Database\Schema\Builder ...@@ -33,8 +33,7 @@ class Builder extends \Illuminate\Database\Schema\Builder
/** /**
* Determine if the given collection exists. * Determine if the given collection exists.
* * @param string $collection
* @param string $collection
* @return bool * @return bool
*/ */
public function hasCollection($collection) public function hasCollection($collection)
...@@ -60,9 +59,8 @@ class Builder extends \Illuminate\Database\Schema\Builder ...@@ -60,9 +59,8 @@ class Builder extends \Illuminate\Database\Schema\Builder
/** /**
* Modify a collection on the schema. * Modify a collection on the schema.
* * @param string $collection
* @param string $collection * @param Closure $callback
* @param Closure $callback
* @return bool * @return bool
*/ */
public function collection($collection, Closure $callback) public function collection($collection, Closure $callback)
...@@ -85,11 +83,11 @@ class Builder extends \Illuminate\Database\Schema\Builder ...@@ -85,11 +83,11 @@ class Builder extends \Illuminate\Database\Schema\Builder
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function create($collection, Closure $callback = null) public function create($collection, Closure $callback = null, array $options = [])
{ {
$blueprint = $this->createBlueprint($collection); $blueprint = $this->createBlueprint($collection);
$blueprint->create(); $blueprint->create($options);
if ($callback) { if ($callback) {
$callback($blueprint); $callback($blueprint);
...@@ -138,7 +136,6 @@ class Builder extends \Illuminate\Database\Schema\Builder ...@@ -138,7 +136,6 @@ class Builder extends \Illuminate\Database\Schema\Builder
/** /**
* Get all of the collections names for the database. * Get all of the collections names for the database.
*
* @return array * @return array
*/ */
protected function getAllCollections() protected function getAllCollections()
......
...@@ -6,20 +6,19 @@ class DatabasePresenceVerifier extends \Illuminate\Validation\DatabasePresenceVe ...@@ -6,20 +6,19 @@ class DatabasePresenceVerifier extends \Illuminate\Validation\DatabasePresenceVe
{ {
/** /**
* Count the number of objects in a collection having the given value. * Count the number of objects in a collection having the given value.
* * @param string $collection
* @param string $collection * @param string $column
* @param string $column * @param string $value
* @param string $value * @param int $excludeId
* @param int $excludeId * @param string $idColumn
* @param string $idColumn * @param array $extra
* @param array $extra
* @return int * @return int
*/ */
public function getCount($collection, $column, $value, $excludeId = null, $idColumn = null, array $extra = []) public function getCount($collection, $column, $value, $excludeId = null, $idColumn = null, array $extra = [])
{ {
$query = $this->table($collection)->where($column, 'regex', "/$value/i"); $query = $this->table($collection)->where($column, 'regex', "/$value/i");
if (!is_null($excludeId) && $excludeId != 'NULL') { if ($excludeId !== null && $excludeId != 'NULL') {
$query->where($idColumn ?: 'id', '<>', $excludeId); $query->where($idColumn ?: 'id', '<>', $excludeId);
} }
...@@ -32,11 +31,10 @@ class DatabasePresenceVerifier extends \Illuminate\Validation\DatabasePresenceVe ...@@ -32,11 +31,10 @@ class DatabasePresenceVerifier extends \Illuminate\Validation\DatabasePresenceVe
/** /**
* Count the number of objects in a collection with the given values. * Count the number of objects in a collection with the given values.
* * @param string $collection
* @param string $collection * @param string $column
* @param string $column * @param array $values
* @param array $values * @param array $extra
* @param array $extra
* @return int * @return int
*/ */
public function getMultiCount($collection, $column, array $values, array $extra = []) public function getMultiCount($collection, $column, array $values, array $extra = [])
......
...@@ -2,11 +2,13 @@ ...@@ -2,11 +2,13 @@
use Illuminate\Auth\Passwords\PasswordBroker; use Illuminate\Auth\Passwords\PasswordBroker;
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use MongoDB\BSON\UTCDateTime;
class AuthTest extends TestCase class AuthTest extends TestCase
{ {
public function tearDown() public function tearDown(): void
{ {
parent::setUp();
User::truncate(); User::truncate();
DB::collection('password_reminders')->truncate(); DB::collection('password_reminders')->truncate();
} }
...@@ -14,8 +16,8 @@ class AuthTest extends TestCase ...@@ -14,8 +16,8 @@ class AuthTest extends TestCase
public function testAuthAttempt() public function testAuthAttempt()
{ {
$user = User::create([ $user = User::create([
'name' => 'John Doe', 'name' => 'John Doe',
'email' => 'john@doe.com', 'email' => 'john@doe.com',
'password' => Hash::make('foobar'), 'password' => Hash::make('foobar'),
]); ]);
...@@ -26,6 +28,7 @@ class AuthTest extends TestCase ...@@ -26,6 +28,7 @@ class AuthTest extends TestCase
public function testRemindOld() public function testRemindOld()
{ {
if (Application::VERSION >= '5.2') { if (Application::VERSION >= '5.2') {
$this->expectNotToPerformAssertions();
return; return;
} }
...@@ -36,8 +39,8 @@ class AuthTest extends TestCase ...@@ -36,8 +39,8 @@ class AuthTest extends TestCase
$broker = new PasswordBroker($tokens, $users, $mailer, ''); $broker = new PasswordBroker($tokens, $users, $mailer, '');
$user = User::create([ $user = User::create([
'name' => 'John Doe', 'name' => 'John Doe',
'email' => 'john@doe.com', 'email' => 'john@doe.com',
'password' => Hash::make('foobar'), 'password' => Hash::make('foobar'),
]); ]);
...@@ -48,13 +51,13 @@ class AuthTest extends TestCase ...@@ -48,13 +51,13 @@ class AuthTest extends TestCase
$reminder = DB::collection('password_resets')->first(); $reminder = DB::collection('password_resets')->first();
$this->assertEquals('john@doe.com', $reminder['email']); $this->assertEquals('john@doe.com', $reminder['email']);
$this->assertNotNull($reminder['token']); $this->assertNotNull($reminder['token']);
$this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $reminder['created_at']); $this->assertInstanceOf(UTCDateTime::class, $reminder['created_at']);
$credentials = [ $credentials = [
'email' => 'john@doe.com', 'email' => 'john@doe.com',
'password' => 'foobar', 'password' => 'foobar',
'password_confirmation' => 'foobar', 'password_confirmation' => 'foobar',
'token' => $reminder['token'], 'token' => $reminder['token'],
]; ];
$response = $broker->reset($credentials, function ($user, $password) { $response = $broker->reset($credentials, function ($user, $password) {
......
<?php <?php
declare(strict_types=1);
use Jenssegers\Mongodb\Connection;
use Jenssegers\Mongodb\Collection; use Jenssegers\Mongodb\Collection;
use MongoDB\Collection as MongoCollection; use Jenssegers\Mongodb\Connection;
use MongoDB\BSON\ObjectID; use MongoDB\BSON\ObjectID;
use MongoDB\Collection as MongoCollection;
class CollectionTest extends TestCase class CollectionTest extends TestCase
{ {
......
<?php <?php
declare(strict_types=1);
use Illuminate\Support\Facades\DB;
class ConnectionTest extends TestCase class ConnectionTest extends TestCase
{ {
public function testConnection() public function testConnection()
{ {
$connection = DB::connection('mongodb'); $connection = DB::connection('mongodb');
$this->assertInstanceOf('Jenssegers\Mongodb\Connection', $connection); $this->assertInstanceOf(\Jenssegers\Mongodb\Connection::class, $connection);
} }
public function testReconnect() public function testReconnect()
...@@ -23,28 +26,28 @@ class ConnectionTest extends TestCase ...@@ -23,28 +26,28 @@ class ConnectionTest extends TestCase
public function testDb() public function testDb()
{ {
$connection = DB::connection('mongodb'); $connection = DB::connection('mongodb');
$this->assertInstanceOf('MongoDB\Database', $connection->getMongoDB()); $this->assertInstanceOf(\MongoDB\Database::class, $connection->getMongoDB());
$connection = DB::connection('mongodb'); $connection = DB::connection('mongodb');
$this->assertInstanceOf('MongoDB\Client', $connection->getMongoClient()); $this->assertInstanceOf(\MongoDB\Client::class, $connection->getMongoClient());
} }
public function testCollection() public function testCollection()
{ {
$collection = DB::connection('mongodb')->getCollection('unittest'); $collection = DB::connection('mongodb')->getCollection('unittest');
$this->assertInstanceOf('Jenssegers\Mongodb\Collection', $collection); $this->assertInstanceOf(Jenssegers\Mongodb\Collection::class, $collection);
$collection = DB::connection('mongodb')->collection('unittests'); $collection = DB::connection('mongodb')->collection('unittests');
$this->assertInstanceOf('Jenssegers\Mongodb\Query\Builder', $collection); $this->assertInstanceOf(Jenssegers\Mongodb\Query\Builder::class, $collection);
$collection = DB::connection('mongodb')->table('unittests'); $collection = DB::connection('mongodb')->table('unittests');
$this->assertInstanceOf('Jenssegers\Mongodb\Query\Builder', $collection); $this->assertInstanceOf(Jenssegers\Mongodb\Query\Builder::class, $collection);
} }
// public function testDynamic() // public function testDynamic()
// { // {
// $dbs = DB::connection('mongodb')->listCollections(); // $dbs = DB::connection('mongodb')->listCollections();
// $this->assertInternalType('array', $dbs); // $this->assertIsArray($dbs);
// } // }
// public function testMultipleConnections() // public function testMultipleConnections()
...@@ -87,7 +90,7 @@ class ConnectionTest extends TestCase ...@@ -87,7 +90,7 @@ class ConnectionTest extends TestCase
public function testSchemaBuilder() public function testSchemaBuilder()
{ {
$schema = DB::connection('mongodb')->getSchemaBuilder(); $schema = DB::connection('mongodb')->getSchemaBuilder();
$this->assertInstanceOf('Jenssegers\Mongodb\Schema\Builder', $schema); $this->assertInstanceOf(\Jenssegers\Mongodb\Schema\Builder::class, $schema);
} }
public function testDriverName() public function testDriverName()
......
<?php <?php
declare(strict_types=1);
class DsnTest extends TestCase class DsnTest extends TestCase
{ {
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Events\Dispatcher;
use MongoDB\BSON\ObjectId;
class EmbeddedRelationsTest extends TestCase class EmbeddedRelationsTest extends TestCase
{ {
public function tearDown() public function tearDown(): void
{ {
Mockery::close(); Mockery::close();
...@@ -20,38 +25,50 @@ class EmbeddedRelationsTest extends TestCase ...@@ -20,38 +25,50 @@ class EmbeddedRelationsTest extends TestCase
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$address = new Address(['city' => 'London']); $address = new Address(['city' => 'London']);
$address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($address), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(true); $events->shouldReceive('until')
$events->shouldReceive('until')->once()->with('eloquent.creating: ' . get_class($address), $address)->andReturn(true); ->once()
$events->shouldReceive('fire')->once()->with('eloquent.created: ' . get_class($address), $address); ->with('eloquent.saving: ' . get_class($address), $address)
$events->shouldReceive('fire')->once()->with('eloquent.saved: ' . get_class($address), $address); ->andReturn(true);
$events->shouldReceive('until')
->once()
->with('eloquent.creating: ' . get_class($address), $address)
->andReturn(true);
$events->shouldReceive('dispatch')->once()->with('eloquent.created: ' . get_class($address), $address);
$events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($address), $address);
$address = $user->addresses()->save($address); $address = $user->addresses()->save($address);
$address->unsetEventDispatcher(); $address->unsetEventDispatcher();
$this->assertNotNull($user->addresses); $this->assertNotNull($user->addresses);
$this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $user->addresses); $this->assertInstanceOf(\Illuminate\Database\Eloquent\Collection::class, $user->addresses);
$this->assertEquals(['London'], $user->addresses->pluck('city')->all()); $this->assertEquals(['London'], $user->addresses->pluck('city')->all());
$this->assertInstanceOf('DateTime', $address->created_at); $this->assertInstanceOf(DateTime::class, $address->created_at);
$this->assertInstanceOf('DateTime', $address->updated_at); $this->assertInstanceOf(DateTime::class, $address->updated_at);
$this->assertNotNull($address->_id); $this->assertNotNull($address->_id);
$this->assertInternalType('string', $address->_id); $this->assertIsString($address->_id);
$raw = $address->getAttributes(); $raw = $address->getAttributes();
$this->assertInstanceOf('MongoDB\BSON\ObjectID', $raw['_id']); $this->assertInstanceOf(ObjectId::class, $raw['_id']);
$address = $user->addresses()->save(new Address(['city' => 'Paris'])); $address = $user->addresses()->save(new Address(['city' => 'Paris']));
$user = User::find($user->_id); $user = User::find($user->_id);
$this->assertEquals(['London', 'Paris'], $user->addresses->pluck('city')->all()); $this->assertEquals(['London', 'Paris'], $user->addresses->pluck('city')->all());
$address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($address), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(true); $events->shouldReceive('until')
$events->shouldReceive('until')->once()->with('eloquent.updating: ' . get_class($address), $address)->andReturn(true); ->once()
$events->shouldReceive('fire')->once()->with('eloquent.updated: ' . get_class($address), $address); ->with('eloquent.saving: ' . get_class($address), $address)
$events->shouldReceive('fire')->once()->with('eloquent.saved: ' . get_class($address), $address); ->andReturn(true);
$events->shouldReceive('until')
->once()
->with('eloquent.updating: ' . get_class($address), $address)
->andReturn(true);
$events->shouldReceive('dispatch')->once()->with('eloquent.updated: ' . get_class($address), $address);
$events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($address), $address);
$address->city = 'New York'; $address->city = 'New York';
$user->addresses()->save($address); $user->addresses()->save($address);
...@@ -68,9 +85,9 @@ class EmbeddedRelationsTest extends TestCase ...@@ -68,9 +85,9 @@ class EmbeddedRelationsTest extends TestCase
$address = $user->addresses->first(); $address = $user->addresses->first();
$this->assertEquals('London', $address->city); $this->assertEquals('London', $address->city);
$this->assertInstanceOf('DateTime', $address->created_at); $this->assertInstanceOf(DateTime::class, $address->created_at);
$this->assertInstanceOf('DateTime', $address->updated_at); $this->assertInstanceOf(DateTime::class, $address->updated_at);
$this->assertInstanceOf('User', $address->user); $this->assertInstanceOf(User::class, $address->user);
$this->assertEmpty($address->relationsToArray()); // prevent infinite loop $this->assertEmpty($address->relationsToArray()); // prevent infinite loop
$user = User::find($user->_id); $user = User::find($user->_id);
...@@ -91,19 +108,19 @@ class EmbeddedRelationsTest extends TestCase ...@@ -91,19 +108,19 @@ class EmbeddedRelationsTest extends TestCase
// $user = User::create(['name' => 'John Doe']); // $user = User::create(['name' => 'John Doe']);
// $address = new Address(['city' => 'London']); // $address = new Address(['city' => 'London']);
// $address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); // $address->setEventDispatcher($events = Mockery::mock(\Illuminate\Events\Dispatcher::class));
// $events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(true); // $events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(true);
// $events->shouldReceive('until')->once()->with('eloquent.creating: ' . get_class($address), $address)->andReturn(true); // $events->shouldReceive('until')->once()->with('eloquent.creating: ' . get_class($address), $address)->andReturn(true);
// $events->shouldReceive('fire')->once()->with('eloquent.created: ' . get_class($address), $address); // $events->shouldReceive('dispatch')->once()->with('eloquent.created: ' . get_class($address), $address);
// $events->shouldReceive('fire')->once()->with('eloquent.saved: ' . get_class($address), $address); // $events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($address), $address);
// $address->save(); // $address->save();
// $address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); // $address->setEventDispatcher($events = Mockery::mock(\Illuminate\Events\Dispatcher::class));
// $events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(true); // $events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(true);
// $events->shouldReceive('until')->once()->with('eloquent.updating: ' . get_class($address), $address)->andReturn(true); // $events->shouldReceive('until')->once()->with('eloquent.updating: ' . get_class($address), $address)->andReturn(true);
// $events->shouldReceive('fire')->once()->with('eloquent.updated: ' . get_class($address), $address); // $events->shouldReceive('dispatch')->once()->with('eloquent.updated: ' . get_class($address), $address);
// $events->shouldReceive('fire')->once()->with('eloquent.saved: ' . get_class($address), $address); // $events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($address), $address);
// $address->city = 'Paris'; // $address->city = 'Paris';
// $address->save(); // $address->save();
...@@ -175,29 +192,29 @@ class EmbeddedRelationsTest extends TestCase ...@@ -175,29 +192,29 @@ class EmbeddedRelationsTest extends TestCase
{ {
$user = User::create([]); $user = User::create([]);
$address = $user->addresses()->create(['city' => 'Bruxelles']); $address = $user->addresses()->create(['city' => 'Bruxelles']);
$this->assertInstanceOf('Address', $address); $this->assertInstanceOf(Address::class, $address);
$this->assertInternalType('string', $address->_id); $this->assertIsString($address->_id);
$this->assertEquals(['Bruxelles'], $user->addresses->pluck('city')->all()); $this->assertEquals(['Bruxelles'], $user->addresses->pluck('city')->all());
$raw = $address->getAttributes(); $raw = $address->getAttributes();
$this->assertInstanceOf('MongoDB\BSON\ObjectID', $raw['_id']); $this->assertInstanceOf(ObjectId::class, $raw['_id']);
$freshUser = User::find($user->id); $freshUser = User::find($user->id);
$this->assertEquals(['Bruxelles'], $freshUser->addresses->pluck('city')->all()); $this->assertEquals(['Bruxelles'], $freshUser->addresses->pluck('city')->all());
$user = User::create([]); $user = User::create([]);
$address = $user->addresses()->create(['_id' => '', 'city' => 'Bruxelles']); $address = $user->addresses()->create(['_id' => '', 'city' => 'Bruxelles']);
$this->assertInternalType('string', $address->_id); $this->assertIsString($address->_id);
$raw = $address->getAttributes(); $raw = $address->getAttributes();
$this->assertInstanceOf('MongoDB\BSON\ObjectID', $raw['_id']); $this->assertInstanceOf(ObjectId::class, $raw['_id']);
} }
public function testEmbedsManyCreateMany() public function testEmbedsManyCreateMany()
{ {
$user = User::create([]); $user = User::create([]);
list($bruxelles, $paris) = $user->addresses()->createMany([['city' => 'Bruxelles'], ['city' => 'Paris']]); list($bruxelles, $paris) = $user->addresses()->createMany([['city' => 'Bruxelles'], ['city' => 'Paris']]);
$this->assertInstanceOf('Address', $bruxelles); $this->assertInstanceOf(Address::class, $bruxelles);
$this->assertEquals('Bruxelles', $bruxelles->city); $this->assertEquals('Bruxelles', $bruxelles->city);
$this->assertEquals(['Bruxelles', 'Paris'], $user->addresses->pluck('city')->all()); $this->assertEquals(['Bruxelles', 'Paris'], $user->addresses->pluck('city')->all());
...@@ -208,14 +225,23 @@ class EmbeddedRelationsTest extends TestCase ...@@ -208,14 +225,23 @@ class EmbeddedRelationsTest extends TestCase
public function testEmbedsManyDestroy() public function testEmbedsManyDestroy()
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$user->addresses()->saveMany([new Address(['city' => 'London']), new Address(['city' => 'Bristol']), new Address(['city' => 'Bruxelles'])]); $user->addresses()->saveMany([
new Address(['city' => 'London']),
new Address(['city' => 'Bristol']),
new Address(['city' => 'Bruxelles']),
]);
$address = $user->addresses->first(); $address = $user->addresses->first();
$address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($address), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.deleting: ' . get_class($address), Mockery::type('Address'))->andReturn(true); $events->shouldReceive('until')
$events->shouldReceive('fire')->once()->with('eloquent.deleted: ' . get_class($address), Mockery::type('Address')); ->once()
->with('eloquent.deleting: ' . get_class($address), Mockery::type(Address::class))
->andReturn(true);
$events->shouldReceive('dispatch')
->once()
->with('eloquent.deleted: ' . get_class($address), Mockery::type(Address::class));
$user->addresses()->destroy($address->_id); $user->addresses()->destroy($address->_id);
$this->assertEquals(['Bristol', 'Bruxelles'], $user->addresses->pluck('city')->all()); $this->assertEquals(['Bristol', 'Bruxelles'], $user->addresses->pluck('city')->all());
...@@ -239,7 +265,11 @@ class EmbeddedRelationsTest extends TestCase ...@@ -239,7 +265,11 @@ class EmbeddedRelationsTest extends TestCase
$freshUser = User::find($user->id); $freshUser = User::find($user->id);
$this->assertEquals([], $freshUser->addresses->pluck('city')->all()); $this->assertEquals([], $freshUser->addresses->pluck('city')->all());
list($london, $bristol, $bruxelles) = $user->addresses()->saveMany([new Address(['city' => 'London']), new Address(['city' => 'Bristol']), new Address(['city' => 'Bruxelles'])]); list($london, $bristol, $bruxelles) = $user->addresses()->saveMany([
new Address(['city' => 'London']),
new Address(['city' => 'Bristol']),
new Address(['city' => 'Bruxelles']),
]);
$user->addresses()->destroy([$london, $bruxelles]); $user->addresses()->destroy([$london, $bruxelles]);
$this->assertEquals(['Bristol'], $user->addresses->pluck('city')->all()); $this->assertEquals(['Bristol'], $user->addresses->pluck('city')->all());
} }
...@@ -247,14 +277,23 @@ class EmbeddedRelationsTest extends TestCase ...@@ -247,14 +277,23 @@ class EmbeddedRelationsTest extends TestCase
public function testEmbedsManyDelete() public function testEmbedsManyDelete()
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$user->addresses()->saveMany([new Address(['city' => 'London']), new Address(['city' => 'Bristol']), new Address(['city' => 'Bruxelles'])]); $user->addresses()->saveMany([
new Address(['city' => 'London']),
new Address(['city' => 'Bristol']),
new Address(['city' => 'Bruxelles']),
]);
$address = $user->addresses->first(); $address = $user->addresses->first();
$address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($address), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.deleting: ' . get_class($address), Mockery::type('Address'))->andReturn(true); $events->shouldReceive('until')
$events->shouldReceive('fire')->once()->with('eloquent.deleted: ' . get_class($address), Mockery::type('Address')); ->once()
->with('eloquent.deleting: ' . get_class($address), Mockery::type(Address::class))
->andReturn(true);
$events->shouldReceive('dispatch')
->once()
->with('eloquent.deleted: ' . get_class($address), Mockery::type(Address::class));
$address->delete(); $address->delete();
...@@ -300,10 +339,16 @@ class EmbeddedRelationsTest extends TestCase ...@@ -300,10 +339,16 @@ class EmbeddedRelationsTest extends TestCase
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$address = new Address(['city' => 'London']); $address = new Address(['city' => 'London']);
$address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($address), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(true); $events->shouldReceive('until')
$events->shouldReceive('until')->once()->with('eloquent.creating: ' . get_class($address), $address)->andReturn(false); ->once()
->with('eloquent.saving: ' . get_class($address), $address)
->andReturn(true);
$events->shouldReceive('until')
->once()
->with('eloquent.creating: ' . get_class($address), $address)
->andReturn(false);
$this->assertFalse($user->addresses()->save($address)); $this->assertFalse($user->addresses()->save($address));
$address->unsetEventDispatcher(); $address->unsetEventDispatcher();
...@@ -315,9 +360,12 @@ class EmbeddedRelationsTest extends TestCase ...@@ -315,9 +360,12 @@ class EmbeddedRelationsTest extends TestCase
$address = new Address(['city' => 'Paris']); $address = new Address(['city' => 'Paris']);
$address->exists = true; $address->exists = true;
$address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($address), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(false); $events->shouldReceive('until')
->once()
->with('eloquent.saving: ' . get_class($address), $address)
->andReturn(false);
$this->assertFalse($user->addresses()->save($address)); $this->assertFalse($user->addresses()->save($address));
$address->unsetEventDispatcher(); $address->unsetEventDispatcher();
...@@ -329,10 +377,16 @@ class EmbeddedRelationsTest extends TestCase ...@@ -329,10 +377,16 @@ class EmbeddedRelationsTest extends TestCase
$address = new Address(['city' => 'New York']); $address = new Address(['city' => 'New York']);
$user->addresses()->save($address); $user->addresses()->save($address);
$address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($address), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($address), $address)->andReturn(true); $events->shouldReceive('until')
$events->shouldReceive('until')->once()->with('eloquent.updating: ' . get_class($address), $address)->andReturn(false); ->once()
->with('eloquent.saving: ' . get_class($address), $address)
->andReturn(true);
$events->shouldReceive('until')
->once()
->with('eloquent.updating: ' . get_class($address), $address)
->andReturn(false);
$address->city = 'Warsaw'; $address->city = 'Warsaw';
...@@ -347,9 +401,12 @@ class EmbeddedRelationsTest extends TestCase ...@@ -347,9 +401,12 @@ class EmbeddedRelationsTest extends TestCase
$address = $user->addresses->first(); $address = $user->addresses->first();
$address->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $address->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($address), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($address), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.deleting: ' . get_class($address), Mockery::mustBe($address))->andReturn(false); $events->shouldReceive('until')
->once()
->with('eloquent.deleting: ' . get_class($address), Mockery::mustBe($address))
->andReturn(false);
$this->assertEquals(0, $user->addresses()->destroy($address)); $this->assertEquals(0, $user->addresses()->destroy($address));
$this->assertEquals(['New York'], $user->addresses->pluck('city')->all()); $this->assertEquals(['New York'], $user->addresses->pluck('city')->all());
...@@ -387,14 +444,14 @@ class EmbeddedRelationsTest extends TestCase ...@@ -387,14 +444,14 @@ class EmbeddedRelationsTest extends TestCase
$relations = $user->getRelations(); $relations = $user->getRelations();
$this->assertArrayNotHasKey('addresses', $relations); $this->assertArrayNotHasKey('addresses', $relations);
$this->assertArrayHasKey('addresses', $user->toArray()); $this->assertArrayHasKey('addresses', $user->toArray());
$this->assertInternalType('array', $user->toArray()['addresses']); $this->assertIsArray($user->toArray()['addresses']);
$user = User::with('addresses')->get()->first(); $user = User::with('addresses')->get()->first();
$relations = $user->getRelations(); $relations = $user->getRelations();
$this->assertArrayHasKey('addresses', $relations); $this->assertArrayHasKey('addresses', $relations);
$this->assertEquals(2, $relations['addresses']->count()); $this->assertEquals(2, $relations['addresses']->count());
$this->assertArrayHasKey('addresses', $user->toArray()); $this->assertArrayHasKey('addresses', $user->toArray());
$this->assertInternalType('array', $user->toArray()['addresses']); $this->assertIsArray($user->toArray()['addresses']);
} }
public function testEmbedsManyDeleteAll() public function testEmbedsManyDeleteAll()
...@@ -424,22 +481,52 @@ class EmbeddedRelationsTest extends TestCase ...@@ -424,22 +481,52 @@ class EmbeddedRelationsTest extends TestCase
public function testEmbedsManyCollectionMethods() public function testEmbedsManyCollectionMethods()
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$user->addresses()->save(new Address(['city' => 'Paris', 'country' => 'France', 'visited' => 4, 'created_at' => new DateTime('3 days ago')])); $user->addresses()->save(new Address([
$user->addresses()->save(new Address(['city' => 'Bruges', 'country' => 'Belgium', 'visited' => 7, 'created_at' => new DateTime('5 days ago')])); 'city' => 'Paris',
$user->addresses()->save(new Address(['city' => 'Brussels', 'country' => 'Belgium', 'visited' => 2, 'created_at' => new DateTime('4 days ago')])); 'country' => 'France',
$user->addresses()->save(new Address(['city' => 'Ghent', 'country' => 'Belgium', 'visited' => 13, 'created_at' => new DateTime('2 days ago')])); 'visited' => 4,
'created_at' => new DateTime('3 days ago'),
]));
$user->addresses()->save(new Address([
'city' => 'Bruges',
'country' => 'Belgium',
'visited' => 7,
'created_at' => new DateTime('5 days ago'),
]));
$user->addresses()->save(new Address([
'city' => 'Brussels',
'country' => 'Belgium',
'visited' => 2,
'created_at' => new DateTime('4 days ago'),
]));
$user->addresses()->save(new Address([
'city' => 'Ghent',
'country' => 'Belgium',
'visited' => 13,
'created_at' => new DateTime('2 days ago'),
]));
$this->assertEquals(['Paris', 'Bruges', 'Brussels', 'Ghent'], $user->addresses()->pluck('city')->all()); $this->assertEquals(['Paris', 'Bruges', 'Brussels', 'Ghent'], $user->addresses()->pluck('city')->all());
$this->assertEquals(['Bruges', 'Brussels', 'Ghent', 'Paris'], $user->addresses()->sortBy('city')->pluck('city')->all()); $this->assertEquals(['Bruges', 'Brussels', 'Ghent', 'Paris'], $user->addresses()
->sortBy('city')
->pluck('city')
->all());
$this->assertEquals([], $user->addresses()->where('city', 'New York')->pluck('city')->all()); $this->assertEquals([], $user->addresses()->where('city', 'New York')->pluck('city')->all());
$this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()->where('country', 'Belgium')->pluck('city')->all()); $this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()
$this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()->where('country', 'Belgium')->sortBy('city')->pluck('city')->all()); ->where('country', 'Belgium')
->pluck('city')
->all());
$this->assertEquals(['Bruges', 'Brussels', 'Ghent'], $user->addresses()
->where('country', 'Belgium')
->sortBy('city')
->pluck('city')
->all());
$results = $user->addresses->first(); $results = $user->addresses->first();
$this->assertInstanceOf('Address', $results); $this->assertInstanceOf(Address::class, $results);
$results = $user->addresses()->where('country', 'Belgium'); $results = $user->addresses()->where('country', 'Belgium');
$this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $results); $this->assertInstanceOf(Collection::class, $results);
$this->assertEquals(3, $results->count()); $this->assertEquals(3, $results->count());
$results = $user->addresses()->whereIn('visited', [7, 13]); $results = $user->addresses()->whereIn('visited', [7, 13]);
...@@ -451,32 +538,44 @@ class EmbeddedRelationsTest extends TestCase ...@@ -451,32 +538,44 @@ class EmbeddedRelationsTest extends TestCase
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$father = new User(['name' => 'Mark Doe']); $father = new User(['name' => 'Mark Doe']);
$father->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $father->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($father), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($father), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($father), $father)->andReturn(true); $events->shouldReceive('until')
$events->shouldReceive('until')->once()->with('eloquent.creating: ' . get_class($father), $father)->andReturn(true); ->once()
$events->shouldReceive('fire')->once()->with('eloquent.created: ' . get_class($father), $father); ->with('eloquent.saving: ' . get_class($father), $father)
$events->shouldReceive('fire')->once()->with('eloquent.saved: ' . get_class($father), $father); ->andReturn(true);
$events->shouldReceive('until')
->once()
->with('eloquent.creating: ' . get_class($father), $father)
->andReturn(true);
$events->shouldReceive('dispatch')->once()->with('eloquent.created: ' . get_class($father), $father);
$events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($father), $father);
$father = $user->father()->save($father); $father = $user->father()->save($father);
$father->unsetEventDispatcher(); $father->unsetEventDispatcher();
$this->assertNotNull($user->father); $this->assertNotNull($user->father);
$this->assertEquals('Mark Doe', $user->father->name); $this->assertEquals('Mark Doe', $user->father->name);
$this->assertInstanceOf('DateTime', $father->created_at); $this->assertInstanceOf(DateTime::class, $father->created_at);
$this->assertInstanceOf('DateTime', $father->updated_at); $this->assertInstanceOf(DateTime::class, $father->updated_at);
$this->assertNotNull($father->_id); $this->assertNotNull($father->_id);
$this->assertInternalType('string', $father->_id); $this->assertIsString($father->_id);
$raw = $father->getAttributes(); $raw = $father->getAttributes();
$this->assertInstanceOf('MongoDB\BSON\ObjectID', $raw['_id']); $this->assertInstanceOf(ObjectId::class, $raw['_id']);
$father->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $father->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($father), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($father), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($father), $father)->andReturn(true); $events->shouldReceive('until')
$events->shouldReceive('until')->once()->with('eloquent.updating: ' . get_class($father), $father)->andReturn(true); ->once()
$events->shouldReceive('fire')->once()->with('eloquent.updated: ' . get_class($father), $father); ->with('eloquent.saving: ' . get_class($father), $father)
$events->shouldReceive('fire')->once()->with('eloquent.saved: ' . get_class($father), $father); ->andReturn(true);
$events->shouldReceive('until')
->once()
->with('eloquent.updating: ' . get_class($father), $father)
->andReturn(true);
$events->shouldReceive('dispatch')->once()->with('eloquent.updated: ' . get_class($father), $father);
$events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($father), $father);
$father->name = 'Tom Doe'; $father->name = 'Tom Doe';
$user->father()->save($father); $user->father()->save($father);
...@@ -487,12 +586,18 @@ class EmbeddedRelationsTest extends TestCase ...@@ -487,12 +586,18 @@ class EmbeddedRelationsTest extends TestCase
$father = new User(['name' => 'Jim Doe']); $father = new User(['name' => 'Jim Doe']);
$father->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $father->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($father), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($father), Mockery::any());
$events->shouldReceive('until')->once()->with('eloquent.saving: ' . get_class($father), $father)->andReturn(true); $events->shouldReceive('until')
$events->shouldReceive('until')->once()->with('eloquent.creating: ' . get_class($father), $father)->andReturn(true); ->once()
$events->shouldReceive('fire')->once()->with('eloquent.created: ' . get_class($father), $father); ->with('eloquent.saving: ' . get_class($father), $father)
$events->shouldReceive('fire')->once()->with('eloquent.saved: ' . get_class($father), $father); ->andReturn(true);
$events->shouldReceive('until')
->once()
->with('eloquent.creating: ' . get_class($father), $father)
->andReturn(true);
$events->shouldReceive('dispatch')->once()->with('eloquent.created: ' . get_class($father), $father);
$events->shouldReceive('dispatch')->once()->with('eloquent.saved: ' . get_class($father), $father);
$father = $user->father()->save($father); $father = $user->father()->save($father);
$father->unsetEventDispatcher(); $father->unsetEventDispatcher();
...@@ -506,8 +611,8 @@ class EmbeddedRelationsTest extends TestCase ...@@ -506,8 +611,8 @@ class EmbeddedRelationsTest extends TestCase
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$father = new User(['name' => 'Mark Doe']); $father = new User(['name' => 'Mark Doe']);
$father->setEventDispatcher($events = Mockery::mock('Illuminate\Events\Dispatcher')); $father->setEventDispatcher($events = Mockery::mock(Dispatcher::class));
$events->shouldReceive('fire')->with('eloquent.retrieved: ' . get_class($father), Mockery::any()); $events->shouldReceive('dispatch')->with('eloquent.retrieved: ' . get_class($father), Mockery::any());
$events->shouldReceive('until')->times(0)->with('eloquent.saving: ' . get_class($father), $father); $events->shouldReceive('until')->times(0)->with('eloquent.saving: ' . get_class($father), $father);
$father = $user->father()->associate($father); $father = $user->father()->associate($father);
...@@ -534,6 +639,7 @@ class EmbeddedRelationsTest extends TestCase ...@@ -534,6 +639,7 @@ class EmbeddedRelationsTest extends TestCase
public function testEmbedsManyToArray() public function testEmbedsManyToArray()
{ {
/** @var User $user */
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$user->addresses()->save(new Address(['city' => 'New York'])); $user->addresses()->save(new Address(['city' => 'New York']));
$user->addresses()->save(new Address(['city' => 'Paris'])); $user->addresses()->save(new Address(['city' => 'Paris']));
...@@ -541,12 +647,14 @@ class EmbeddedRelationsTest extends TestCase ...@@ -541,12 +647,14 @@ class EmbeddedRelationsTest extends TestCase
$array = $user->toArray(); $array = $user->toArray();
$this->assertArrayHasKey('addresses', $array); $this->assertArrayHasKey('addresses', $array);
$this->assertInternalType('array', $array['addresses']); $this->assertIsArray($array['addresses']);
} }
public function testEmbeddedSave() public function testEmbeddedSave()
{ {
/** @var User $user */
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
/** @var \Address $address */
$address = $user->addresses()->create(['city' => 'New York']); $address = $user->addresses()->create(['city' => 'New York']);
$father = $user->father()->create(['name' => 'Mark Doe']); $father = $user->father()->create(['name' => 'Mark Doe']);
...@@ -765,4 +873,23 @@ class EmbeddedRelationsTest extends TestCase ...@@ -765,4 +873,23 @@ class EmbeddedRelationsTest extends TestCase
$this->assertEquals(2, $results->count()); $this->assertEquals(2, $results->count());
$this->assertEquals(3, $results->total()); $this->assertEquals(3, $results->total());
} }
public function testGetQueueableRelationsEmbedsMany()
{
$user = User::create(['name' => 'John Doe']);
$user->addresses()->save(new Address(['city' => 'New York']));
$user->addresses()->save(new Address(['city' => 'Paris']));
$this->assertEquals(['addresses'], $user->getQueueableRelations());
$this->assertEquals([], $user->addresses->getQueueableRelations());
}
public function testGetQueueableRelationsEmbedsOne()
{
$user = User::create(['name' => 'John Doe']);
$user->father()->save(new User(['name' => 'Mark Doe']));
$this->assertEquals(['father'], $user->getQueueableRelations());
$this->assertEquals([], $user->father->getQueueableRelations());
}
} }
<?php <?php
declare(strict_types=1);
class GeospatialTest extends TestCase class GeospatialTest extends TestCase
{ {
public function setUp() public function setUp(): void
{ {
parent::setUp(); parent::setUp();
...@@ -43,7 +44,7 @@ class GeospatialTest extends TestCase ...@@ -43,7 +44,7 @@ class GeospatialTest extends TestCase
]); ]);
} }
public function tearDown() public function tearDown(): void
{ {
Schema::drop('locations'); Schema::drop('locations');
} }
...@@ -53,28 +54,30 @@ class GeospatialTest extends TestCase ...@@ -53,28 +54,30 @@ class GeospatialTest extends TestCase
$locations = Location::where('location', 'geoWithin', [ $locations = Location::where('location', 'geoWithin', [
'$geometry' => [ '$geometry' => [
'type' => 'Polygon', 'type' => 'Polygon',
'coordinates' => [[ 'coordinates' => [
[
-0.1450383,
51.5069158,
],
[
-0.1367563,
51.5100913,
],
[
-0.1270247,
51.5013233,
],
[
-0.1460866,
51.4952136,
],
[ [
-0.1450383, [
51.5069158, -0.1450383,
51.5069158,
],
[
-0.1367563,
51.5100913,
],
[
-0.1270247,
51.5013233,
],
[
-0.1460866,
51.4952136,
],
[
-0.1450383,
51.5069158,
],
], ],
]], ],
], ],
]); ]);
...@@ -104,7 +107,7 @@ class GeospatialTest extends TestCase ...@@ -104,7 +107,7 @@ class GeospatialTest extends TestCase
51.5078646, 51.5078646,
], ],
], ],
] ],
]); ]);
$this->assertEquals(1, $locations->count()); $this->assertEquals(1, $locations->count());
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\MySqlConnection;
class HybridRelationsTest extends TestCase class HybridRelationsTest extends TestCase
{ {
public function setUp() public function setUp(): void
{ {
parent::setUp(); parent::setUp();
...@@ -11,7 +14,7 @@ class HybridRelationsTest extends TestCase ...@@ -11,7 +14,7 @@ class HybridRelationsTest extends TestCase
MysqlRole::executeSchema(); MysqlRole::executeSchema();
} }
public function tearDown() public function tearDown(): void
{ {
MysqlUser::truncate(); MysqlUser::truncate();
MysqlBook::truncate(); MysqlBook::truncate();
...@@ -21,13 +24,13 @@ class HybridRelationsTest extends TestCase ...@@ -21,13 +24,13 @@ class HybridRelationsTest extends TestCase
public function testMysqlRelations() public function testMysqlRelations()
{ {
$user = new MysqlUser; $user = new MysqlUser;
$this->assertInstanceOf('MysqlUser', $user); $this->assertInstanceOf(MysqlUser::class, $user);
$this->assertInstanceOf('Illuminate\Database\MySqlConnection', $user->getConnection()); $this->assertInstanceOf(MySqlConnection::class, $user->getConnection());
// Mysql User // Mysql User
$user->name = "John Doe"; $user->name = "John Doe";
$user->save(); $user->save();
$this->assertInternalType('int', $user->id); $this->assertIsInt($user->id);
// SQL has many // SQL has many
$book = new Book(['title' => 'Game of Thrones']); $book = new Book(['title' => 'Game of Thrones']);
...@@ -79,10 +82,10 @@ class HybridRelationsTest extends TestCase ...@@ -79,10 +82,10 @@ class HybridRelationsTest extends TestCase
{ {
$user = new MysqlUser; $user = new MysqlUser;
$otherUser = new MysqlUser; $otherUser = new MysqlUser;
$this->assertInstanceOf('MysqlUser', $user); $this->assertInstanceOf(MysqlUser::class, $user);
$this->assertInstanceOf('Illuminate\Database\MySqlConnection', $user->getConnection()); $this->assertInstanceOf(MySqlConnection::class, $user->getConnection());
$this->assertInstanceOf('MysqlUser', $otherUser); $this->assertInstanceOf(MysqlUser::class, $otherUser);
$this->assertInstanceOf('Illuminate\Database\MySqlConnection', $otherUser->getConnection()); $this->assertInstanceOf(MySqlConnection::class, $otherUser->getConnection());
//MySql User //MySql User
$user->name = "John Doe"; $user->name = "John Doe";
...@@ -93,8 +96,8 @@ class HybridRelationsTest extends TestCase ...@@ -93,8 +96,8 @@ class HybridRelationsTest extends TestCase
$otherUser->id = 3; $otherUser->id = 3;
$otherUser->save(); $otherUser->save();
// Make sure they are created // Make sure they are created
$this->assertInternalType('int', $user->id); $this->assertIsInt($user->id);
$this->assertInternalType('int', $otherUser->id); $this->assertIsInt($otherUser->id);
// Clear to start // Clear to start
$user->books()->truncate(); $user->books()->truncate();
$otherUser->books()->truncate(); $otherUser->books()->truncate();
...@@ -133,10 +136,10 @@ class HybridRelationsTest extends TestCase ...@@ -133,10 +136,10 @@ class HybridRelationsTest extends TestCase
{ {
$user = new MysqlUser; $user = new MysqlUser;
$otherUser = new MysqlUser; $otherUser = new MysqlUser;
$this->assertInstanceOf('MysqlUser', $user); $this->assertInstanceOf(MysqlUser::class, $user);
$this->assertInstanceOf('Illuminate\Database\MySqlConnection', $user->getConnection()); $this->assertInstanceOf(MySqlConnection::class, $user->getConnection());
$this->assertInstanceOf('MysqlUser', $otherUser); $this->assertInstanceOf(MysqlUser::class, $otherUser);
$this->assertInstanceOf('Illuminate\Database\MySqlConnection', $otherUser->getConnection()); $this->assertInstanceOf(MySqlConnection::class, $otherUser->getConnection());
//MySql User //MySql User
$user->name = "John Doe"; $user->name = "John Doe";
...@@ -147,8 +150,8 @@ class HybridRelationsTest extends TestCase ...@@ -147,8 +150,8 @@ class HybridRelationsTest extends TestCase
$otherUser->id = 3; $otherUser->id = 3;
$otherUser->save(); $otherUser->save();
// Make sure they are created // Make sure they are created
$this->assertInternalType('int', $user->id); $this->assertIsInt($user->id);
$this->assertInternalType('int', $otherUser->id); $this->assertIsInt($otherUser->id);
// Clear to start // Clear to start
Book::truncate(); Book::truncate();
MysqlBook::truncate(); MysqlBook::truncate();
......
<?php <?php
declare(strict_types=1);
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Jenssegers\Mongodb\Eloquent\Model; use Jenssegers\Mongodb\Eloquent\Model;
use MongoDB\BSON\ObjectID; use MongoDB\BSON\ObjectID;
use MongoDB\BSON\UTCDateTime; use MongoDB\BSON\UTCDateTime;
class ModelTest extends TestCase class ModelTest extends TestCase
{ {
public function tearDown() public function tearDown(): void
{ {
User::truncate(); User::truncate();
Soft::truncate(); Soft::truncate();
...@@ -16,17 +18,17 @@ class ModelTest extends TestCase ...@@ -16,17 +18,17 @@ class ModelTest extends TestCase
Item::truncate(); Item::truncate();
} }
public function testNewModel() public function testNewModel(): void
{ {
$user = new User; $user = new User;
$this->assertInstanceOf(Model::class, $user); $this->assertInstanceOf(Model::class, $user);
$this->assertInstanceOf('Jenssegers\Mongodb\Connection', $user->getConnection()); $this->assertInstanceOf(\Jenssegers\Mongodb\Connection::class, $user->getConnection());
$this->assertFalse($user->exists); $this->assertFalse($user->exists);
$this->assertEquals('users', $user->getTable()); $this->assertEquals('users', $user->getTable());
$this->assertEquals('_id', $user->getKeyName()); $this->assertEquals('_id', $user->getKeyName());
} }
public function testInsert() public function testInsert(): void
{ {
$user = new User; $user = new User;
$user->name = 'John Doe'; $user->name = 'John Doe';
...@@ -39,7 +41,7 @@ class ModelTest extends TestCase ...@@ -39,7 +41,7 @@ class ModelTest extends TestCase
$this->assertEquals(1, User::count()); $this->assertEquals(1, User::count());
$this->assertTrue(isset($user->_id)); $this->assertTrue(isset($user->_id));
$this->assertInternalType('string', $user->_id); $this->assertIsString($user->_id);
$this->assertNotEquals('', (string) $user->_id); $this->assertNotEquals('', (string) $user->_id);
$this->assertNotEquals(0, strlen((string) $user->_id)); $this->assertNotEquals(0, strlen((string) $user->_id));
$this->assertInstanceOf(Carbon::class, $user->created_at); $this->assertInstanceOf(Carbon::class, $user->created_at);
...@@ -51,7 +53,7 @@ class ModelTest extends TestCase ...@@ -51,7 +53,7 @@ class ModelTest extends TestCase
$this->assertEquals(35, $user->age); $this->assertEquals(35, $user->age);
} }
public function testUpdate() public function testUpdate(): void
{ {
$user = new User; $user = new User;
$user->name = 'John Doe'; $user->name = 'John Doe';
...@@ -62,8 +64,8 @@ class ModelTest extends TestCase ...@@ -62,8 +64,8 @@ class ModelTest extends TestCase
$raw = $user->getAttributes(); $raw = $user->getAttributes();
$this->assertInstanceOf(ObjectID::class, $raw['_id']); $this->assertInstanceOf(ObjectID::class, $raw['_id']);
/** @var User $check */
$check = User::find($user->_id); $check = User::find($user->_id);
$check->age = 36; $check->age = 36;
$check->save(); $check->save();
...@@ -84,7 +86,7 @@ class ModelTest extends TestCase ...@@ -84,7 +86,7 @@ class ModelTest extends TestCase
$this->assertEquals(20, $check->age); $this->assertEquals(20, $check->age);
} }
public function testManualStringId() public function testManualStringId(): void
{ {
$user = new User; $user = new User;
$user->_id = '4af9f23d8ead0e1d32000000'; $user->_id = '4af9f23d8ead0e1d32000000';
...@@ -110,10 +112,10 @@ class ModelTest extends TestCase ...@@ -110,10 +112,10 @@ class ModelTest extends TestCase
$this->assertEquals('customId', $user->_id); $this->assertEquals('customId', $user->_id);
$raw = $user->getAttributes(); $raw = $user->getAttributes();
$this->assertInternalType('string', $raw['_id']); $this->assertIsString($raw['_id']);
} }
public function testManualIntId() public function testManualIntId(): void
{ {
$user = new User; $user = new User;
$user->_id = 1; $user->_id = 1;
...@@ -126,10 +128,10 @@ class ModelTest extends TestCase ...@@ -126,10 +128,10 @@ class ModelTest extends TestCase
$this->assertEquals(1, $user->_id); $this->assertEquals(1, $user->_id);
$raw = $user->getAttributes(); $raw = $user->getAttributes();
$this->assertInternalType('integer', $raw['_id']); $this->assertIsInt($raw['_id']);
} }
public function testDelete() public function testDelete(): void
{ {
$user = new User; $user = new User;
$user->name = 'John Doe'; $user->name = 'John Doe';
...@@ -145,7 +147,7 @@ class ModelTest extends TestCase ...@@ -145,7 +147,7 @@ class ModelTest extends TestCase
$this->assertEquals(0, User::count()); $this->assertEquals(0, User::count());
} }
public function testAll() public function testAll(): void
{ {
$user = new User; $user = new User;
$user->name = 'John Doe'; $user->name = 'John Doe';
...@@ -166,7 +168,7 @@ class ModelTest extends TestCase ...@@ -166,7 +168,7 @@ class ModelTest extends TestCase
$this->assertContains('Jane Doe', $all->pluck('name')); $this->assertContains('Jane Doe', $all->pluck('name'));
} }
public function testFind() public function testFind(): void
{ {
$user = new User; $user = new User;
$user->name = 'John Doe'; $user->name = 'John Doe';
...@@ -174,6 +176,7 @@ class ModelTest extends TestCase ...@@ -174,6 +176,7 @@ class ModelTest extends TestCase
$user->age = 35; $user->age = 35;
$user->save(); $user->save();
/** @var User $check */
$check = User::find($user->_id); $check = User::find($user->_id);
$this->assertInstanceOf(Model::class, $check); $this->assertInstanceOf(Model::class, $check);
...@@ -184,7 +187,7 @@ class ModelTest extends TestCase ...@@ -184,7 +187,7 @@ class ModelTest extends TestCase
$this->assertEquals(35, $check->age); $this->assertEquals(35, $check->age);
} }
public function testGet() public function testGet(): void
{ {
User::insert([ User::insert([
['name' => 'John Doe'], ['name' => 'John Doe'],
...@@ -197,19 +200,20 @@ class ModelTest extends TestCase ...@@ -197,19 +200,20 @@ class ModelTest extends TestCase
$this->assertInstanceOf(Model::class, $users[0]); $this->assertInstanceOf(Model::class, $users[0]);
} }
public function testFirst() public function testFirst(): void
{ {
User::insert([ User::insert([
['name' => 'John Doe'], ['name' => 'John Doe'],
['name' => 'Jane Doe'], ['name' => 'Jane Doe'],
]); ]);
/** @var User $user */
$user = User::first(); $user = User::first();
$this->assertInstanceOf(Model::class, $user); $this->assertInstanceOf(Model::class, $user);
$this->assertEquals('John Doe', $user->name); $this->assertEquals('John Doe', $user->name);
} }
public function testNoDocument() public function testNoDocument(): void
{ {
$items = Item::where('name', 'nothing')->get(); $items = Item::where('name', 'nothing')->get();
$this->assertInstanceOf(Collection::class, $items); $this->assertInstanceOf(Collection::class, $items);
...@@ -222,25 +226,27 @@ class ModelTest extends TestCase ...@@ -222,25 +226,27 @@ class ModelTest extends TestCase
$this->assertNull($item); $this->assertNull($item);
} }
public function testFindOrfail() public function testFindOrFail(): void
{ {
$this->expectException(Illuminate\Database\Eloquent\ModelNotFoundException::class); $this->expectException(ModelNotFoundException::class);
User::findOrfail('51c33d8981fec6813e00000a'); User::findOrFail('51c33d8981fec6813e00000a');
} }
public function testCreate() public function testCreate(): void
{ {
/** @var User $user */
$user = User::create(['name' => 'Jane Poe']); $user = User::create(['name' => 'Jane Poe']);
$this->assertInstanceOf(Model::class, $user); $this->assertInstanceOf(Model::class, $user);
$this->assertTrue($user->exists); $this->assertTrue($user->exists);
$this->assertEquals('Jane Poe', $user->name); $this->assertEquals('Jane Poe', $user->name);
/** @var User $check */
$check = User::where('name', 'Jane Poe')->first(); $check = User::where('name', 'Jane Poe')->first();
$this->assertEquals($user->_id, $check->_id); $this->assertEquals($user->_id, $check->_id);
} }
public function testDestroy() public function testDestroy(): void
{ {
$user = new User; $user = new User;
$user->name = 'John Doe'; $user->name = 'John Doe';
...@@ -253,7 +259,7 @@ class ModelTest extends TestCase ...@@ -253,7 +259,7 @@ class ModelTest extends TestCase
$this->assertEquals(0, User::count()); $this->assertEquals(0, User::count());
} }
public function testTouch() public function testTouch(): void
{ {
$user = new User; $user = new User;
$user->name = 'John Doe'; $user->name = 'John Doe';
...@@ -262,21 +268,23 @@ class ModelTest extends TestCase ...@@ -262,21 +268,23 @@ class ModelTest extends TestCase
$user->save(); $user->save();
$old = $user->updated_at; $old = $user->updated_at;
sleep(1); sleep(1);
$user->touch(); $user->touch();
/** @var User $check */
$check = User::find($user->_id); $check = User::find($user->_id);
$this->assertNotEquals($old, $check->updated_at); $this->assertNotEquals($old, $check->updated_at);
} }
public function testSoftDelete() public function testSoftDelete(): void
{ {
Soft::create(['name' => 'John Doe']); Soft::create(['name' => 'John Doe']);
Soft::create(['name' => 'Jane Doe']); Soft::create(['name' => 'Jane Doe']);
$this->assertEquals(2, Soft::count()); $this->assertEquals(2, Soft::count());
/** @var Soft $user */
$user = Soft::where('name', 'John Doe')->first(); $user = Soft::where('name', 'John Doe')->first();
$this->assertTrue($user->exists); $this->assertTrue($user->exists);
$this->assertFalse($user->trashed()); $this->assertFalse($user->trashed());
...@@ -301,7 +309,7 @@ class ModelTest extends TestCase ...@@ -301,7 +309,7 @@ class ModelTest extends TestCase
$this->assertEquals(2, Soft::count()); $this->assertEquals(2, Soft::count());
} }
public function testPrimaryKey() public function testPrimaryKey(): void
{ {
$user = new User; $user = new User;
$this->assertEquals('_id', $user->getKeyName()); $this->assertEquals('_id', $user->getKeyName());
...@@ -315,13 +323,14 @@ class ModelTest extends TestCase ...@@ -315,13 +323,14 @@ class ModelTest extends TestCase
$this->assertEquals('A Game of Thrones', $book->getKey()); $this->assertEquals('A Game of Thrones', $book->getKey());
/** @var Book $check */
$check = Book::find('A Game of Thrones'); $check = Book::find('A Game of Thrones');
$this->assertEquals('title', $check->getKeyName()); $this->assertEquals('title', $check->getKeyName());
$this->assertEquals('A Game of Thrones', $check->getKey()); $this->assertEquals('A Game of Thrones', $check->getKey());
$this->assertEquals('A Game of Thrones', $check->title); $this->assertEquals('A Game of Thrones', $check->title);
} }
public function testScope() public function testScope(): void
{ {
Item::insert([ Item::insert([
['name' => 'knife', 'type' => 'sharp'], ['name' => 'knife', 'type' => 'sharp'],
...@@ -332,7 +341,7 @@ class ModelTest extends TestCase ...@@ -332,7 +341,7 @@ class ModelTest extends TestCase
$this->assertEquals(1, $sharp->count()); $this->assertEquals(1, $sharp->count());
} }
public function testToArray() public function testToArray(): void
{ {
$item = Item::create(['name' => 'fork', 'type' => 'sharp']); $item = Item::create(['name' => 'fork', 'type' => 'sharp']);
...@@ -340,19 +349,19 @@ class ModelTest extends TestCase ...@@ -340,19 +349,19 @@ class ModelTest extends TestCase
$keys = array_keys($array); $keys = array_keys($array);
sort($keys); sort($keys);
$this->assertEquals(['_id', 'created_at', 'name', 'type', 'updated_at'], $keys); $this->assertEquals(['_id', 'created_at', 'name', 'type', 'updated_at'], $keys);
$this->assertInternalType('string', $array['created_at']); $this->assertIsString($array['created_at']);
$this->assertInternalType('string', $array['updated_at']); $this->assertIsString($array['updated_at']);
$this->assertInternalType('string', $array['_id']); $this->assertIsString($array['_id']);
} }
public function testUnset() public function testUnset(): void
{ {
$user1 = User::create(['name' => 'John Doe', 'note1' => 'ABC', 'note2' => 'DEF']); $user1 = User::create(['name' => 'John Doe', 'note1' => 'ABC', 'note2' => 'DEF']);
$user2 = User::create(['name' => 'Jane Doe', 'note1' => 'ABC', 'note2' => 'DEF']); $user2 = User::create(['name' => 'Jane Doe', 'note1' => 'ABC', 'note2' => 'DEF']);
$user1->unset('note1'); $user1->unset('note1');
$this->assertObjectNotHasAttribute('note1', $user1); $this->assertFalse(isset($user1->note1));
$this->assertTrue(isset($user1->note2)); $this->assertTrue(isset($user1->note2));
$this->assertTrue(isset($user2->note1)); $this->assertTrue(isset($user2->note1));
$this->assertTrue(isset($user2->note2)); $this->assertTrue(isset($user2->note2));
...@@ -361,18 +370,18 @@ class ModelTest extends TestCase ...@@ -361,18 +370,18 @@ class ModelTest extends TestCase
$user1 = User::find($user1->_id); $user1 = User::find($user1->_id);
$user2 = User::find($user2->_id); $user2 = User::find($user2->_id);
$this->assertObjectNotHasAttribute('note1', $user1); $this->assertFalse(isset($user1->note1));
$this->assertTrue(isset($user1->note2)); $this->assertTrue(isset($user1->note2));
$this->assertTrue(isset($user2->note1)); $this->assertTrue(isset($user2->note1));
$this->assertTrue(isset($user2->note2)); $this->assertTrue(isset($user2->note2));
$user2->unset(['note1', 'note2']); $user2->unset(['note1', 'note2']);
$this->assertObjectNotHasAttribute('note1', $user2); $this->assertFalse(isset($user2->note1));
$this->assertObjectNotHasAttribute('note2', $user2); $this->assertFalse(isset($user2->note2));
} }
public function testDates() public function testDates(): void
{ {
$birthday = new DateTime('1980/1/1'); $birthday = new DateTime('1980/1/1');
$user = User::create(['name' => 'John Doe', 'birthday' => $birthday]); $user = User::create(['name' => 'John Doe', 'birthday' => $birthday]);
...@@ -399,10 +408,12 @@ class ModelTest extends TestCase ...@@ -399,10 +408,12 @@ class ModelTest extends TestCase
$this->assertLessThan(2, abs(time() - $item->created_at->getTimestamp())); $this->assertLessThan(2, abs(time() - $item->created_at->getTimestamp()));
// test default date format for json output // test default date format for json output
/** @var Item $item */
$item = Item::create(['name' => 'sword']); $item = Item::create(['name' => 'sword']);
$json = $item->toArray(); $json = $item->toArray();
$this->assertEquals($item->created_at->format('Y-m-d H:i:s'), $json['created_at']); $this->assertEquals($item->created_at->format('Y-m-d H:i:s'), $json['created_at']);
/** @var User $user */
$user = User::create(['name' => 'Jane Doe', 'birthday' => time()]); $user = User::create(['name' => 'Jane Doe', 'birthday' => time()]);
$this->assertInstanceOf(Carbon::class, $user->birthday); $this->assertInstanceOf(Carbon::class, $user->birthday);
...@@ -423,8 +434,19 @@ class ModelTest extends TestCase ...@@ -423,8 +434,19 @@ class ModelTest extends TestCase
$this->assertEquals((string) $user->getAttribute('entry.date')->format('Y-m-d H:i:s'), $data['entry']['date']); $this->assertEquals((string) $user->getAttribute('entry.date')->format('Y-m-d H:i:s'), $data['entry']['date']);
} }
public function testIdAttribute() public function testCarbonDateMockingWorks()
{
$fakeDate = \Carbon\Carbon::createFromDate(2000, 01, 01);
Carbon::setTestNow($fakeDate);
$item = Item::create(['name' => 'sword']);
$this->assertLessThan(1, $fakeDate->diffInSeconds($item->created_at));
}
public function testIdAttribute(): void
{ {
/** @var User $user */
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$this->assertEquals($user->id, $user->_id); $this->assertEquals($user->id, $user->_id);
...@@ -432,8 +454,9 @@ class ModelTest extends TestCase ...@@ -432,8 +454,9 @@ class ModelTest extends TestCase
$this->assertNotEquals($user->id, $user->_id); $this->assertNotEquals($user->id, $user->_id);
} }
public function testPushPull() public function testPushPull(): void
{ {
/** @var User $user */
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$user->push('tags', 'tag1'); $user->push('tags', 'tag1');
...@@ -458,36 +481,36 @@ class ModelTest extends TestCase ...@@ -458,36 +481,36 @@ class ModelTest extends TestCase
$this->assertEquals([], $user->tags); $this->assertEquals([], $user->tags);
} }
public function testRaw() public function testRaw(): void
{ {
User::create(['name' => 'John Doe', 'age' => 35]); User::create(['name' => 'John Doe', 'age' => 35]);
User::create(['name' => 'Jane Doe', 'age' => 35]); User::create(['name' => 'Jane Doe', 'age' => 35]);
User::create(['name' => 'Harry Hoe', 'age' => 15]); User::create(['name' => 'Harry Hoe', 'age' => 15]);
$users = User::raw(function ($collection) { $users = User::raw(function (\Jenssegers\Mongodb\Collection $collection) {
return $collection->find(['age' => 35]); return $collection->find(['age' => 35]);
}); });
$this->assertInstanceOf(Collection::class, $users); $this->assertInstanceOf(Collection::class, $users);
$this->assertInstanceOf(Model::class, $users[0]); $this->assertInstanceOf(Model::class, $users[0]);
$user = User::raw(function ($collection) { $user = User::raw(function (\Jenssegers\Mongodb\Collection $collection) {
return $collection->findOne(['age' => 35]); return $collection->findOne(['age' => 35]);
}); });
$this->assertInstanceOf(Model::class, $user); $this->assertInstanceOf(Model::class, $user);
$count = User::raw(function ($collection) { $count = User::raw(function (\Jenssegers\Mongodb\Collection $collection) {
return $collection->count(); return $collection->count();
}); });
$this->assertEquals(3, $count); $this->assertEquals(3, $count);
$result = User::raw(function ($collection) { $result = User::raw(function (\Jenssegers\Mongodb\Collection $collection) {
return $collection->insertOne(['name' => 'Yvonne Yoe', 'age' => 35]); return $collection->insertOne(['name' => 'Yvonne Yoe', 'age' => 35]);
}); });
$this->assertNotNull($result); $this->assertNotNull($result);
} }
public function testDotNotation() public function testDotNotation(): void
{ {
$user = User::create([ $user = User::create([
'name' => 'John Doe', 'name' => 'John Doe',
...@@ -509,8 +532,9 @@ class ModelTest extends TestCase ...@@ -509,8 +532,9 @@ class ModelTest extends TestCase
$this->assertEquals('Strasbourg', $user['address.city']); $this->assertEquals('Strasbourg', $user['address.city']);
} }
public function testMultipleLevelDotNotation() public function testMultipleLevelDotNotation(): void
{ {
/** @var Book $book */
$book = Book::create([ $book = Book::create([
'title' => 'A Game of Thrones', 'title' => 'A Game of Thrones',
'chapters' => [ 'chapters' => [
...@@ -525,7 +549,7 @@ class ModelTest extends TestCase ...@@ -525,7 +549,7 @@ class ModelTest extends TestCase
$this->assertEquals('The first chapter', $book['chapters.one.title']); $this->assertEquals('The first chapter', $book['chapters.one.title']);
} }
public function testGetDirtyDates() public function testGetDirtyDates(): void
{ {
$user = new User(); $user = new User();
$user->setRawAttributes(['name' => 'John Doe', 'birthday' => new DateTime('19 august 1989')], true); $user->setRawAttributes(['name' => 'John Doe', 'birthday' => new DateTime('19 august 1989')], true);
...@@ -535,17 +559,26 @@ class ModelTest extends TestCase ...@@ -535,17 +559,26 @@ class ModelTest extends TestCase
$this->assertEmpty($user->getDirty()); $this->assertEmpty($user->getDirty());
} }
public function testChunkById() public function testChunkById(): void
{ {
User::create(['name' => 'fork', 'tags' => ['sharp', 'pointy']]); User::create(['name' => 'fork', 'tags' => ['sharp', 'pointy']]);
User::create(['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']]); User::create(['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']]);
User::create(['name' => 'spoon', 'tags' => ['round', 'bowl']]); User::create(['name' => 'spoon', 'tags' => ['round', 'bowl']]);
$count = 0; $count = 0;
User::chunkById(2, function ($items) use (&$count) { User::chunkById(2, function (\Illuminate\Database\Eloquent\Collection $items) use (&$count) {
$count += count($items); $count += count($items);
}); });
$this->assertEquals(3, $count); $this->assertEquals(3, $count);
} }
public function testTruncateModel()
{
User::create(['name' => 'John Doe']);
User::truncate();
$this->assertEquals(0, User::count());
}
} }
<?php <?php
declare(strict_types=1);
use MongoDB\BSON\UTCDateTime; use Illuminate\Support\Facades\DB;
use Jenssegers\Mongodb\Collection;
use Jenssegers\Mongodb\Query\Builder;
use MongoDB\BSON\ObjectId;
use MongoDB\BSON\Regex; use MongoDB\BSON\Regex;
use MongoDB\BSON\UTCDateTime;
use MongoDB\Driver\Cursor;
class QueryBuilderTest extends TestCase class QueryBuilderTest extends TestCase
{ {
public function tearDown() public function tearDown(): void
{ {
DB::collection('users')->truncate(); DB::collection('users')->truncate();
DB::collection('items')->truncate(); DB::collection('items')->truncate();
...@@ -40,14 +46,14 @@ class QueryBuilderTest extends TestCase ...@@ -40,14 +46,14 @@ class QueryBuilderTest extends TestCase
DB::collection('items')->where('user_id', $user_id)->delete($pid); DB::collection('items')->where('user_id', $user_id)->delete($pid);
DB::collection('items')->where('user_id', $user_id)->delete(str_random(32)); DB::collection('items')->where('user_id', $user_id)->delete(md5('random-id'));
$this->assertEquals(2, DB::collection('items')->count()); $this->assertEquals(2, DB::collection('items')->count());
} }
public function testCollection() public function testCollection()
{ {
$this->assertInstanceOf('Jenssegers\Mongodb\Query\Builder', DB::collection('users')); $this->assertInstanceOf(Builder::class, DB::collection('users'));
} }
public function testGet() public function testGet()
...@@ -85,13 +91,13 @@ class QueryBuilderTest extends TestCase ...@@ -85,13 +91,13 @@ class QueryBuilderTest extends TestCase
$user = $users[0]; $user = $users[0];
$this->assertEquals('John Doe', $user['name']); $this->assertEquals('John Doe', $user['name']);
$this->assertInternalType('array', $user['tags']); $this->assertIsArray($user['tags']);
} }
public function testInsertGetId() public function testInsertGetId()
{ {
$id = DB::collection('users')->insertGetId(['name' => 'John Doe']); $id = DB::collection('users')->insertGetId(['name' => 'John Doe']);
$this->assertInstanceOf('MongoDB\BSON\ObjectID', $id); $this->assertInstanceOf(ObjectId::class, $id);
} }
public function testBatchInsert() public function testBatchInsert()
...@@ -109,7 +115,7 @@ class QueryBuilderTest extends TestCase ...@@ -109,7 +115,7 @@ class QueryBuilderTest extends TestCase
$users = DB::collection('users')->get(); $users = DB::collection('users')->get();
$this->assertCount(2, $users); $this->assertCount(2, $users);
$this->assertInternalType('array', $users[0]['tags']); $this->assertIsArray($users[0]['tags']);
} }
public function testFind() public function testFind()
...@@ -169,7 +175,8 @@ class QueryBuilderTest extends TestCase ...@@ -169,7 +175,8 @@ class QueryBuilderTest extends TestCase
public function testTruncate() public function testTruncate()
{ {
DB::collection('users')->insert(['name' => 'John Doe']); DB::collection('users')->insert(['name' => 'John Doe']);
DB::collection('users')->truncate(); $result = DB::collection('users')->truncate();
$this->assertEquals(1, $result);
$this->assertEquals(0, DB::collection('users')->count()); $this->assertEquals(0, DB::collection('users')->count());
} }
...@@ -177,11 +184,11 @@ class QueryBuilderTest extends TestCase ...@@ -177,11 +184,11 @@ class QueryBuilderTest extends TestCase
{ {
DB::collection('users')->insert([ DB::collection('users')->insert([
[ [
'name' => 'John Doe', 'name' => 'John Doe',
'address' => ['country' => 'Belgium', 'city' => 'Ghent'], 'address' => ['country' => 'Belgium', 'city' => 'Ghent'],
], ],
[ [
'name' => 'Jane Doe', 'name' => 'Jane Doe',
'address' => ['country' => 'France', 'city' => 'Paris'], 'address' => ['country' => 'France', 'city' => 'Paris'],
], ],
]); ]);
...@@ -220,14 +227,14 @@ class QueryBuilderTest extends TestCase ...@@ -220,14 +227,14 @@ class QueryBuilderTest extends TestCase
return $collection->find(['age' => 20]); return $collection->find(['age' => 20]);
}); });
$this->assertInstanceOf('MongoDB\Driver\Cursor', $cursor); $this->assertInstanceOf(Cursor::class, $cursor);
$this->assertCount(1, $cursor->toArray()); $this->assertCount(1, $cursor->toArray());
$collection = DB::collection('users')->raw(); $collection = DB::collection('users')->raw();
$this->assertInstanceOf('Jenssegers\Mongodb\Collection', $collection); $this->assertInstanceOf(Collection::class, $collection);
$collection = User::raw(); $collection = User::raw();
$this->assertInstanceOf('Jenssegers\Mongodb\Collection', $collection); $this->assertInstanceOf(Collection::class, $collection);
$results = DB::collection('users')->whereRaw(['age' => 20])->get(); $results = DB::collection('users')->whereRaw(['age' => 20])->get();
$this->assertCount(1, $results); $this->assertCount(1, $results);
...@@ -237,15 +244,15 @@ class QueryBuilderTest extends TestCase ...@@ -237,15 +244,15 @@ class QueryBuilderTest extends TestCase
public function testPush() public function testPush()
{ {
$id = DB::collection('users')->insertGetId([ $id = DB::collection('users')->insertGetId([
'name' => 'John Doe', 'name' => 'John Doe',
'tags' => [], 'tags' => [],
'messages' => [], 'messages' => [],
]); ]);
DB::collection('users')->where('_id', $id)->push('tags', 'tag1'); DB::collection('users')->where('_id', $id)->push('tags', 'tag1');
$user = DB::collection('users')->find($id); $user = DB::collection('users')->find($id);
$this->assertInternalType('array', $user['tags']); $this->assertIsArray($user['tags']);
$this->assertCount(1, $user['tags']); $this->assertCount(1, $user['tags']);
$this->assertEquals('tag1', $user['tags'][0]); $this->assertEquals('tag1', $user['tags'][0]);
...@@ -267,17 +274,25 @@ class QueryBuilderTest extends TestCase ...@@ -267,17 +274,25 @@ class QueryBuilderTest extends TestCase
$message = ['from' => 'Jane', 'body' => 'Hi John']; $message = ['from' => 'Jane', 'body' => 'Hi John'];
DB::collection('users')->where('_id', $id)->push('messages', $message); DB::collection('users')->where('_id', $id)->push('messages', $message);
$user = DB::collection('users')->find($id); $user = DB::collection('users')->find($id);
$this->assertInternalType('array', $user['messages']); $this->assertIsArray($user['messages']);
$this->assertCount(1, $user['messages']); $this->assertCount(1, $user['messages']);
$this->assertEquals($message, $user['messages'][0]); $this->assertEquals($message, $user['messages'][0]);
// Raw // Raw
DB::collection('users')->where('_id', $id)->push(['tags' => 'tag3', 'messages' => ['from' => 'Mark', 'body' => 'Hi John']]); DB::collection('users')->where('_id', $id)->push([
'tags' => 'tag3',
'messages' => ['from' => 'Mark', 'body' => 'Hi John'],
]);
$user = DB::collection('users')->find($id); $user = DB::collection('users')->find($id);
$this->assertCount(4, $user['tags']); $this->assertCount(4, $user['tags']);
$this->assertCount(2, $user['messages']); $this->assertCount(2, $user['messages']);
DB::collection('users')->where('_id', $id)->push(['messages' => ['date' => new DateTime(), 'body' => 'Hi John']]); DB::collection('users')->where('_id', $id)->push([
'messages' => [
'date' => new DateTime(),
'body' => 'Hi John',
],
]);
$user = DB::collection('users')->find($id); $user = DB::collection('users')->find($id);
$this->assertCount(3, $user['messages']); $this->assertCount(3, $user['messages']);
} }
...@@ -288,22 +303,22 @@ class QueryBuilderTest extends TestCase ...@@ -288,22 +303,22 @@ class QueryBuilderTest extends TestCase
$message2 = ['from' => 'Mark', 'body' => 'Hi John']; $message2 = ['from' => 'Mark', 'body' => 'Hi John'];
$id = DB::collection('users')->insertGetId([ $id = DB::collection('users')->insertGetId([
'name' => 'John Doe', 'name' => 'John Doe',
'tags' => ['tag1', 'tag2', 'tag3', 'tag4'], 'tags' => ['tag1', 'tag2', 'tag3', 'tag4'],
'messages' => [$message1, $message2], 'messages' => [$message1, $message2],
]); ]);
DB::collection('users')->where('_id', $id)->pull('tags', 'tag3'); DB::collection('users')->where('_id', $id)->pull('tags', 'tag3');
$user = DB::collection('users')->find($id); $user = DB::collection('users')->find($id);
$this->assertInternalType('array', $user['tags']); $this->assertIsArray($user['tags']);
$this->assertCount(3, $user['tags']); $this->assertCount(3, $user['tags']);
$this->assertEquals('tag4', $user['tags'][2]); $this->assertEquals('tag4', $user['tags'][2]);
DB::collection('users')->where('_id', $id)->pull('messages', $message1); DB::collection('users')->where('_id', $id)->pull('messages', $message1);
$user = DB::collection('users')->find($id); $user = DB::collection('users')->find($id);
$this->assertInternalType('array', $user['messages']); $this->assertIsArray($user['messages']);
$this->assertCount(1, $user['messages']); $this->assertCount(1, $user['messages']);
// Raw // Raw
...@@ -317,7 +332,7 @@ class QueryBuilderTest extends TestCase ...@@ -317,7 +332,7 @@ class QueryBuilderTest extends TestCase
{ {
DB::collection('items')->insert([ DB::collection('items')->insert([
['name' => 'knife', 'type' => 'sharp'], ['name' => 'knife', 'type' => 'sharp'],
['name' => 'fork', 'type' => 'sharp'], ['name' => 'fork', 'type' => 'sharp'],
['name' => 'spoon', 'type' => 'round'], ['name' => 'spoon', 'type' => 'round'],
['name' => 'spoon', 'type' => 'round'], ['name' => 'spoon', 'type' => 'round'],
]); ]);
...@@ -337,7 +352,7 @@ class QueryBuilderTest extends TestCase ...@@ -337,7 +352,7 @@ class QueryBuilderTest extends TestCase
{ {
DB::collection('items')->insert([ DB::collection('items')->insert([
['_id' => 'knife', 'type' => 'sharp', 'amount' => 34], ['_id' => 'knife', 'type' => 'sharp', 'amount' => 34],
['_id' => 'fork', 'type' => 'sharp', 'amount' => 20], ['_id' => 'fork', 'type' => 'sharp', 'amount' => 20],
['_id' => 'spoon', 'type' => 'round', 'amount' => 3], ['_id' => 'spoon', 'type' => 'round', 'amount' => 3],
]); ]);
...@@ -360,7 +375,7 @@ class QueryBuilderTest extends TestCase ...@@ -360,7 +375,7 @@ class QueryBuilderTest extends TestCase
{ {
DB::collection('items')->insert([ DB::collection('items')->insert([
['name' => 'knife', 'type' => 'sharp', 'amount' => 34], ['name' => 'knife', 'type' => 'sharp', 'amount' => 34],
['name' => 'fork', 'type' => 'sharp', 'amount' => 20], ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
['name' => 'spoon', 'type' => 'round', 'amount' => 3], ['name' => 'spoon', 'type' => 'round', 'amount' => 3],
['name' => 'spoon', 'type' => 'round', 'amount' => 14], ['name' => 'spoon', 'type' => 'round', 'amount' => 14],
]); ]);
...@@ -374,7 +389,7 @@ class QueryBuilderTest extends TestCase ...@@ -374,7 +389,7 @@ class QueryBuilderTest extends TestCase
{ {
DB::collection('items')->insert([ DB::collection('items')->insert([
['name' => 'knife', 'type' => 'sharp', 'amount' => 34], ['name' => 'knife', 'type' => 'sharp', 'amount' => 34],
['name' => 'fork', 'type' => 'sharp', 'amount' => 20], ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
['name' => 'spoon', 'type' => 'round', 'amount' => 3], ['name' => 'spoon', 'type' => 'round', 'amount' => 3],
['name' => 'spoon', 'type' => 'round', 'amount' => 14], ['name' => 'spoon', 'type' => 'round', 'amount' => 14],
]); ]);
...@@ -399,7 +414,7 @@ class QueryBuilderTest extends TestCase ...@@ -399,7 +414,7 @@ class QueryBuilderTest extends TestCase
{ {
DB::collection('items')->insert([ DB::collection('items')->insert([
['name' => 'knife', 'type' => 'sharp', 'amount' => 34], ['name' => 'knife', 'type' => 'sharp', 'amount' => 34],
['name' => 'fork', 'type' => 'sharp', 'amount' => 20], ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
['name' => 'spoon', 'type' => 'round', 'amount' => 3], ['name' => 'spoon', 'type' => 'round', 'amount' => 3],
['name' => 'spoon', 'type' => 'round', 'amount' => 14], ['name' => 'spoon', 'type' => 'round', 'amount' => 14],
]); ]);
...@@ -422,7 +437,7 @@ class QueryBuilderTest extends TestCase ...@@ -422,7 +437,7 @@ class QueryBuilderTest extends TestCase
{ {
DB::collection('items')->insert([ DB::collection('items')->insert([
['name' => 'knife', 'type' => 'sharp', 'amount' => 34], ['name' => 'knife', 'type' => 'sharp', 'amount' => 34],
['name' => 'fork', 'type' => 'sharp', 'amount' => 20], ['name' => 'fork', 'type' => 'sharp', 'amount' => 20],
['name' => 'spoon', 'type' => 'round', 'amount' => 3], ['name' => 'spoon', 'type' => 'round', 'amount' => 3],
['name' => 'spoon', 'type' => 'round', 'amount' => 14], ['name' => 'spoon', 'type' => 'round', 'amount' => 14],
]); ]);
...@@ -441,7 +456,7 @@ class QueryBuilderTest extends TestCase ...@@ -441,7 +456,7 @@ class QueryBuilderTest extends TestCase
{ {
DB::collection('items')->insert([ DB::collection('items')->insert([
['name' => 'knife', 'amount' => ['hidden' => 10, 'found' => 3]], ['name' => 'knife', 'amount' => ['hidden' => 10, 'found' => 3]],
['name' => 'fork', 'amount' => ['hidden' => 35, 'found' => 12]], ['name' => 'fork', 'amount' => ['hidden' => 35, 'found' => 12]],
['name' => 'spoon', 'amount' => ['hidden' => 14, 'found' => 21]], ['name' => 'spoon', 'amount' => ['hidden' => 14, 'found' => 21]],
['name' => 'spoon', 'amount' => ['hidden' => 6, 'found' => 4]], ['name' => 'spoon', 'amount' => ['hidden' => 6, 'found' => 4]],
]); ]);
...@@ -457,7 +472,14 @@ class QueryBuilderTest extends TestCase ...@@ -457,7 +472,14 @@ class QueryBuilderTest extends TestCase
{ {
DB::collection('items')->insert([ DB::collection('items')->insert([
['name' => 'knife', 'amount' => [['hidden' => 10, 'found' => 3], ['hidden' => 5, 'found' => 2]]], ['name' => 'knife', 'amount' => [['hidden' => 10, 'found' => 3], ['hidden' => 5, 'found' => 2]]],
['name' => 'fork', 'amount' => [['hidden' => 35, 'found' => 12], ['hidden' => 7, 'found' => 17], ['hidden' => 1, 'found' => 19]]], [
'name' => 'fork',
'amount' => [
['hidden' => 35, 'found' => 12],
['hidden' => 7, 'found' => 17],
['hidden' => 1, 'found' => 19],
],
],
['name' => 'spoon', 'amount' => [['hidden' => 14, 'found' => 21]]], ['name' => 'spoon', 'amount' => [['hidden' => 14, 'found' => 21]]],
['name' => 'teaspoon', 'amount' => []], ['name' => 'teaspoon', 'amount' => []],
]); ]);
...@@ -472,15 +494,15 @@ class QueryBuilderTest extends TestCase ...@@ -472,15 +494,15 @@ class QueryBuilderTest extends TestCase
public function testUpsert() public function testUpsert()
{ {
DB::collection('items')->where('name', 'knife') DB::collection('items')->where('name', 'knife')
->update( ->update(
['amount' => 1], ['amount' => 1],
['upsert' => true] ['upsert' => true]
); );
$this->assertEquals(1, DB::collection('items')->count()); $this->assertEquals(1, DB::collection('items')->count());
Item::where('name', 'spoon') Item::where('name', 'spoon')
->update( ->update(
['amount' => 1], ['amount' => 1],
['upsert' => true] ['upsert' => true]
); );
...@@ -529,7 +551,9 @@ class QueryBuilderTest extends TestCase ...@@ -529,7 +551,9 @@ class QueryBuilderTest extends TestCase
['name' => 'Mark Moe', 'birthday' => new UTCDateTime(1000 * strtotime("1983-01-01 00:00:00"))], ['name' => 'Mark Moe', 'birthday' => new UTCDateTime(1000 * strtotime("1983-01-01 00:00:00"))],
]); ]);
$user = DB::collection('users')->where('birthday', new UTCDateTime(1000 * strtotime("1980-01-01 00:00:00")))->first(); $user = DB::collection('users')
->where('birthday', new UTCDateTime(1000 * strtotime("1980-01-01 00:00:00")))
->first();
$this->assertEquals('John Doe', $user['name']); $this->assertEquals('John Doe', $user['name']);
$user = DB::collection('users')->where('birthday', '=', new DateTime("1980-01-01 00:00:00"))->first(); $user = DB::collection('users')->where('birthday', '=', new DateTime("1980-01-01 00:00:00"))->first();
...@@ -576,7 +600,7 @@ class QueryBuilderTest extends TestCase ...@@ -576,7 +600,7 @@ class QueryBuilderTest extends TestCase
$this->assertCount(0, $results); $this->assertCount(0, $results);
DB::collection('items')->insert([ DB::collection('items')->insert([
['name' => 'fork', 'tags' => ['sharp', 'pointy']], ['name' => 'fork', 'tags' => ['sharp', 'pointy']],
['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']], ['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']],
['name' => 'spoon', 'tags' => ['round', 'bowl']], ['name' => 'spoon', 'tags' => ['round', 'bowl']],
]); ]);
...@@ -618,14 +642,14 @@ class QueryBuilderTest extends TestCase ...@@ -618,14 +642,14 @@ class QueryBuilderTest extends TestCase
DB::collection('users')->insert([ DB::collection('users')->insert([
[ [
'name' => 'John Doe', 'name' => 'John Doe',
'addresses' => [ 'addresses' => [
['city' => 'Ghent'], ['city' => 'Ghent'],
['city' => 'Paris'], ['city' => 'Paris'],
], ],
], ],
[ [
'name' => 'Jane Doe', 'name' => 'Jane Doe',
'addresses' => [ 'addresses' => [
['city' => 'Brussels'], ['city' => 'Brussels'],
['city' => 'Paris'], ['city' => 'Paris'],
...@@ -690,7 +714,7 @@ class QueryBuilderTest extends TestCase ...@@ -690,7 +714,7 @@ class QueryBuilderTest extends TestCase
public function testProjections() public function testProjections()
{ {
DB::collection('items')->insert([ DB::collection('items')->insert([
['name' => 'fork', 'tags' => ['sharp', 'pointy']], ['name' => 'fork', 'tags' => ['sharp', 'pointy']],
['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']], ['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']],
['name' => 'spoon', 'tags' => ['round', 'bowl']], ['name' => 'spoon', 'tags' => ['round', 'bowl']],
]); ]);
...@@ -701,4 +725,38 @@ class QueryBuilderTest extends TestCase ...@@ -701,4 +725,38 @@ class QueryBuilderTest extends TestCase
$this->assertEquals(1, count($result['tags'])); $this->assertEquals(1, count($result['tags']));
} }
} }
public function testValue()
{
DB::collection('books')->insert([
['title' => 'Moby-Dick', 'author' => ['first_name' => 'Herman', 'last_name' => 'Melville']],
]);
$this->assertEquals('Moby-Dick', DB::collection('books')->value('title'));
$this->assertEquals(['first_name' => 'Herman', 'last_name' => 'Melville'], DB::collection('books')
->value('author'));
$this->assertEquals('Herman', DB::collection('books')->value('author.first_name'));
$this->assertEquals('Melville', DB::collection('books')->value('author.last_name'));
}
public function testHintOptions()
{
DB::collection('items')->insert([
['name' => 'fork', 'tags' => ['sharp', 'pointy']],
['name' => 'spork', 'tags' => ['sharp', 'pointy', 'round', 'bowl']],
['name' => 'spoon', 'tags' => ['round', 'bowl']],
]);
$results = DB::collection('items')->hint(['$natural' => -1])->get();
$this->assertEquals('spoon', $results[0]['name']);
$this->assertEquals('spork', $results[1]['name']);
$this->assertEquals('fork', $results[2]['name']);
$results = DB::collection('items')->hint(['$natural' => 1])->get();
$this->assertEquals('spoon', $results[2]['name']);
$this->assertEquals('spork', $results[1]['name']);
$this->assertEquals('fork', $results[0]['name']);
}
} }
<?php <?php
declare(strict_types=1);
class QueryTest extends TestCase class QueryTest extends TestCase
{ {
protected static $started = false; protected static $started = false;
public function setUp() public function setUp(): void
{ {
parent::setUp(); parent::setUp();
User::create(['name' => 'John Doe', 'age' => 35, 'title' => 'admin']); User::create(['name' => 'John Doe', 'age' => 35, 'title' => 'admin']);
...@@ -18,13 +19,14 @@ class QueryTest extends TestCase ...@@ -18,13 +19,14 @@ class QueryTest extends TestCase
User::create(['name' => 'Error', 'age' => null, 'title' => null]); User::create(['name' => 'Error', 'age' => null, 'title' => null]);
} }
public function tearDown() public function tearDown(): void
{ {
User::truncate(); User::truncate();
Scoped::truncate();
parent::tearDown(); parent::tearDown();
} }
public function testWhere() public function testWhere(): void
{ {
$users = User::where('age', 35)->get(); $users = User::where('age', 35)->get();
$this->assertCount(3, $users); $this->assertCount(3, $users);
...@@ -45,7 +47,7 @@ class QueryTest extends TestCase ...@@ -45,7 +47,7 @@ class QueryTest extends TestCase
$this->assertCount(6, $users); $this->assertCount(6, $users);
} }
public function testAndWhere() public function testAndWhere(): void
{ {
$users = User::where('age', 35)->where('title', 'admin')->get(); $users = User::where('age', 35)->where('title', 'admin')->get();
$this->assertCount(2, $users); $this->assertCount(2, $users);
...@@ -54,7 +56,7 @@ class QueryTest extends TestCase ...@@ -54,7 +56,7 @@ class QueryTest extends TestCase
$this->assertCount(2, $users); $this->assertCount(2, $users);
} }
public function testLike() public function testLike(): void
{ {
$users = User::where('name', 'like', '%doe')->get(); $users = User::where('name', 'like', '%doe')->get();
$this->assertCount(2, $users); $this->assertCount(2, $users);
...@@ -69,7 +71,22 @@ class QueryTest extends TestCase ...@@ -69,7 +71,22 @@ class QueryTest extends TestCase
$this->assertCount(1, $users); $this->assertCount(1, $users);
} }
public function testSelect() public function testNotLike(): void
{
$users = User::where('name', 'not like', '%doe')->get();
$this->assertCount(7, $users);
$users = User::where('name', 'not like', '%y%')->get();
$this->assertCount(6, $users);
$users = User::where('name', 'not LIKE', '%y%')->get();
$this->assertCount(6, $users);
$users = User::where('name', 'not like', 't%')->get();
$this->assertCount(8, $users);
}
public function testSelect(): void
{ {
$user = User::where('name', 'John Doe')->select('name')->first(); $user = User::where('name', 'John Doe')->select('name')->first();
...@@ -95,7 +112,7 @@ class QueryTest extends TestCase ...@@ -95,7 +112,7 @@ class QueryTest extends TestCase
$this->assertNull($user->age); $this->assertNull($user->age);
} }
public function testOrWhere() public function testOrWhere(): void
{ {
$users = User::where('age', 13)->orWhere('title', 'admin')->get(); $users = User::where('age', 13)->orWhere('title', 'admin')->get();
$this->assertCount(4, $users); $this->assertCount(4, $users);
...@@ -104,7 +121,7 @@ class QueryTest extends TestCase ...@@ -104,7 +121,7 @@ class QueryTest extends TestCase
$this->assertCount(2, $users); $this->assertCount(2, $users);
} }
public function testBetween() public function testBetween(): void
{ {
$users = User::whereBetween('age', [0, 25])->get(); $users = User::whereBetween('age', [0, 25])->get();
$this->assertCount(2, $users); $this->assertCount(2, $users);
...@@ -117,7 +134,7 @@ class QueryTest extends TestCase ...@@ -117,7 +134,7 @@ class QueryTest extends TestCase
$this->assertCount(6, $users); $this->assertCount(6, $users);
} }
public function testIn() public function testIn(): void
{ {
$users = User::whereIn('age', [13, 23])->get(); $users = User::whereIn('age', [13, 23])->get();
$this->assertCount(2, $users); $this->assertCount(2, $users);
...@@ -129,23 +146,23 @@ class QueryTest extends TestCase ...@@ -129,23 +146,23 @@ class QueryTest extends TestCase
$this->assertCount(4, $users); $this->assertCount(4, $users);
$users = User::whereNotNull('age') $users = User::whereNotNull('age')
->whereNotIn('age', [33, 35])->get(); ->whereNotIn('age', [33, 35])->get();
$this->assertCount(3, $users); $this->assertCount(3, $users);
} }
public function testWhereNull() public function testWhereNull(): void
{ {
$users = User::whereNull('age')->get(); $users = User::whereNull('age')->get();
$this->assertCount(1, $users); $this->assertCount(1, $users);
} }
public function testWhereNotNull() public function testWhereNotNull(): void
{ {
$users = User::whereNotNull('age')->get(); $users = User::whereNotNull('age')->get();
$this->assertCount(8, $users); $this->assertCount(8, $users);
} }
public function testOrder() public function testOrder(): void
{ {
$user = User::whereNotNull('age')->orderBy('age', 'asc')->first(); $user = User::whereNotNull('age')->orderBy('age', 'asc')->first();
$this->assertEquals(13, $user->age); $this->assertEquals(13, $user->age);
...@@ -166,7 +183,7 @@ class QueryTest extends TestCase ...@@ -166,7 +183,7 @@ class QueryTest extends TestCase
$this->assertEquals(35, $user->age); $this->assertEquals(35, $user->age);
} }
public function testGroupBy() public function testGroupBy(): void
{ {
$users = User::groupBy('title')->get(); $users = User::groupBy('title')->get();
$this->assertCount(3, $users); $this->assertCount(3, $users);
...@@ -196,7 +213,7 @@ class QueryTest extends TestCase ...@@ -196,7 +213,7 @@ class QueryTest extends TestCase
$this->assertNotNull($users[0]->name); $this->assertNotNull($users[0]->name);
} }
public function testCount() public function testCount(): void
{ {
$count = User::where('age', '<>', 35)->count(); $count = User::where('age', '<>', 35)->count();
$this->assertEquals(6, $count); $this->assertEquals(6, $count);
...@@ -206,17 +223,17 @@ class QueryTest extends TestCase ...@@ -206,17 +223,17 @@ class QueryTest extends TestCase
$this->assertEquals(6, $count); $this->assertEquals(6, $count);
} }
public function testExists() public function testExists(): void
{ {
$this->assertFalse(User::where('age', '>', 37)->exists()); $this->assertFalse(User::where('age', '>', 37)->exists());
$this->assertTrue(User::where('age', '<', 37)->exists()); $this->assertTrue(User::where('age', '<', 37)->exists());
} }
public function testSubquery() public function testSubQuery(): void
{ {
$users = User::where('title', 'admin')->orWhere(function ($query) { $users = User::where('title', 'admin')->orWhere(function ($query) {
$query->where('name', 'Tommy Toe') $query->where('name', 'Tommy Toe')
->orWhere('name', 'Error'); ->orWhere('name', 'Error');
}) })
->get(); ->get();
...@@ -224,7 +241,7 @@ class QueryTest extends TestCase ...@@ -224,7 +241,7 @@ class QueryTest extends TestCase
$users = User::where('title', 'user')->where(function ($query) { $users = User::where('title', 'user')->where(function ($query) {
$query->where('age', 35) $query->where('age', 35)
->orWhere('name', 'like', '%harry%'); ->orWhere('name', 'like', '%harry%');
}) })
->get(); ->get();
...@@ -232,36 +249,36 @@ class QueryTest extends TestCase ...@@ -232,36 +249,36 @@ class QueryTest extends TestCase
$users = User::where('age', 35)->orWhere(function ($query) { $users = User::where('age', 35)->orWhere(function ($query) {
$query->where('title', 'admin') $query->where('title', 'admin')
->orWhere('name', 'Error'); ->orWhere('name', 'Error');
}) })
->get(); ->get();
$this->assertCount(5, $users); $this->assertCount(5, $users);
$users = User::whereNull('deleted_at') $users = User::whereNull('deleted_at')
->where('title', 'admin') ->where('title', 'admin')
->where(function ($query) { ->where(function ($query) {
$query->where('age', '>', 15) $query->where('age', '>', 15)
->orWhere('name', 'Harry Hoe'); ->orWhere('name', 'Harry Hoe');
}) })
->get(); ->get();
$this->assertEquals(3, $users->count()); $this->assertEquals(3, $users->count());
$users = User::whereNull('deleted_at') $users = User::whereNull('deleted_at')
->where(function ($query) { ->where(function ($query) {
$query->where('name', 'Harry Hoe') $query->where('name', 'Harry Hoe')
->orWhere(function ($query) { ->orWhere(function ($query) {
$query->where('age', '>', 15) $query->where('age', '>', 15)
->where('title', '<>', 'admin'); ->where('title', '<>', 'admin');
}); });
}) })
->get(); ->get();
$this->assertEquals(5, $users->count()); $this->assertEquals(5, $users->count());
} }
public function testWhereRaw() public function testWhereRaw(): void
{ {
$where = ['age' => ['$gt' => 30, '$lt' => 40]]; $where = ['age' => ['$gt' => 30, '$lt' => 40]];
$users = User::whereRaw($where)->get(); $users = User::whereRaw($where)->get();
...@@ -269,34 +286,34 @@ class QueryTest extends TestCase ...@@ -269,34 +286,34 @@ class QueryTest extends TestCase
$this->assertCount(6, $users); $this->assertCount(6, $users);
$where1 = ['age' => ['$gt' => 30, '$lte' => 35]]; $where1 = ['age' => ['$gt' => 30, '$lte' => 35]];
$where2 = ['age' => ['$gt' => 35, '$lt' => 40]]; $where2 = ['age' => ['$gt' => 35, '$lt' => 40]];
$users = User::whereRaw($where1)->orWhereRaw($where2)->get(); $users = User::whereRaw($where1)->orWhereRaw($where2)->get();
$this->assertCount(6, $users); $this->assertCount(6, $users);
} }
public function testMultipleOr() public function testMultipleOr(): void
{ {
$users = User::where(function ($query) { $users = User::where(function ($query) {
$query->where('age', 35)->orWhere('age', 33); $query->where('age', 35)->orWhere('age', 33);
}) })
->where(function ($query) { ->where(function ($query) {
$query->where('name', 'John Doe')->orWhere('name', 'Jane Doe'); $query->where('name', 'John Doe')->orWhere('name', 'Jane Doe');
})->get(); })->get();
$this->assertCount(2, $users); $this->assertCount(2, $users);
$users = User::where(function ($query) { $users = User::where(function ($query) {
$query->orWhere('age', 35)->orWhere('age', 33); $query->orWhere('age', 35)->orWhere('age', 33);
}) })
->where(function ($query) { ->where(function ($query) {
$query->orWhere('name', 'John Doe')->orWhere('name', 'Jane Doe'); $query->orWhere('name', 'John Doe')->orWhere('name', 'Jane Doe');
})->get(); })->get();
$this->assertCount(2, $users); $this->assertCount(2, $users);
} }
public function testPaginate() public function testPaginate(): void
{ {
$results = User::paginate(2); $results = User::paginate(2);
$this->assertEquals(2, $results->count()); $this->assertEquals(2, $results->count());
...@@ -309,4 +326,21 @@ class QueryTest extends TestCase ...@@ -309,4 +326,21 @@ class QueryTest extends TestCase
$this->assertEquals(9, $results->total()); $this->assertEquals(9, $results->total());
$this->assertEquals(1, $results->currentPage()); $this->assertEquals(1, $results->currentPage());
} }
public function testUpdate(): void
{
$this->assertEquals(1, User::where(['name' => 'John Doe'])->update(['name' => 'Jim Morrison']));
$this->assertEquals(1, User::where(['name' => 'Jim Morrison'])->count());
Scoped::create(['favorite' => true]);
Scoped::create(['favorite' => false]);
$this->assertCount(1, Scoped::get());
$this->assertEquals(1, Scoped::query()->update(['name' => 'Johnny']));
$this->assertCount(1, Scoped::withoutGlobalScopes()->where(['name' => 'Johnny'])->get());
$this->assertCount(2, Scoped::withoutGlobalScopes()->get());
$this->assertEquals(2, Scoped::withoutGlobalScopes()->update(['name' => 'Jimmy']));
$this->assertCount(2, Scoped::withoutGlobalScopes()->where(['name' => 'Jimmy'])->get());
}
} }
<?php <?php
declare(strict_types=1);
use Jenssegers\Mongodb\Queue\Failed\MongoFailedJobProvider;
class QueueTest extends TestCase class QueueTest extends TestCase
{ {
public function setUp() public function setUp(): void
{ {
parent::setUp(); parent::setUp();
...@@ -11,7 +14,7 @@ class QueueTest extends TestCase ...@@ -11,7 +14,7 @@ class QueueTest extends TestCase
Queue::getDatabase()->table(Config::get('queue.failed.table'))->truncate(); Queue::getDatabase()->table(Config::get('queue.failed.table'))->truncate();
} }
public function testQueueJobLifeCycle() public function testQueueJobLifeCycle(): void
{ {
$id = Queue::push('test', ['action' => 'QueueJobLifeCycle'], 'test'); $id = Queue::push('test', ['action' => 'QueueJobLifeCycle'], 'test');
$this->assertNotNull($id); $this->assertNotNull($id);
...@@ -24,6 +27,7 @@ class QueueTest extends TestCase ...@@ -24,6 +27,7 @@ class QueueTest extends TestCase
'displayName' => 'test', 'displayName' => 'test',
'job' => 'test', 'job' => 'test',
'maxTries' => null, 'maxTries' => null,
'delay' => null,
'timeout' => null, 'timeout' => null,
'data' => ['action' => 'QueueJobLifeCycle'], 'data' => ['action' => 'QueueJobLifeCycle'],
]), $job->getRawBody()); ]), $job->getRawBody());
...@@ -33,7 +37,7 @@ class QueueTest extends TestCase ...@@ -33,7 +37,7 @@ class QueueTest extends TestCase
$this->assertEquals(0, Queue::getDatabase()->table(Config::get('queue.connections.database.table'))->count()); $this->assertEquals(0, Queue::getDatabase()->table(Config::get('queue.connections.database.table'))->count());
} }
public function testQueueJobExpired() public function testQueueJobExpired(): void
{ {
$id = Queue::push('test', ['action' => 'QueueJobExpired'], 'test'); $id = Queue::push('test', ['action' => 'QueueJobExpired'], 'test');
$this->assertNotNull($id); $this->assertNotNull($id);
...@@ -53,4 +57,38 @@ class QueueTest extends TestCase ...@@ -53,4 +57,38 @@ class QueueTest extends TestCase
$job->delete(); $job->delete();
$this->assertEquals(0, Queue::getDatabase()->table(Config::get('queue.connections.database.table'))->count()); $this->assertEquals(0, Queue::getDatabase()->table(Config::get('queue.connections.database.table'))->count());
} }
public function testFailQueueJob(): void
{
$provider = app('queue.failer');
$this->assertInstanceOf(MongoFailedJobProvider::class, $provider);
}
public function testFindFailJobNull(): void
{
Config::set('queue.failed.database', 'mongodb');
$provider = app('queue.failer');
$this->assertNull($provider->find(1));
}
public function testIncrementAttempts(): void
{
$job_id = Queue::push('test1', ['action' => 'QueueJobExpired'], 'test');
$this->assertNotNull($job_id);
$job_id = Queue::push('test2', ['action' => 'QueueJobExpired'], 'test');
$this->assertNotNull($job_id);
$job = Queue::pop('test');
$this->assertEquals(1, $job->attempts());
$job->delete();
$others_jobs = Queue::getDatabase()
->table(Config::get('queue.connections.database.table'))
->get();
$this->assertCount(1, $others_jobs);
$this->assertEquals(0, $others_jobs[0]['attempts']);
}
} }
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Collection;
class RelationsTest extends TestCase class RelationsTest extends TestCase
{ {
public function tearDown() public function tearDown(): void
{ {
Mockery::close(); Mockery::close();
...@@ -17,7 +20,7 @@ class RelationsTest extends TestCase ...@@ -17,7 +20,7 @@ class RelationsTest extends TestCase
Photo::truncate(); Photo::truncate();
} }
public function testHasMany() public function testHasMany(): void
{ {
$author = User::create(['name' => 'George R. R. Martin']); $author = User::create(['name' => 'George R. R. Martin']);
Book::create(['title' => 'A Game of Thrones', 'author_id' => $author->_id]); Book::create(['title' => 'A Game of Thrones', 'author_id' => $author->_id]);
...@@ -36,7 +39,7 @@ class RelationsTest extends TestCase ...@@ -36,7 +39,7 @@ class RelationsTest extends TestCase
$this->assertCount(3, $items); $this->assertCount(3, $items);
} }
public function testBelongsTo() public function testBelongsTo(): void
{ {
$user = User::create(['name' => 'George R. R. Martin']); $user = User::create(['name' => 'George R. R. Martin']);
Book::create(['title' => 'A Game of Thrones', 'author_id' => $user->_id]); Book::create(['title' => 'A Game of Thrones', 'author_id' => $user->_id]);
...@@ -55,7 +58,7 @@ class RelationsTest extends TestCase ...@@ -55,7 +58,7 @@ class RelationsTest extends TestCase
$this->assertNull($book->author); $this->assertNull($book->author);
} }
public function testHasOne() public function testHasOne(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
Role::create(['type' => 'admin', 'user_id' => $user->_id]); Role::create(['type' => 'admin', 'user_id' => $user->_id]);
...@@ -78,7 +81,7 @@ class RelationsTest extends TestCase ...@@ -78,7 +81,7 @@ class RelationsTest extends TestCase
$this->assertEquals($user->_id, $role->user_id); $this->assertEquals($user->_id, $role->user_id);
} }
public function testWithBelongsTo() public function testWithBelongsTo(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
Item::create(['type' => 'knife', 'user_id' => $user->_id]); Item::create(['type' => 'knife', 'user_id' => $user->_id]);
...@@ -89,13 +92,13 @@ class RelationsTest extends TestCase ...@@ -89,13 +92,13 @@ class RelationsTest extends TestCase
$items = Item::with('user')->orderBy('user_id', 'desc')->get(); $items = Item::with('user')->orderBy('user_id', 'desc')->get();
$user = $items[0]->getRelation('user'); $user = $items[0]->getRelation('user');
$this->assertInstanceOf('User', $user); $this->assertInstanceOf(User::class, $user);
$this->assertEquals('John Doe', $user->name); $this->assertEquals('John Doe', $user->name);
$this->assertCount(1, $items[0]->getRelations()); $this->assertCount(1, $items[0]->getRelations());
$this->assertNull($items[3]->getRelation('user')); $this->assertNull($items[3]->getRelation('user'));
} }
public function testWithHashMany() public function testWithHashMany(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
Item::create(['type' => 'knife', 'user_id' => $user->_id]); Item::create(['type' => 'knife', 'user_id' => $user->_id]);
...@@ -107,10 +110,10 @@ class RelationsTest extends TestCase ...@@ -107,10 +110,10 @@ class RelationsTest extends TestCase
$items = $user->getRelation('items'); $items = $user->getRelation('items');
$this->assertCount(3, $items); $this->assertCount(3, $items);
$this->assertInstanceOf('Item', $items[0]); $this->assertInstanceOf(Item::class, $items[0]);
} }
public function testWithHasOne() public function testWithHasOne(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
Role::create(['type' => 'admin', 'user_id' => $user->_id]); Role::create(['type' => 'admin', 'user_id' => $user->_id]);
...@@ -119,11 +122,11 @@ class RelationsTest extends TestCase ...@@ -119,11 +122,11 @@ class RelationsTest extends TestCase
$user = User::with('role')->find($user->_id); $user = User::with('role')->find($user->_id);
$role = $user->getRelation('role'); $role = $user->getRelation('role');
$this->assertInstanceOf('Role', $role); $this->assertInstanceOf(Role::class, $role);
$this->assertEquals('admin', $role->type); $this->assertEquals('admin', $role->type);
} }
public function testEasyRelation() public function testEasyRelation(): void
{ {
// Has Many // Has Many
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
...@@ -133,7 +136,7 @@ class RelationsTest extends TestCase ...@@ -133,7 +136,7 @@ class RelationsTest extends TestCase
$user = User::find($user->_id); $user = User::find($user->_id);
$items = $user->items; $items = $user->items;
$this->assertCount(1, $items); $this->assertCount(1, $items);
$this->assertInstanceOf('Item', $items[0]); $this->assertInstanceOf(Item::class, $items[0]);
$this->assertEquals($user->_id, $items[0]->user_id); $this->assertEquals($user->_id, $items[0]->user_id);
// Has one // Has one
...@@ -143,12 +146,12 @@ class RelationsTest extends TestCase ...@@ -143,12 +146,12 @@ class RelationsTest extends TestCase
$user = User::find($user->_id); $user = User::find($user->_id);
$role = $user->role; $role = $user->role;
$this->assertInstanceOf('Role', $role); $this->assertInstanceOf(Role::class, $role);
$this->assertEquals('admin', $role->type); $this->assertEquals('admin', $role->type);
$this->assertEquals($user->_id, $role->user_id); $this->assertEquals($user->_id, $role->user_id);
} }
public function testBelongsToMany() public function testBelongsToMany(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
...@@ -167,18 +170,18 @@ class RelationsTest extends TestCase ...@@ -167,18 +170,18 @@ class RelationsTest extends TestCase
$clients = $user->getRelation('clients'); $clients = $user->getRelation('clients');
$users = $client->getRelation('users'); $users = $client->getRelation('users');
$this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $users); $this->assertInstanceOf(Collection::class, $users);
$this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $clients); $this->assertInstanceOf(Collection::class, $clients);
$this->assertInstanceOf('Client', $clients[0]); $this->assertInstanceOf(Client::class, $clients[0]);
$this->assertInstanceOf('User', $users[0]); $this->assertInstanceOf(User::class, $users[0]);
$this->assertCount(2, $user->clients); $this->assertCount(2, $user->clients);
$this->assertCount(1, $client->users); $this->assertCount(1, $client->users);
// Now create a new user to an existing client // Now create a new user to an existing client
$user = $client->users()->create(['name' => 'Jane Doe']); $user = $client->users()->create(['name' => 'Jane Doe']);
$this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $user->clients); $this->assertInstanceOf(Collection::class, $user->clients);
$this->assertInstanceOf('Client', $user->clients->first()); $this->assertInstanceOf(Client::class, $user->clients->first());
$this->assertCount(1, $user->clients); $this->assertCount(1, $user->clients);
// Get user and unattached client // Get user and unattached client
...@@ -186,8 +189,8 @@ class RelationsTest extends TestCase ...@@ -186,8 +189,8 @@ class RelationsTest extends TestCase
$client = Client::Where('name', '=', 'Buffet Bar Inc.')->first(); $client = Client::Where('name', '=', 'Buffet Bar Inc.')->first();
// Check the models are what they should be // Check the models are what they should be
$this->assertInstanceOf('Client', $client); $this->assertInstanceOf(Client::class, $client);
$this->assertInstanceOf('User', $user); $this->assertInstanceOf(User::class, $user);
// Assert they are not attached // Assert they are not attached
$this->assertNotContains($client->_id, $user->client_ids); $this->assertNotContains($client->_id, $user->client_ids);
...@@ -222,7 +225,7 @@ class RelationsTest extends TestCase ...@@ -222,7 +225,7 @@ class RelationsTest extends TestCase
$this->assertCount(1, $client->users); $this->assertCount(1, $client->users);
} }
public function testBelongsToManyAttachesExistingModels() public function testBelongsToManyAttachesExistingModels(): void
{ {
$user = User::create(['name' => 'John Doe', 'client_ids' => ['1234523']]); $user = User::create(['name' => 'John Doe', 'client_ids' => ['1234523']]);
...@@ -261,7 +264,7 @@ class RelationsTest extends TestCase ...@@ -261,7 +264,7 @@ class RelationsTest extends TestCase
$this->assertStringStartsWith('synced', $user->clients[1]->name); $this->assertStringStartsWith('synced', $user->clients[1]->name);
} }
public function testBelongsToManySync() public function testBelongsToManySync(): void
{ {
// create test instances // create test instances
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
...@@ -280,7 +283,7 @@ class RelationsTest extends TestCase ...@@ -280,7 +283,7 @@ class RelationsTest extends TestCase
$this->assertCount(1, $user->clients); $this->assertCount(1, $user->clients);
} }
public function testBelongsToManyAttachArray() public function testBelongsToManyAttachArray(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$client1 = Client::create(['name' => 'Test 1'])->_id; $client1 = Client::create(['name' => 'Test 1'])->_id;
...@@ -291,7 +294,7 @@ class RelationsTest extends TestCase ...@@ -291,7 +294,7 @@ class RelationsTest extends TestCase
$this->assertCount(2, $user->clients); $this->assertCount(2, $user->clients);
} }
public function testBelongsToManyAttachEloquentCollection() public function testBelongsToManyAttachEloquentCollection(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$client1 = Client::create(['name' => 'Test 1']); $client1 = Client::create(['name' => 'Test 1']);
...@@ -303,7 +306,7 @@ class RelationsTest extends TestCase ...@@ -303,7 +306,7 @@ class RelationsTest extends TestCase
$this->assertCount(2, $user->clients); $this->assertCount(2, $user->clients);
} }
public function testBelongsToManySyncAlreadyPresent() public function testBelongsToManySyncAlreadyPresent(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$client1 = Client::create(['name' => 'Test 1'])->_id; $client1 = Client::create(['name' => 'Test 1'])->_id;
...@@ -320,7 +323,7 @@ class RelationsTest extends TestCase ...@@ -320,7 +323,7 @@ class RelationsTest extends TestCase
$this->assertCount(1, $user['client_ids']); $this->assertCount(1, $user['client_ids']);
} }
public function testBelongsToManyCustom() public function testBelongsToManyCustom(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$group = $user->groups()->create(['name' => 'Admins']); $group = $user->groups()->create(['name' => 'Admins']);
...@@ -340,7 +343,7 @@ class RelationsTest extends TestCase ...@@ -340,7 +343,7 @@ class RelationsTest extends TestCase
$this->assertEquals($user->_id, $group->users()->first()->_id); $this->assertEquals($user->_id, $group->users()->first()->_id);
} }
public function testMorph() public function testMorph(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$client = Client::create(['name' => 'Jane Doe']); $client = Client::create(['name' => 'Jane Doe']);
...@@ -376,14 +379,14 @@ class RelationsTest extends TestCase ...@@ -376,14 +379,14 @@ class RelationsTest extends TestCase
$photos = Photo::with('imageable')->get(); $photos = Photo::with('imageable')->get();
$relations = $photos[0]->getRelations(); $relations = $photos[0]->getRelations();
$this->assertArrayHasKey('imageable', $relations); $this->assertArrayHasKey('imageable', $relations);
$this->assertInstanceOf('User', $photos[0]->imageable); $this->assertInstanceOf(User::class, $photos[0]->imageable);
$relations = $photos[1]->getRelations(); $relations = $photos[1]->getRelations();
$this->assertArrayHasKey('imageable', $relations); $this->assertArrayHasKey('imageable', $relations);
$this->assertInstanceOf('Client', $photos[1]->imageable); $this->assertInstanceOf(Client::class, $photos[1]->imageable);
} }
public function testHasManyHas() public function testHasManyHas(): void
{ {
$author1 = User::create(['name' => 'George R. R. Martin']); $author1 = User::create(['name' => 'George R. R. Martin']);
$author1->books()->create(['title' => 'A Game of Thrones', 'rating' => 5]); $author1->books()->create(['title' => 'A Game of Thrones', 'rating' => 5]);
...@@ -433,7 +436,7 @@ class RelationsTest extends TestCase ...@@ -433,7 +436,7 @@ class RelationsTest extends TestCase
$this->assertCount(1, $authors); $this->assertCount(1, $authors);
} }
public function testHasOneHas() public function testHasOneHas(): void
{ {
$user1 = User::create(['name' => 'John Doe']); $user1 = User::create(['name' => 'John Doe']);
$user1->role()->create(['title' => 'admin']); $user1->role()->create(['title' => 'admin']);
...@@ -455,19 +458,19 @@ class RelationsTest extends TestCase ...@@ -455,19 +458,19 @@ class RelationsTest extends TestCase
$this->assertCount(2, $users); $this->assertCount(2, $users);
} }
public function testNestedKeys() public function testNestedKeys(): void
{ {
$client = Client::create([ $client = Client::create([
'data' => [ 'data' => [
'client_id' => 35298, 'client_id' => 35298,
'name' => 'John Doe', 'name' => 'John Doe',
], ],
]); ]);
$address = $client->addresses()->create([ $address = $client->addresses()->create([
'data' => [ 'data' => [
'address_id' => 1432, 'address_id' => 1432,
'city' => 'Paris', 'city' => 'Paris',
], ],
]); ]);
...@@ -481,7 +484,7 @@ class RelationsTest extends TestCase ...@@ -481,7 +484,7 @@ class RelationsTest extends TestCase
$this->assertEquals('Paris', $client->addresses->first()->data['city']); $this->assertEquals('Paris', $client->addresses->first()->data['city']);
} }
public function testDoubleSaveOneToMany() public function testDoubleSaveOneToMany(): void
{ {
$author = User::create(['name' => 'George R. R. Martin']); $author = User::create(['name' => 'George R. R. Martin']);
$book = Book::create(['title' => 'A Game of Thrones']); $book = Book::create(['title' => 'A Game of Thrones']);
...@@ -504,7 +507,7 @@ class RelationsTest extends TestCase ...@@ -504,7 +507,7 @@ class RelationsTest extends TestCase
$this->assertEquals($author->_id, $book->author_id); $this->assertEquals($author->_id, $book->author_id);
} }
public function testDoubleSaveManyToMany() public function testDoubleSaveManyToMany(): void
{ {
$user = User::create(['name' => 'John Doe']); $user = User::create(['name' => 'John Doe']);
$client = Client::create(['name' => 'Admins']); $client = Client::create(['name' => 'Admins']);
......
<?php <?php
declare(strict_types=1);
use Jenssegers\Mongodb\Schema\Blueprint;
class SchemaTest extends TestCase class SchemaTest extends TestCase
{ {
public function tearDown() public function tearDown(): void
{ {
Schema::drop('newcollection'); Schema::drop('newcollection');
Schema::drop('newcollection_two');
} }
public function testCreate() public function testCreate(): void
{ {
Schema::create('newcollection'); Schema::create('newcollection');
$this->assertTrue(Schema::hasCollection('newcollection')); $this->assertTrue(Schema::hasCollection('newcollection'));
$this->assertTrue(Schema::hasTable('newcollection')); $this->assertTrue(Schema::hasTable('newcollection'));
} }
public function testCreateWithCallback() public function testCreateWithCallback(): void
{ {
$instance = $this; $instance = $this;
Schema::create('newcollection', function ($collection) use ($instance) { Schema::create('newcollection', function ($collection) use ($instance) {
$instance->assertInstanceOf('Jenssegers\Mongodb\Schema\Blueprint', $collection); $instance->assertInstanceOf(Blueprint::class, $collection);
}); });
$this->assertTrue(Schema::hasCollection('newcollection')); $this->assertTrue(Schema::hasCollection('newcollection'));
} }
public function testDrop() public function testCreateWithOptions(): void
{
Schema::create('newcollection_two', null, ['capped' => true, 'size' => 1024]);
$this->assertTrue(Schema::hasCollection('newcollection_two'));
$this->assertTrue(Schema::hasTable('newcollection_two'));
}
public function testDrop(): void
{ {
Schema::create('newcollection'); Schema::create('newcollection');
Schema::drop('newcollection'); Schema::drop('newcollection');
$this->assertFalse(Schema::hasCollection('newcollection')); $this->assertFalse(Schema::hasCollection('newcollection'));
} }
public function testBluePrint() public function testBluePrint(): void
{ {
$instance = $this; $instance = $this;
Schema::collection('newcollection', function ($collection) use ($instance) { Schema::collection('newcollection', function ($collection) use ($instance) {
$instance->assertInstanceOf('Jenssegers\Mongodb\Schema\Blueprint', $collection); $instance->assertInstanceOf(Blueprint::class, $collection);
}); });
Schema::table('newcollection', function ($collection) use ($instance) { Schema::table('newcollection', function ($collection) use ($instance) {
$instance->assertInstanceOf('Jenssegers\Mongodb\Schema\Blueprint', $collection); $instance->assertInstanceOf(Blueprint::class, $collection);
}); });
} }
public function testIndex() public function testIndex(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->index('mykey1'); $collection->index('mykey1');
...@@ -69,7 +80,7 @@ class SchemaTest extends TestCase ...@@ -69,7 +80,7 @@ class SchemaTest extends TestCase
$this->assertEquals(1, $index['key']['mykey3']); $this->assertEquals(1, $index['key']['mykey3']);
} }
public function testPrimary() public function testPrimary(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->string('mykey', 100)->primary(); $collection->string('mykey', 100)->primary();
...@@ -79,7 +90,7 @@ class SchemaTest extends TestCase ...@@ -79,7 +90,7 @@ class SchemaTest extends TestCase
$this->assertEquals(1, $index['unique']); $this->assertEquals(1, $index['unique']);
} }
public function testUnique() public function testUnique(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->unique('uniquekey'); $collection->unique('uniquekey');
...@@ -89,7 +100,7 @@ class SchemaTest extends TestCase ...@@ -89,7 +100,7 @@ class SchemaTest extends TestCase
$this->assertEquals(1, $index['unique']); $this->assertEquals(1, $index['unique']);
} }
public function testDropIndex() public function testDropIndex(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->unique('uniquekey'); $collection->unique('uniquekey');
...@@ -121,6 +132,20 @@ class SchemaTest extends TestCase ...@@ -121,6 +132,20 @@ class SchemaTest extends TestCase
$index = $this->getIndex('newcollection', 'field_a_1_field_b_1'); $index = $this->getIndex('newcollection', 'field_a_1_field_b_1');
$this->assertFalse($index); $this->assertFalse($index);
Schema::collection('newcollection', function ($collection) {
$collection->index(['field_a' => -1, 'field_b' => 1]);
});
$index = $this->getIndex('newcollection', 'field_a_-1_field_b_1');
$this->assertNotNull($index);
Schema::collection('newcollection', function ($collection) {
$collection->dropIndex(['field_a' => -1, 'field_b' => 1]);
});
$index = $this->getIndex('newcollection', 'field_a_-1_field_b_1');
$this->assertFalse($index);
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->index(['field_a', 'field_b'], 'custom_index_name'); $collection->index(['field_a', 'field_b'], 'custom_index_name');
}); });
...@@ -136,7 +161,77 @@ class SchemaTest extends TestCase ...@@ -136,7 +161,77 @@ class SchemaTest extends TestCase
$this->assertFalse($index); $this->assertFalse($index);
} }
public function testBackground() public function testDropIndexIfExists(): void
{
Schema::collection('newcollection', function (Blueprint $collection) {
$collection->unique('uniquekey');
$collection->dropIndexIfExists('uniquekey_1');
});
$index = $this->getIndex('newcollection', 'uniquekey');
$this->assertEquals(null, $index);
Schema::collection('newcollection', function (Blueprint $collection) {
$collection->unique('uniquekey');
$collection->dropIndexIfExists(['uniquekey']);
});
$index = $this->getIndex('newcollection', 'uniquekey');
$this->assertEquals(null, $index);
Schema::collection('newcollection', function (Blueprint $collection) {
$collection->index(['field_a', 'field_b']);
});
$index = $this->getIndex('newcollection', 'field_a_1_field_b_1');
$this->assertNotNull($index);
Schema::collection('newcollection', function (Blueprint $collection) {
$collection->dropIndexIfExists(['field_a', 'field_b']);
});
$index = $this->getIndex('newcollection', 'field_a_1_field_b_1');
$this->assertFalse($index);
Schema::collection('newcollection', function (Blueprint $collection) {
$collection->index(['field_a', 'field_b'], 'custom_index_name');
});
$index = $this->getIndex('newcollection', 'custom_index_name');
$this->assertNotNull($index);
Schema::collection('newcollection', function (Blueprint $collection) {
$collection->dropIndexIfExists('custom_index_name');
});
$index = $this->getIndex('newcollection', 'custom_index_name');
$this->assertFalse($index);
}
public function testHasIndex(): void
{
$instance = $this;
Schema::collection('newcollection', function (Blueprint $collection) use ($instance) {
$collection->index('myhaskey1');
$instance->assertTrue($collection->hasIndex('myhaskey1_1'));
$instance->assertFalse($collection->hasIndex('myhaskey1'));
});
Schema::collection('newcollection', function (Blueprint $collection) use ($instance) {
$collection->index('myhaskey2');
$instance->assertTrue($collection->hasIndex(['myhaskey2']));
$instance->assertFalse($collection->hasIndex(['myhaskey2_1']));
});
Schema::collection('newcollection', function (Blueprint $collection) use ($instance) {
$collection->index(['field_a', 'field_b']);
$instance->assertTrue($collection->hasIndex(['field_a_1_field_b']));
$instance->assertFalse($collection->hasIndex(['field_a_1_field_b_1']));
});
}
public function testBackground(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->background('backgroundkey'); $collection->background('backgroundkey');
...@@ -146,7 +241,7 @@ class SchemaTest extends TestCase ...@@ -146,7 +241,7 @@ class SchemaTest extends TestCase
$this->assertEquals(1, $index['background']); $this->assertEquals(1, $index['background']);
} }
public function testSparse() public function testSparse(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->sparse('sparsekey'); $collection->sparse('sparsekey');
...@@ -156,7 +251,7 @@ class SchemaTest extends TestCase ...@@ -156,7 +251,7 @@ class SchemaTest extends TestCase
$this->assertEquals(1, $index['sparse']); $this->assertEquals(1, $index['sparse']);
} }
public function testExpire() public function testExpire(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->expire('expirekey', 60); $collection->expire('expirekey', 60);
...@@ -166,7 +261,7 @@ class SchemaTest extends TestCase ...@@ -166,7 +261,7 @@ class SchemaTest extends TestCase
$this->assertEquals(60, $index['expireAfterSeconds']); $this->assertEquals(60, $index['expireAfterSeconds']);
} }
public function testSoftDeletes() public function testSoftDeletes(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->softDeletes(); $collection->softDeletes();
...@@ -180,7 +275,7 @@ class SchemaTest extends TestCase ...@@ -180,7 +275,7 @@ class SchemaTest extends TestCase
$this->assertEquals(1, $index['key']['email']); $this->assertEquals(1, $index['key']['email']);
} }
public function testFluent() public function testFluent(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->string('email')->index(); $collection->string('email')->index();
...@@ -195,7 +290,7 @@ class SchemaTest extends TestCase ...@@ -195,7 +290,7 @@ class SchemaTest extends TestCase
$this->assertEquals(1, $index['key']['token']); $this->assertEquals(1, $index['key']['token']);
} }
public function testGeospatial() public function testGeospatial(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->geospatial('point'); $collection->geospatial('point');
...@@ -213,15 +308,16 @@ class SchemaTest extends TestCase ...@@ -213,15 +308,16 @@ class SchemaTest extends TestCase
$this->assertEquals('2dsphere', $index['key']['continent']); $this->assertEquals('2dsphere', $index['key']['continent']);
} }
public function testDummies() public function testDummies(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->boolean('activated')->default(0); $collection->boolean('activated')->default(0);
$collection->integer('user_id')->unsigned(); $collection->integer('user_id')->unsigned();
}); });
$this->expectNotToPerformAssertions();
} }
public function testSparseUnique() public function testSparseUnique(): void
{ {
Schema::collection('newcollection', function ($collection) { Schema::collection('newcollection', function ($collection) {
$collection->sparse_and_unique('sparseuniquekey'); $collection->sparse_and_unique('sparseuniquekey');
...@@ -232,7 +328,7 @@ class SchemaTest extends TestCase ...@@ -232,7 +328,7 @@ class SchemaTest extends TestCase
$this->assertEquals(1, $index['unique']); $this->assertEquals(1, $index['unique']);
} }
protected function getIndex($collection, $name) protected function getIndex(string $collection, string $name)
{ {
$collection = DB::getCollection($collection); $collection = DB::getCollection($collection);
......
<?php <?php
declare(strict_types=1);
class SeederTest extends TestCase class SeederTest extends TestCase
{ {
public function tearDown() public function tearDown(): void
{ {
User::truncate(); User::truncate();
} }
public function testSeed() public function testSeed(): void
{ {
$seeder = new UserTableSeeder; $seeder = new UserTableSeeder;
$seeder->run(); $seeder->run();
...@@ -16,7 +17,7 @@ class SeederTest extends TestCase ...@@ -16,7 +17,7 @@ class SeederTest extends TestCase
$this->assertTrue($user->seed); $this->assertTrue($user->seed);
} }
public function testArtisan() public function testArtisan(): void
{ {
Artisan::call('db:seed'); Artisan::call('db:seed');
......
<?php <?php
declare(strict_types=1);
use Illuminate\Auth\Passwords\PasswordResetServiceProvider;
class TestCase extends Orchestra\Testbench\TestCase class TestCase extends Orchestra\Testbench\TestCase
{ {
/** /**
* Get application providers. * Get application providers.
* * @param \Illuminate\Foundation\Application $app
* @param \Illuminate\Foundation\Application $app
*
* @return array * @return array
*/ */
protected function getApplicationProviders($app) protected function getApplicationProviders($app)
{ {
$providers = parent::getApplicationProviders($app); $providers = parent::getApplicationProviders($app);
unset($providers[array_search('Illuminate\Auth\Passwords\PasswordResetServiceProvider', $providers)]); unset($providers[array_search(PasswordResetServiceProvider::class, $providers)]);
return $providers; return $providers;
} }
/** /**
* Get package providers. * Get package providers.
* * @param \Illuminate\Foundation\Application $app
* @param \Illuminate\Foundation\Application $app
* @return array * @return array
*/ */
protected function getPackageProviders($app) protected function getPackageProviders($app)
{ {
return [ return [
Jenssegers\Mongodb\MongodbServiceProvider::class, Jenssegers\Mongodb\MongodbServiceProvider::class,
Jenssegers\Mongodb\MongodbQueueServiceProvider::class,
Jenssegers\Mongodb\Auth\PasswordResetServiceProvider::class, Jenssegers\Mongodb\Auth\PasswordResetServiceProvider::class,
Jenssegers\Mongodb\Validation\ValidationServiceProvider::class Jenssegers\Mongodb\Validation\ValidationServiceProvider::class,
]; ];
} }
/** /**
* Define environment setup. * Define environment setup.
* * @param Illuminate\Foundation\Application $app
* @param Illuminate\Foundation\Application $app
* @return void * @return void
*/ */
protected function getEnvironmentSetUp($app) protected function getEnvironmentSetUp($app)
...@@ -51,6 +51,7 @@ class TestCase extends Orchestra\Testbench\TestCase ...@@ -51,6 +51,7 @@ class TestCase extends Orchestra\Testbench\TestCase
$app['config']->set('database.default', 'mongodb'); $app['config']->set('database.default', 'mongodb');
$app['config']->set('database.connections.mysql', $config['connections']['mysql']); $app['config']->set('database.connections.mysql', $config['connections']['mysql']);
$app['config']->set('database.connections.mongodb', $config['connections']['mongodb']); $app['config']->set('database.connections.mongodb', $config['connections']['mongodb']);
$app['config']->set('database.connections.mongodb2', $config['connections']['mongodb']);
$app['config']->set('database.connections.dsn_mongodb', $config['connections']['dsn_mongodb']); $app['config']->set('database.connections.dsn_mongodb', $config['connections']['dsn_mongodb']);
$app['config']->set('auth.model', 'User'); $app['config']->set('auth.model', 'User');
...@@ -60,9 +61,10 @@ class TestCase extends Orchestra\Testbench\TestCase ...@@ -60,9 +61,10 @@ class TestCase extends Orchestra\Testbench\TestCase
$app['config']->set('queue.default', 'database'); $app['config']->set('queue.default', 'database');
$app['config']->set('queue.connections.database', [ $app['config']->set('queue.connections.database', [
'driver' => 'mongodb', 'driver' => 'mongodb',
'table' => 'jobs', 'table' => 'jobs',
'queue' => 'default', 'queue' => 'default',
'expire' => 60, 'expire' => 60,
]); ]);
$app['config']->set('queue.failed.database', 'mongodb2');
} }
} }
<?php <?php
declare(strict_types=1);
class ValidationTest extends TestCase class ValidationTest extends TestCase
{ {
public function tearDown() public function tearDown(): void
{ {
User::truncate(); User::truncate();
} }
public function testUnique() public function testUnique(): void
{ {
$validator = Validator::make( $validator = Validator::make(
['name' => 'John Doe'], ['name' => 'John Doe'],
...@@ -42,7 +43,7 @@ class ValidationTest extends TestCase ...@@ -42,7 +43,7 @@ class ValidationTest extends TestCase
$this->assertFalse($validator->fails()); $this->assertFalse($validator->fails());
} }
public function testExists() public function testExists(): void
{ {
$validator = Validator::make( $validator = Validator::make(
['name' => 'John Doe'], ['name' => 'John Doe'],
......
<?php <?php
$mongoHost = env('MONGO_HOST', 'mongodb');
$mongoPort = env('MONGO_PORT') ? (int) env('MONGO_PORT') : 27017;
$mysqlPort = env('MYSQL_PORT') ? (int) env('MYSQL_PORT') : 3306;
return [ return [
'connections' => [ 'connections' => [
'mongodb' => [ 'mongodb' => [
'name' => 'mongodb', 'name' => 'mongodb',
'driver' => 'mongodb', 'driver' => 'mongodb',
'host' => 'mongodb', 'host' => $mongoHost,
'database' => 'unittest', 'database' => env('MONGO_DATABASE', 'unittest'),
],
'dsn_mongodb' => [
'driver' => 'mongodb',
'dsn' => "mongodb://$mongoHost:$mongoPort",
'database' => env('MONGO_DATABASE', 'unittest'),
], ],
'dsn_mongodb' => [ 'dsn_mongodb' => [
...@@ -18,14 +28,15 @@ return [ ...@@ -18,14 +28,15 @@ return [
], ],
'mysql' => [ 'mysql' => [
'driver' => 'mysql', 'driver' => 'mysql',
'host' => 'mysql', 'host' => env('MYSQL_HOST', 'mysql'),
'database' => 'unittest', 'port' => $mysqlPort,
'username' => 'root', 'database' => env('MYSQL_DATABASE', 'unittest'),
'password' => '', 'username' => env('MYSQL_USERNAME', 'root'),
'charset' => 'utf8', 'password' => env('MYSQL_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci', 'collation' => 'utf8_unicode_ci',
'prefix' => '', 'prefix' => '',
], ],
], ],
......
...@@ -2,22 +2,22 @@ ...@@ -2,22 +2,22 @@
return [ return [
'default' => 'database', 'default' => env('QUEUE_CONNECTION'),
'connections' => [ 'connections' => [
'database' => [ 'database' => [
'driver' => 'mongodb', 'driver' => 'mongodb',
'table' => 'jobs', 'table' => 'jobs',
'queue' => 'default', 'queue' => 'default',
'expire' => 60, 'expire' => 60,
], ],
], ],
'failed' => [ 'failed' => [
'database' => 'mongodb', 'database' => env('MONGO_DATABASE'),
'table' => 'failed_jobs', 'table' => 'failed_jobs',
], ],
]; ];
<?php <?php
declare(strict_types=1);
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
use Jenssegers\Mongodb\Relations\EmbedsMany;
class Address extends Eloquent class Address extends Eloquent
{ {
protected $connection = 'mongodb'; protected $connection = 'mongodb';
protected static $unguarded = true; protected static $unguarded = true;
public function addresses() public function addresses(): EmbedsMany
{ {
return $this->embedsMany('Address'); return $this->embedsMany('Address');
} }
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
/**
* Class Book
* @property string $title
* @property string $author
* @property array $chapters
*/
class Book extends Eloquent class Book extends Eloquent
{ {
protected $connection = 'mongodb'; protected $connection = 'mongodb';
...@@ -9,12 +17,12 @@ class Book extends Eloquent ...@@ -9,12 +17,12 @@ class Book extends Eloquent
protected static $unguarded = true; protected static $unguarded = true;
protected $primaryKey = 'title'; protected $primaryKey = 'title';
public function author() public function author(): BelongsTo
{ {
return $this->belongsTo('User', 'author_id'); return $this->belongsTo('User', 'author_id');
} }
public function mysqlAuthor() public function mysqlAuthor(): BelongsTo
{ {
return $this->belongsTo('MysqlUser', 'author_id'); return $this->belongsTo('MysqlUser', 'author_id');
} }
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Client extends Eloquent class Client extends Eloquent
...@@ -8,17 +12,17 @@ class Client extends Eloquent ...@@ -8,17 +12,17 @@ class Client extends Eloquent
protected $collection = 'clients'; protected $collection = 'clients';
protected static $unguarded = true; protected static $unguarded = true;
public function users() public function users(): BelongsToMany
{ {
return $this->belongsToMany('User'); return $this->belongsToMany('User');
} }
public function photo() public function photo(): MorphOne
{ {
return $this->morphOne('Photo', 'imageable'); return $this->morphOne('Photo', 'imageable');
} }
public function addresses() public function addresses(): HasMany
{ {
return $this->hasMany('Address', 'data.client_id', 'data.client_id'); return $this->hasMany('Address', 'data.client_id', 'data.client_id');
} }
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Group extends Eloquent class Group extends Eloquent
...@@ -8,7 +10,7 @@ class Group extends Eloquent ...@@ -8,7 +10,7 @@ class Group extends Eloquent
protected $collection = 'groups'; protected $collection = 'groups';
protected static $unguarded = true; protected static $unguarded = true;
public function users() public function users(): BelongsToMany
{ {
return $this->belongsToMany('User', 'users', 'groups', 'users', '_id', '_id', 'users'); return $this->belongsToMany('User', 'users', 'groups', 'users', '_id', '_id', 'users');
} }
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Jenssegers\Mongodb\Eloquent\Builder;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
/**
* Class Item
* @property \Carbon\Carbon $created_at
*/
class Item extends Eloquent class Item extends Eloquent
{ {
protected $connection = 'mongodb'; protected $connection = 'mongodb';
protected $collection = 'items'; protected $collection = 'items';
protected static $unguarded = true; protected static $unguarded = true;
public function user() public function user(): BelongsTo
{ {
return $this->belongsTo('User'); return $this->belongsTo('User');
} }
public function scopeSharp($query) public function scopeSharp(Builder $query)
{ {
return $query->where('type', 'sharp'); return $query->where('type', 'sharp');
} }
......
<?php <?php
declare(strict_types=1);
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Jenssegers\Mongodb\Eloquent\HybridRelations; use Jenssegers\Mongodb\Eloquent\HybridRelations;
...@@ -12,7 +15,7 @@ class MysqlBook extends Eloquent ...@@ -12,7 +15,7 @@ class MysqlBook extends Eloquent
protected static $unguarded = true; protected static $unguarded = true;
protected $primaryKey = 'title'; protected $primaryKey = 'title';
public function author() public function author(): BelongsTo
{ {
return $this->belongsTo('User', 'author_id'); return $this->belongsTo('User', 'author_id');
} }
...@@ -20,12 +23,13 @@ class MysqlBook extends Eloquent ...@@ -20,12 +23,13 @@ class MysqlBook extends Eloquent
/** /**
* Check if we need to run the schema. * Check if we need to run the schema.
*/ */
public static function executeSchema() public static function executeSchema(): void
{ {
/** @var \Illuminate\Database\Schema\MySqlBuilder $schema */
$schema = Schema::connection('mysql'); $schema = Schema::connection('mysql');
if (!$schema->hasTable('books')) { if (!$schema->hasTable('books')) {
Schema::connection('mysql')->create('books', function ($table) { Schema::connection('mysql')->create('books', function (Blueprint $table) {
$table->string('title'); $table->string('title');
$table->string('author_id')->nullable(); $table->string('author_id')->nullable();
$table->integer('mysql_user_id')->unsigned()->nullable(); $table->integer('mysql_user_id')->unsigned()->nullable();
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Jenssegers\Mongodb\Eloquent\HybridRelations; use Jenssegers\Mongodb\Eloquent\HybridRelations;
...@@ -11,12 +14,12 @@ class MysqlRole extends Eloquent ...@@ -11,12 +14,12 @@ class MysqlRole extends Eloquent
protected $table = 'roles'; protected $table = 'roles';
protected static $unguarded = true; protected static $unguarded = true;
public function user() public function user(): BelongsTo
{ {
return $this->belongsTo('User'); return $this->belongsTo('User');
} }
public function mysqlUser() public function mysqlUser(): BelongsTo
{ {
return $this->belongsTo('MysqlUser'); return $this->belongsTo('MysqlUser');
} }
...@@ -26,10 +29,11 @@ class MysqlRole extends Eloquent ...@@ -26,10 +29,11 @@ class MysqlRole extends Eloquent
*/ */
public static function executeSchema() public static function executeSchema()
{ {
/** @var \Illuminate\Database\Schema\MySqlBuilder $schema */
$schema = Schema::connection('mysql'); $schema = Schema::connection('mysql');
if (!$schema->hasTable('roles')) { if (!$schema->hasTable('roles')) {
Schema::connection('mysql')->create('roles', function ($table) { Schema::connection('mysql')->create('roles', function (Blueprint $table) {
$table->string('type'); $table->string('type');
$table->string('user_id'); $table->string('user_id');
$table->timestamps(); $table->timestamps();
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Jenssegers\Mongodb\Eloquent\HybridRelations; use Jenssegers\Mongodb\Eloquent\HybridRelations;
...@@ -11,17 +15,17 @@ class MysqlUser extends Eloquent ...@@ -11,17 +15,17 @@ class MysqlUser extends Eloquent
protected $table = 'users'; protected $table = 'users';
protected static $unguarded = true; protected static $unguarded = true;
public function books() public function books(): HasMany
{ {
return $this->hasMany('Book', 'author_id'); return $this->hasMany('Book', 'author_id');
} }
public function role() public function role(): HasOne
{ {
return $this->hasOne('Role'); return $this->hasOne('Role');
} }
public function mysqlBooks() public function mysqlBooks(): HasMany
{ {
return $this->hasMany(MysqlBook::class); return $this->hasMany(MysqlBook::class);
} }
...@@ -29,12 +33,13 @@ class MysqlUser extends Eloquent ...@@ -29,12 +33,13 @@ class MysqlUser extends Eloquent
/** /**
* Check if we need to run the schema. * Check if we need to run the schema.
*/ */
public static function executeSchema() public static function executeSchema(): void
{ {
/** @var \Illuminate\Database\Schema\MySqlBuilder $schema */
$schema = Schema::connection('mysql'); $schema = Schema::connection('mysql');
if (!$schema->hasTable('users')) { if (!$schema->hasTable('users')) {
Schema::connection('mysql')->create('users', function ($table) { Schema::connection('mysql')->create('users', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->string('name'); $table->string('name');
$table->timestamps(); $table->timestamps();
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Photo extends Eloquent class Photo extends Eloquent
...@@ -8,7 +10,7 @@ class Photo extends Eloquent ...@@ -8,7 +10,7 @@ class Photo extends Eloquent
protected $collection = 'photos'; protected $collection = 'photos';
protected static $unguarded = true; protected static $unguarded = true;
public function imageable() public function imageable(): MorphTo
{ {
return $this->morphTo(); return $this->morphTo();
} }
......
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Role extends Eloquent class Role extends Eloquent
...@@ -8,12 +10,12 @@ class Role extends Eloquent ...@@ -8,12 +10,12 @@ class Role extends Eloquent
protected $collection = 'roles'; protected $collection = 'roles';
protected static $unguarded = true; protected static $unguarded = true;
public function user() public function user(): BelongsTo
{ {
return $this->belongsTo('User'); return $this->belongsTo('User');
} }
public function mysqlUser() public function mysqlUser(): BelongsTo
{ {
return $this->belongsTo('MysqlUser'); return $this->belongsTo('MysqlUser');
} }
......
<?php
declare(strict_types=1);
use Jenssegers\Mongodb\Eloquent\Builder;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
class Scoped extends Eloquent
{
protected $connection = 'mongodb';
protected $collection = 'scoped';
protected $fillable = ['name', 'favorite'];
protected static function boot()
{
parent::boot();
static::addGlobalScope('favorite', function (Builder $builder) {
$builder->where('favorite', true);
});
}
}
<?php <?php
declare(strict_types=1);
use Jenssegers\Mongodb\Eloquent\Model as Eloquent; use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
use Jenssegers\Mongodb\Eloquent\SoftDeletes; use Jenssegers\Mongodb\Eloquent\SoftDeletes;
/**
* Class Soft
* @property \Carbon\Carbon $deleted_at
*/
class Soft extends Eloquent class Soft extends Eloquent
{ {
use SoftDeletes; use SoftDeletes;
......
<?php <?php
declare(strict_types=1);
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
use Jenssegers\Mongodb\Eloquent\HybridRelations;
use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Notifications\Notifiable;
use Jenssegers\Mongodb\Eloquent\HybridRelations;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
/**
* Class User
* @property string $_id
* @property string $name
* @property string $title
* @property int $age
* @property \Carbon\Carbon $birthday
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
*/
class User extends Eloquent implements AuthenticatableContract, CanResetPasswordContract class User extends Eloquent implements AuthenticatableContract, CanResetPasswordContract
{ {
use Authenticatable, CanResetPassword, HybridRelations; use Authenticatable, CanResetPassword, HybridRelations, Notifiable;
protected $connection = 'mongodb'; protected $connection = 'mongodb';
protected $dates = ['birthday', 'entry.date']; protected $dates = ['birthday', 'entry.date'];
......
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 to comment