diff --git a/.github/workflows/databases-nightly.yml b/.github/workflows/databases-nightly.yml index 059c35ce1321..9003fab41ec5 100644 --- a/.github/workflows/databases-nightly.yml +++ b/.github/workflows/databases-nightly.yml @@ -36,7 +36,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -82,7 +82,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/databases.yml b/.github/workflows/databases.yml index bd20bfad48bd..f2f57a6249a3 100644 --- a/.github/workflows/databases.yml +++ b/.github/workflows/databases.yml @@ -40,7 +40,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -87,7 +87,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -133,7 +133,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -180,7 +180,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -229,7 +229,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -276,7 +276,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -324,7 +324,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -363,7 +363,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/facades.yml b/.github/workflows/facades.yml index 3a3bf57c2f06..7b8671755aae 100644 --- a/.github/workflows/facades.yml +++ b/.github/workflows/facades.yml @@ -26,13 +26,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/queues.yml b/.github/workflows/queues.yml index 3df36c7d6c82..a66202accef5 100644 --- a/.github/workflows/queues.yml +++ b/.github/workflows/queues.yml @@ -23,13 +23,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -58,13 +58,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -106,13 +106,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -144,13 +144,13 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_mysql, :php-psr tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -182,9 +182,9 @@ jobs: fail-fast: true matrix: include: - - php: 8.2 - pheanstalk: 5 - php: 8.3 + pheanstalk: 5 + - php: 8.4 pheanstalk: 7 name: Beanstalkd Driver (pda/pheanstalk:^${{ matrix.pheanstalk }}) @@ -209,7 +209,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index da698e647f91..e112061b8844 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -25,12 +25,12 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.3 tools: composer:v2 coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2a156dd33351..e3267ee11cff 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,14 +39,9 @@ jobs: strategy: fail-fast: true matrix: - php: [8.2, 8.3, 8.4] + php: [8.3, 8.4] phpunit: ['10.5.35', '11.5.3', '12.0.0', '12.1.0'] stability: [prefer-lowest, prefer-stable] - exclude: - - php: 8.2 - phpunit: '12.0.0' - - php: 8.2 - phpunit: '12.1.0' name: PHP ${{ matrix.php }} - PHPUnit ${{ matrix.phpunit }} - ${{ matrix.stability }} @@ -67,7 +62,7 @@ jobs: REDIS_LIBS: liblz4-dev, liblzf-dev, libzstd-dev - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 @@ -100,14 +95,9 @@ jobs: strategy: fail-fast: true matrix: - php: [8.2, 8.3, 8.4] + php: [8.3, 8.4] phpunit: ['10.5.35', '11.5.3', '12.0.0', '12.1.0'] stability: [prefer-lowest, prefer-stable] - exclude: - - php: 8.2 - phpunit: '12.0.0' - - php: 8.2 - phpunit: '12.1.0' name: PHP ${{ matrix.php }} - PHPUnit ${{ matrix.phpunit }} - ${{ matrix.stability }} - Windows @@ -129,7 +119,7 @@ jobs: coverage: none - name: Set Framework version - run: composer config version "12.x-dev" + run: composer config version "13.x-dev" - name: Install dependencies uses: nick-fields/retry@v3 diff --git a/bin/split.sh b/bin/split.sh index ae4cdf01f8f3..9536ec7a4f31 100755 --- a/bin/split.sh +++ b/bin/split.sh @@ -3,7 +3,7 @@ set -e set -x -CURRENT_BRANCH="12.x" +CURRENT_BRANCH="master" function split() { diff --git a/composer.json b/composer.json index 8c76eb8b7c06..4210a1ae0073 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-ctype": "*", "ext-filter": "*", "ext-hash": "*", @@ -51,7 +51,6 @@ "symfony/http-kernel": "^7.2.0", "symfony/mailer": "^7.2.0", "symfony/mime": "^7.2.0", - "symfony/polyfill-php83": "^1.31", "symfony/process": "^7.2.0", "symfony/routing": "^7.2.0", "symfony/uid": "^7.2.0", @@ -111,7 +110,7 @@ "league/flysystem-read-only": "^3.25.1", "league/flysystem-sftp-v3": "^3.25.1", "mockery/mockery": "^1.6.10", - "orchestra/testbench-core": "^10.0.0", + "orchestra/testbench-core": "^11.0.0", "pda/pheanstalk": "^5.0.6|^7.0.0", "php-http/discovery": "^1.15", "phpstan/phpstan": "^2.0", @@ -161,7 +160,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { diff --git a/src/Illuminate/Auth/composer.json b/src/Illuminate/Auth/composer.json index 7073f8b060cc..45cbc2f973bc 100644 --- a/src/Illuminate/Auth/composer.json +++ b/src/Illuminate/Auth/composer.json @@ -14,14 +14,14 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-hash": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/http": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/queue": "^12.0", - "illuminate/support": "^12.0" + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/http": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/queue": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -30,13 +30,13 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/console": "Required to use the auth:clear-resets command (^12.0).", - "illuminate/queue": "Required to fire login / logout events (^12.0).", - "illuminate/session": "Required to use the session based guard (^12.0)." + "illuminate/console": "Required to use the auth:clear-resets command (^13.0).", + "illuminate/queue": "Required to fire login / logout events (^13.0).", + "illuminate/session": "Required to use the session based guard (^13.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Broadcasting/BroadcastEvent.php b/src/Illuminate/Broadcasting/BroadcastEvent.php index c4da0faab220..7c03641ace53 100644 --- a/src/Illuminate/Broadcasting/BroadcastEvent.php +++ b/src/Illuminate/Broadcasting/BroadcastEvent.php @@ -50,6 +50,13 @@ class BroadcastEvent implements ShouldQueue */ public $maxExceptions; + /** + * Indicates if the job should be deleted when models are missing. + * + * @var bool + */ + public $deleteWhenMissingModels; + /** * Create a new job handler instance. * @@ -63,6 +70,7 @@ public function __construct($event) $this->backoff = property_exists($event, 'backoff') ? $event->backoff : null; $this->afterCommit = property_exists($event, 'afterCommit') ? $event->afterCommit : null; $this->maxExceptions = property_exists($event, 'maxExceptions') ? $event->maxExceptions : null; + $this->deleteWhenMissingModels = property_exists($event, 'deleteWhenMissingModels') ? $event->deleteWhenMissingModels : null; } /** diff --git a/src/Illuminate/Broadcasting/composer.json b/src/Illuminate/Broadcasting/composer.json index 103b02ac2733..03d45b78ea54 100644 --- a/src/Illuminate/Broadcasting/composer.json +++ b/src/Illuminate/Broadcasting/composer.json @@ -14,14 +14,14 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "psr/log": "^1.0|^2.0|^3.0", - "illuminate/bus": "^12.0", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/queue": "^12.0", - "illuminate/support": "^12.0" + "illuminate/bus": "^13.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/queue": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -30,7 +30,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { diff --git a/src/Illuminate/Bus/composer.json b/src/Illuminate/Bus/composer.json index dc3385da5120..57aea7551f3e 100644 --- a/src/Illuminate/Bus/composer.json +++ b/src/Illuminate/Bus/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/pipeline": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/pipeline": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -27,11 +27,11 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/queue": "Required to use closures when chaining jobs (^12.0)." + "illuminate/queue": "Required to use closures when chaining jobs (^13.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Cache/Console/ClearCommand.php b/src/Illuminate/Cache/Console/ClearCommand.php index e84cefae8d6c..965a39cf0248 100755 --- a/src/Illuminate/Cache/Console/ClearCommand.php +++ b/src/Illuminate/Cache/Console/ClearCommand.php @@ -57,7 +57,7 @@ public function __construct(CacheManager $cache, Filesystem $files) /** * Execute the console command. * - * @return void + * @return int|null */ public function handle() { @@ -70,7 +70,9 @@ public function handle() $this->flushFacades(); if (! $successful) { - return $this->components->error('Failed to clear cache. Make sure you have the appropriate permissions.'); + $this->components->error('Failed to clear cache. Make sure you have the appropriate permissions.'); + + return 1; } $this->laravel['events']->dispatch( diff --git a/src/Illuminate/Cache/composer.json b/src/Illuminate/Cache/composer.json index b1a44ef6d451..dea22e5a6d83 100755 --- a/src/Illuminate/Cache/composer.json +++ b/src/Illuminate/Cache/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0" }, "provide": { "psr/simple-cache-implementation": "1.0|2.0|3.0" @@ -30,16 +30,16 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "ext-apcu": "Required to use the APC cache driver.", "ext-filter": "Required to use the DynamoDb cache driver.", "ext-memcached": "Required to use the memcache cache driver.", - "illuminate/database": "Required to use the database cache driver (^12.0).", - "illuminate/filesystem": "Required to use the file cache driver (^12.0).", - "illuminate/redis": "Required to use the redis cache driver (^12.0).", + "illuminate/database": "Required to use the database cache driver (^13.0).", + "illuminate/filesystem": "Required to use the file cache driver (^13.0).", + "illuminate/redis": "Required to use the redis cache driver (^13.0).", "symfony/cache": "Required to use PSR-6 cache bridge (^7.2)." }, "config": { diff --git a/src/Illuminate/Collections/composer.json b/src/Illuminate/Collections/composer.json index 8d9c96125a47..b7cad15cc091 100644 --- a/src/Illuminate/Collections/composer.json +++ b/src/Illuminate/Collections/composer.json @@ -14,10 +14,10 @@ } ], "require": { - "php": "^8.2", - "illuminate/conditionable": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0" + "php": "^8.3", + "illuminate/conditionable": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0" }, "autoload": { "psr-4": { @@ -30,7 +30,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { diff --git a/src/Illuminate/Concurrency/composer.json b/src/Illuminate/Concurrency/composer.json index eb4e9467f66e..0a5d5c39bbe4 100644 --- a/src/Illuminate/Concurrency/composer.json +++ b/src/Illuminate/Concurrency/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", - "illuminate/console": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/process": "^12.0", - "illuminate/support": "^12.0", + "php": "^8.3", + "illuminate/console": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/process": "^13.0", + "illuminate/support": "^13.0", "laravel/serializable-closure": "^1.3|^2.0" }, "autoload": { @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "11.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Conditionable/composer.json b/src/Illuminate/Conditionable/composer.json index 9e0ddfbbdcf1..be75be9adf18 100644 --- a/src/Illuminate/Conditionable/composer.json +++ b/src/Illuminate/Conditionable/composer.json @@ -23,7 +23,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Config/composer.json b/src/Illuminate/Config/composer.json index 48db6c1db52a..484c4c58ea47 100755 --- a/src/Illuminate/Config/composer.json +++ b/src/Illuminate/Config/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0" + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0" }, "autoload": { "psr-4": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Console/composer.json b/src/Illuminate/Console/composer.json index 82fe11336e8a..d7ccfaa2ed0f 100755 --- a/src/Illuminate/Console/composer.json +++ b/src/Illuminate/Console/composer.json @@ -14,17 +14,16 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-mbstring": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", - "illuminate/view": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", + "illuminate/view": "^13.0", "laravel/prompts": "^0.3.0", "nunomaduro/termwind": "^2.0", "symfony/console": "^7.2.0", - "symfony/polyfill-php83": "^1.31", "symfony/process": "^7.2.0" }, "autoload": { @@ -34,17 +33,17 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "ext-pcntl": "Required to use signal trapping.", "dragonmantank/cron-expression": "Required to use scheduler (^3.3.2).", "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^7.8).", - "illuminate/bus": "Required to use the scheduled job dispatcher (^12.0).", - "illuminate/container": "Required to use the scheduler (^12.0).", - "illuminate/filesystem": "Required to use the generator command (^12.0).", - "illuminate/queue": "Required to use closures for scheduled jobs (^12.0)." + "illuminate/bus": "Required to use the scheduled job dispatcher (^13.0).", + "illuminate/container": "Required to use the scheduler (^13.0).", + "illuminate/filesystem": "Required to use the generator command (^13.0).", + "illuminate/queue": "Required to use closures for scheduled jobs (^13.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Container/composer.json b/src/Illuminate/Container/composer.json index 16d737f2a216..85b4860bf832 100755 --- a/src/Illuminate/Container/composer.json +++ b/src/Illuminate/Container/composer.json @@ -14,8 +14,8 @@ } ], "require": { - "php": "^8.2", - "illuminate/contracts": "^12.0", + "php": "^8.3", + "illuminate/contracts": "^13.0", "psr/container": "^1.1.1|^2.0.1" }, "provide": { @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Contracts/composer.json b/src/Illuminate/Contracts/composer.json index 01e8f8495602..dea7426f157e 100644 --- a/src/Illuminate/Contracts/composer.json +++ b/src/Illuminate/Contracts/composer.json @@ -14,7 +14,7 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "psr/container": "^1.1.1|^2.0.1", "psr/simple-cache": "^1.0|^2.0|^3.0" }, @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Cookie/composer.json b/src/Illuminate/Cookie/composer.json index 7184c3d2e351..75ad9b0bef1c 100755 --- a/src/Illuminate/Cookie/composer.json +++ b/src/Illuminate/Cookie/composer.json @@ -14,12 +14,12 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-hash": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", "symfony/http-foundation": "^7.2.0", "symfony/http-kernel": "^7.2.0" }, @@ -30,7 +30,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Database/Connection.php b/src/Illuminate/Database/Connection.php index a883e3edb22e..f0474f0fd7de 100755 --- a/src/Illuminate/Database/Connection.php +++ b/src/Illuminate/Database/Connection.php @@ -388,11 +388,12 @@ public function selectFromWriteConnection($query, $bindings = []) * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return array */ - public function select($query, $bindings = [], $useReadPdo = true) + public function select($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []) { - return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) { + return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo, $fetchUsing) { if ($this->pretending()) { return []; } @@ -408,7 +409,7 @@ public function select($query, $bindings = [], $useReadPdo = true) $statement->execute(); - return $statement->fetchAll(); + return $statement->fetchAll(...$fetchUsing); }); } @@ -418,11 +419,12 @@ public function select($query, $bindings = [], $useReadPdo = true) * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return array */ - public function selectResultSets($query, $bindings = [], $useReadPdo = true) + public function selectResultSets($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []) { - return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) { + return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo, $fetchUsing) { if ($this->pretending()) { return []; } @@ -438,7 +440,7 @@ public function selectResultSets($query, $bindings = [], $useReadPdo = true) $sets = []; do { - $sets[] = $statement->fetchAll(); + $sets[] = $statement->fetchAll(...$fetchUsing); } while ($statement->nextRowset()); return $sets; @@ -451,9 +453,10 @@ public function selectResultSets($query, $bindings = [], $useReadPdo = true) * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return \Generator */ - public function cursor($query, $bindings = [], $useReadPdo = true) + public function cursor($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []) { $statement = $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) { if ($this->pretending()) { @@ -478,7 +481,7 @@ public function cursor($query, $bindings = [], $useReadPdo = true) return $statement; }); - while ($record = $statement->fetch()) { + while ($record = $statement->fetch(...$fetchUsing)) { yield $record; } } diff --git a/src/Illuminate/Database/ConnectionInterface.php b/src/Illuminate/Database/ConnectionInterface.php index 288adb4206e3..22f866b43763 100755 --- a/src/Illuminate/Database/ConnectionInterface.php +++ b/src/Illuminate/Database/ConnectionInterface.php @@ -51,9 +51,10 @@ public function scalar($query, $bindings = [], $useReadPdo = true); * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return array */ - public function select($query, $bindings = [], $useReadPdo = true); + public function select($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []); /** * Run a select statement against the database and returns a generator. @@ -61,9 +62,10 @@ public function select($query, $bindings = [], $useReadPdo = true); * @param string $query * @param array $bindings * @param bool $useReadPdo + * @param array $fetchUsing * @return \Generator */ - public function cursor($query, $bindings = [], $useReadPdo = true); + public function cursor($query, $bindings = [], $useReadPdo = true, array $fetchUsing = []); /** * Run an insert statement against the database. diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index 4e22b9ae9fa2..e97591c4ccc6 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -325,6 +325,9 @@ public function where($column, $operator = null, $value = null, $boolean = 'and' $this->eagerLoad = array_merge($this->eagerLoad, $query->getEagerLoads()); + $this->withoutGlobalScopes( + $query->removedScopes() + ); $this->query->addNestedWhereQuery($query->getQuery(), $boolean); } else { $this->query->where(...func_get_args()); diff --git a/src/Illuminate/Database/Eloquent/Model.php b/src/Illuminate/Database/Eloquent/Model.php index 72d7e3315e36..990b5b526108 100644 --- a/src/Illuminate/Database/Eloquent/Model.php +++ b/src/Illuminate/Database/Eloquent/Model.php @@ -4,6 +4,7 @@ use ArrayAccess; use Closure; +use Exception; use Illuminate\Contracts\Broadcasting\HasBroadcastChannel; use Illuminate\Contracts\Queue\QueueableCollection; use Illuminate\Contracts\Queue\QueueableEntity; @@ -143,6 +144,13 @@ abstract class Model implements Arrayable, ArrayAccess, CanBeEscapedWhenCastToSt */ protected static $dispatcher; + /** + * The models that are currently being booted. + * + * @var array + */ + protected static $booting = []; + /** * The array of booted models. * @@ -286,12 +294,20 @@ public function __construct(array $attributes = []) protected function bootIfNotBooted() { if (! isset(static::$booted[static::class])) { - static::$booted[static::class] = true; + if (isset(static::$booting[static::class])) { + throw new LogicException('The ['.__METHOD__.'] method may not be called on model ['.static::class.'] while it is being booted.'); + } + + static::$booting[static::class] = true; $this->fireModelEvent('booting', false); static::booting(); static::boot(); + + static::$booted[static::class] = true; + unset(static::$booting[static::class]); + static::booted(); static::$bootedCallbacks[static::class] ??= []; diff --git a/src/Illuminate/Database/Query/Builder.php b/src/Illuminate/Database/Query/Builder.php index d2b97d5d121e..16afbd436295 100755 --- a/src/Illuminate/Database/Query/Builder.php +++ b/src/Illuminate/Database/Query/Builder.php @@ -262,6 +262,13 @@ class Builder implements BuilderContract */ public $useWritePdo = false; + /** + * The custom arguments for the PDOStatement::fetchAll / fetch functions. + * + * @var array + */ + public array $fetchUsing = []; + /** * Create a new query builder instance. */ @@ -3101,9 +3108,13 @@ public function soleValue($column) */ public function get($columns = ['*']) { - $items = new Collection($this->onceWithColumns(Arr::wrap($columns), function () { - return $this->processor->processSelect($this, $this->runSelect()); - })); + $original = $this->columns; + + $this->columns ??= Arr::wrap($columns); + + $items = new Collection($this->processor->processSelect($this, $this->runSelect())); + + $this->columns = $original; return $this->applyAfterQueryCallbacks( isset($this->groupLimit) ? $this->withoutGroupLimitKeys($items) : $items @@ -3118,7 +3129,7 @@ public function get($columns = ['*']) protected function runSelect() { return $this->connection->select( - $this->toSql(), $this->getBindings(), ! $this->useWritePdo + $this->toSql(), $this->getBindings(), ! $this->useWritePdo, $this->fetchUsing ); } @@ -3338,7 +3349,7 @@ public function cursor() return (new LazyCollection(function () { yield from $this->connection->cursor( - $this->toSql(), $this->getBindings(), ! $this->useWritePdo + $this->toSql(), $this->getBindings(), ! $this->useWritePdo, $this->fetchUsing ); }))->map(function ($item) { return $this->applyAfterQueryCallbacks(new Collection([$item]))->first(); @@ -3368,17 +3379,18 @@ protected function enforceOrderBy() */ public function pluck($column, $key = null) { + $original = $this->columns; + // First, we will need to select the results of the query accounting for the // given columns / key. Once we have the results, we will be able to take // the results and get the exact data that was requested for the query. - $queryResult = $this->onceWithColumns( - is_null($key) || $key === $column ? [$column] : [$column, $key], - function () { - return $this->processor->processSelect( - $this, $this->runSelect() - ); - } - ); + $this->columns ??= is_null($key) || $key === $column + ? [$column] + : [$column, $key]; + + $queryResult = $this->processor->processSelect($this, $this->runSelect()); + + $this->columns = $original; if (empty($queryResult)) { return new Collection; @@ -3673,32 +3685,6 @@ protected function setAggregate($function, $columns) return $this; } - /** - * Execute the given callback while selecting the given columns. - * - * After running the callback, the columns are reset to the original value. - * - * @template TResult - * - * @param array $columns - * @param callable(): TResult $callback - * @return TResult - */ - protected function onceWithColumns($columns, $callback) - { - $original = $this->columns; - - if (is_null($original)) { - $this->columns = $columns; - } - - $result = $callback(); - - $this->columns = $original; - - return $result; - } - /** * Insert new records into the database. * @@ -4325,6 +4311,19 @@ public function useWritePdo() return $this; } + /** + * Specify arguments for the PDOStatement::fetchAll / fetch functions. + * + * @param mixed ...$fetchUsing + * @return $this + */ + public function fetchUsing(...$fetchUsing) + { + $this->fetchUsing = $fetchUsing; + + return $this; + } + /** * Determine if the value is a query builder instance or a Closure. * diff --git a/src/Illuminate/Database/composer.json b/src/Illuminate/Database/composer.json index 606c093f1ba9..f6d619aea731 100644 --- a/src/Illuminate/Database/composer.json +++ b/src/Illuminate/Database/composer.json @@ -15,14 +15,14 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-pdo": "*", "brick/math": "^0.11|^0.12", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", "laravel/serializable-closure": "^1.3|^2.0" }, "autoload": { @@ -32,17 +32,17 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "ext-filter": "Required to use the Postgres database driver.", "fakerphp/faker": "Required to use the eloquent factory builder (^1.24).", - "illuminate/console": "Required to use the database commands (^12.0).", - "illuminate/events": "Required to use the observers with Eloquent (^12.0).", - "illuminate/filesystem": "Required to use the migrations (^12.0).", - "illuminate/http": "Required to convert Eloquent models to API resources (^12.0).", - "illuminate/pagination": "Required to paginate the result set (^12.0).", + "illuminate/console": "Required to use the database commands (^13.0).", + "illuminate/events": "Required to use the observers with Eloquent (^13.0).", + "illuminate/filesystem": "Required to use the migrations (^13.0).", + "illuminate/http": "Required to convert Eloquent models to API resources (^13.0).", + "illuminate/pagination": "Required to paginate the result set (^13.0).", "symfony/finder": "Required to use Eloquent model factories (^7.2)." }, "config": { diff --git a/src/Illuminate/Encryption/composer.json b/src/Illuminate/Encryption/composer.json index 1c430e9c3e34..1539e86ff687 100644 --- a/src/Illuminate/Encryption/composer.json +++ b/src/Illuminate/Encryption/composer.json @@ -14,12 +14,12 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-hash": "*", "ext-mbstring": "*", "ext-openssl": "*", - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0" + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Events/CallQueuedListener.php b/src/Illuminate/Events/CallQueuedListener.php index e78a4c4e2c5f..13f33e338304 100644 --- a/src/Illuminate/Events/CallQueuedListener.php +++ b/src/Illuminate/Events/CallQueuedListener.php @@ -82,6 +82,13 @@ class CallQueuedListener implements ShouldQueue */ public $shouldBeEncrypted = false; + /** + * Indicates if the job should be deleted when models are missing. + * + * @var bool + */ + public $deleteWhenMissingModels; + /** * Create a new job instance. * diff --git a/src/Illuminate/Events/Dispatcher.php b/src/Illuminate/Events/Dispatcher.php index c49a49d30ad7..9771d47d5c0d 100755 --- a/src/Illuminate/Events/Dispatcher.php +++ b/src/Illuminate/Events/Dispatcher.php @@ -679,6 +679,7 @@ protected function propagateListenerOptions($listener, $job) $job->timeout = $listener->timeout ?? null; $job->failOnTimeout = $listener->failOnTimeout ?? false; $job->tries = $listener->tries ?? null; + $job->deleteWhenMissingModels = $listener->deleteWhenMissingModels ?? false; $job->through(array_merge( method_exists($listener, 'middleware') ? $listener->middleware(...$data) : [], diff --git a/src/Illuminate/Events/composer.json b/src/Illuminate/Events/composer.json index 801895fd899f..4f3f2b4c62e5 100755 --- a/src/Illuminate/Events/composer.json +++ b/src/Illuminate/Events/composer.json @@ -14,13 +14,13 @@ } ], "require": { - "php": "^8.2", - "illuminate/bus": "^12.0", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/bus": "^13.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -32,7 +32,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Filesystem/composer.json b/src/Illuminate/Filesystem/composer.json index f5fa95db75a5..2f0edda1a1ef 100644 --- a/src/Illuminate/Filesystem/composer.json +++ b/src/Illuminate/Filesystem/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", "symfony/finder": "^7.2.0" }, "autoload": { @@ -31,14 +31,14 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-hash": "Required to use the Filesystem class.", - "illuminate/http": "Required for handling uploaded files (^12.0).", + "illuminate/http": "Required for handling uploaded files (^13.0).", "league/flysystem": "Required to use the Flysystem local driver (^3.25.1).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 243144794d59..5fd2090f74e2 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -45,7 +45,7 @@ class Application extends Container implements ApplicationContract, CachesConfig * * @var string */ - const VERSION = '12.14.1'; + const VERSION = '13.x-dev'; /** * The base path for the Laravel installation. diff --git a/src/Illuminate/Hashing/composer.json b/src/Illuminate/Hashing/composer.json index 623485f95dfc..18eec76368bd 100755 --- a/src/Illuminate/Hashing/composer.json +++ b/src/Illuminate/Hashing/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^8.2", - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Http/Client/Response.php b/src/Illuminate/Http/Client/Response.php index e69647bfb2bc..02f768ac05b8 100644 --- a/src/Illuminate/Http/Client/Response.php +++ b/src/Illuminate/Http/Client/Response.php @@ -304,14 +304,13 @@ public function toException() /** * Throw an exception if a server or client error occurred. * + * @param null|(\Closure(\Illuminate\Http\Client\Response, \Illuminate\Http\Client\RequestException): mixed) $callback * @return $this * * @throws \Illuminate\Http\Client\RequestException */ - public function throw() + public function throw($callback = null) { - $callback = func_get_args()[0] ?? null; - if ($this->failed()) { throw tap($this->toException(), function ($exception) use ($callback) { if ($callback && is_callable($callback)) { @@ -327,13 +326,14 @@ public function throw() * Throw an exception if a server or client error occurred and the given condition evaluates to true. * * @param \Closure|bool $condition + * @param null|(\Closure(\Illuminate\Http\Client\Response, \Illuminate\Http\Client\RequestException): mixed) $callback * @return $this * * @throws \Illuminate\Http\Client\RequestException */ - public function throwIf($condition) + public function throwIf($condition, $callback = null) { - return value($condition, $this) ? $this->throw(func_get_args()[1] ?? null) : $this; + return value($condition, $this) ? $this->throw($callback) : $this; } /** diff --git a/src/Illuminate/Http/composer.json b/src/Illuminate/Http/composer.json index 0ab2371d7c50..0aaf1f34e773 100755 --- a/src/Illuminate/Http/composer.json +++ b/src/Illuminate/Http/composer.json @@ -14,18 +14,17 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-filter": "*", "fruitcake/php-cors": "^1.3", "guzzlehttp/guzzle": "^7.8.2", "guzzlehttp/uri-template": "^1.0", - "illuminate/collections": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/session": "^12.0", - "illuminate/support": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/session": "^13.0", + "illuminate/support": "^13.0", "symfony/http-foundation": "^7.2.0", "symfony/http-kernel": "^7.2.0", - "symfony/polyfill-php83": "^1.31", "symfony/mime": "^7.2.0" }, "autoload": { @@ -38,7 +37,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Log/composer.json b/src/Illuminate/Log/composer.json index 201883d80002..7dfa1dcd0d1d 100755 --- a/src/Illuminate/Log/composer.json +++ b/src/Illuminate/Log/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^8.2", - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0", + "php": "^8.3", + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0", "monolog/monolog": "^3.0", "psr/log": "^1.0|^2.0|^3.0" }, @@ -30,7 +30,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Macroable/composer.json b/src/Illuminate/Macroable/composer.json index 38dc6f161a42..6c2d4901c89a 100644 --- a/src/Illuminate/Macroable/composer.json +++ b/src/Illuminate/Macroable/composer.json @@ -23,7 +23,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Mail/composer.json b/src/Illuminate/Mail/composer.json index 6f976a9e45dc..f834704a3600 100755 --- a/src/Illuminate/Mail/composer.json +++ b/src/Illuminate/Mail/composer.json @@ -14,12 +14,12 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", "league/commonmark": "^2.7", "psr/log": "^1.0|^2.0|^3.0", "symfony/mailer": "^7.2.0", @@ -32,7 +32,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { diff --git a/src/Illuminate/Notifications/composer.json b/src/Illuminate/Notifications/composer.json index 4041897464c5..eee1f69ccfa8 100644 --- a/src/Illuminate/Notifications/composer.json +++ b/src/Illuminate/Notifications/composer.json @@ -14,16 +14,16 @@ } ], "require": { - "php": "^8.2", - "illuminate/broadcasting": "^12.0", - "illuminate/bus": "^12.0", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/filesystem": "^12.0", - "illuminate/mail": "^12.0", - "illuminate/queue": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/broadcasting": "^13.0", + "illuminate/bus": "^13.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/filesystem": "^13.0", + "illuminate/mail": "^13.0", + "illuminate/queue": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -32,11 +32,11 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/database": "Required to use the database transport (^12.0)." + "illuminate/database": "Required to use the database transport (^13.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Pagination/composer.json b/src/Illuminate/Pagination/composer.json index b848b4a3b08d..dcb94402aaf9 100755 --- a/src/Illuminate/Pagination/composer.json +++ b/src/Illuminate/Pagination/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-filter": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0" + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Pipeline/composer.json b/src/Illuminate/Pipeline/composer.json index fbc26da597d0..24f627d4db14 100644 --- a/src/Illuminate/Pipeline/composer.json +++ b/src/Illuminate/Pipeline/composer.json @@ -14,9 +14,9 @@ } ], "require": { - "php": "^8.2", - "illuminate/contracts": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/contracts": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Process/composer.json b/src/Illuminate/Process/composer.json index 63c4afad444f..55bf46f2203d 100644 --- a/src/Illuminate/Process/composer.json +++ b/src/Illuminate/Process/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", "symfony/process": "^7.2.0" }, "autoload": { @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Queue/composer.json b/src/Illuminate/Queue/composer.json index 197737e2d1b3..12c8a2a0a771 100644 --- a/src/Illuminate/Queue/composer.json +++ b/src/Illuminate/Queue/composer.json @@ -14,15 +14,15 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/console": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/database": "^12.0", - "illuminate/filesystem": "^12.0", - "illuminate/pipeline": "^12.0", - "illuminate/support": "^12.0", + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/console": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/database": "^13.0", + "illuminate/filesystem": "^13.0", + "illuminate/pipeline": "^13.0", + "illuminate/support": "^13.0", "laravel/serializable-closure": "^1.3|^2.0", "ramsey/uuid": "^4.7", "symfony/process": "^7.2.0" @@ -34,7 +34,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { @@ -44,7 +44,7 @@ "ext-pcntl": "Required to use all features of the queue worker.", "ext-posix": "Required to use all features of the queue worker.", "aws/aws-sdk-php": "Required to use the SQS queue driver and DynamoDb failed job storage (^3.322.9).", - "illuminate/redis": "Required to use the Redis queue driver (^12.0).", + "illuminate/redis": "Required to use the Redis queue driver (^13.0).", "pda/pheanstalk": "Required to use the Beanstalk queue driver (^5.0.6|^7.0.0)." }, "config": { diff --git a/src/Illuminate/Redis/composer.json b/src/Illuminate/Redis/composer.json index 05535a2460b2..ea981b952d4a 100755 --- a/src/Illuminate/Redis/composer.json +++ b/src/Illuminate/Redis/composer.json @@ -14,11 +14,11 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -31,7 +31,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Routing/composer.json b/src/Illuminate/Routing/composer.json index 1f7e2281463f..3a54fba26192 100644 --- a/src/Illuminate/Routing/composer.json +++ b/src/Illuminate/Routing/composer.json @@ -14,17 +14,17 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-filter": "*", "ext-hash": "*", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/http": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/pipeline": "^12.0", - "illuminate/session": "^12.0", - "illuminate/support": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/http": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/pipeline": "^13.0", + "illuminate/session": "^13.0", + "illuminate/support": "^13.0", "symfony/http-foundation": "^7.2.0", "symfony/http-kernel": "^7.2.0", "symfony/routing": "^7.2.0" @@ -36,11 +36,11 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/console": "Required to use the make commands (^12.0).", + "illuminate/console": "Required to use the make commands (^13.0).", "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)." }, diff --git a/src/Illuminate/Session/composer.json b/src/Illuminate/Session/composer.json index c19e6cbe5081..3b0cbfed6897 100755 --- a/src/Illuminate/Session/composer.json +++ b/src/Illuminate/Session/composer.json @@ -14,13 +14,13 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-ctype": "*", "ext-session": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/filesystem": "^12.0", - "illuminate/support": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/filesystem": "^13.0", + "illuminate/support": "^13.0", "symfony/finder": "^7.2.0", "symfony/http-foundation": "^7.2.0" }, @@ -31,11 +31,11 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/console": "Required to use the session:table command (^12.0)." + "illuminate/console": "Required to use the session:table command (^13.0)." }, "config": { "sort-packages": true diff --git a/src/Illuminate/Support/Facades/DB.php b/src/Illuminate/Support/Facades/DB.php index f1c41bc0abb4..90990046ed69 100644 --- a/src/Illuminate/Support/Facades/DB.php +++ b/src/Illuminate/Support/Facades/DB.php @@ -40,9 +40,9 @@ * @method static mixed selectOne(string $query, array $bindings = [], bool $useReadPdo = true) * @method static mixed scalar(string $query, array $bindings = [], bool $useReadPdo = true) * @method static array selectFromWriteConnection(string $query, array $bindings = []) - * @method static array select(string $query, array $bindings = [], bool $useReadPdo = true) - * @method static array selectResultSets(string $query, array $bindings = [], bool $useReadPdo = true) - * @method static \Generator cursor(string $query, array $bindings = [], bool $useReadPdo = true) + * @method static array select(string $query, array $bindings = [], bool $useReadPdo = true, array $fetchUsing = []) + * @method static array selectResultSets(string $query, array $bindings = [], bool $useReadPdo = true, array $fetchUsing = []) + * @method static \Generator cursor(string $query, array $bindings = [], bool $useReadPdo = true, array $fetchUsing = []) * @method static bool insert(string $query, array $bindings = []) * @method static int update(string $query, array $bindings = []) * @method static int delete(string $query, array $bindings = []) diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index e2909a8d50f9..9a18bedf0822 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -4,7 +4,6 @@ use Closure; use Illuminate\Support\Traits\Macroable; -use JsonException; use League\CommonMark\Environment\Environment; use League\CommonMark\Extension\GithubFlavoredMarkdownExtension; use League\CommonMark\Extension\InlinesOnly\InlinesOnlyExtension; @@ -553,17 +552,7 @@ public static function isJson($value) return false; } - if (function_exists('json_validate')) { - return json_validate($value, 512); - } - - try { - json_decode($value, true, 512, JSON_THROW_ON_ERROR); - } catch (JsonException) { - return false; - } - - return true; + return json_validate($value); } /** @@ -913,17 +902,7 @@ public static function numbers($value) */ public static function padBoth($value, $length, $pad = ' ') { - if (function_exists('mb_str_pad')) { - return mb_str_pad($value, $length, $pad, STR_PAD_BOTH); - } - - $short = max(0, $length - mb_strlen($value)); - $shortLeft = floor($short / 2); - $shortRight = ceil($short / 2); - - return mb_substr(str_repeat($pad, $shortLeft), 0, $shortLeft). - $value. - mb_substr(str_repeat($pad, $shortRight), 0, $shortRight); + return mb_str_pad($value, $length, $pad, STR_PAD_BOTH); } /** @@ -936,13 +915,7 @@ public static function padBoth($value, $length, $pad = ' ') */ public static function padLeft($value, $length, $pad = ' ') { - if (function_exists('mb_str_pad')) { - return mb_str_pad($value, $length, $pad, STR_PAD_LEFT); - } - - $short = max(0, $length - mb_strlen($value)); - - return mb_substr(str_repeat($pad, $short), 0, $short).$value; + return mb_str_pad($value, $length, $pad, STR_PAD_LEFT); } /** @@ -955,13 +928,7 @@ public static function padLeft($value, $length, $pad = ' ') */ public static function padRight($value, $length, $pad = ' ') { - if (function_exists('mb_str_pad')) { - return mb_str_pad($value, $length, $pad, STR_PAD_RIGHT); - } - - $short = max(0, $length - mb_strlen($value)); - - return $value.mb_substr(str_repeat($pad, $short), 0, $short); + return mb_str_pad($value, $length, $pad, STR_PAD_RIGHT); } /** diff --git a/src/Illuminate/Support/Testing/Fakes/BatchFake.php b/src/Illuminate/Support/Testing/Fakes/BatchFake.php index 0d1176c2b3ec..8698e00e71fc 100644 --- a/src/Illuminate/Support/Testing/Fakes/BatchFake.php +++ b/src/Illuminate/Support/Testing/Fakes/BatchFake.php @@ -67,6 +67,7 @@ public function __construct( * * @return self */ + #[\Override] public function fresh() { return $this; @@ -78,6 +79,7 @@ public function fresh() * @param \Illuminate\Support\Enumerable|object|array $jobs * @return self */ + #[\Override] public function add($jobs) { $jobs = Collection::wrap($jobs); @@ -97,6 +99,7 @@ public function add($jobs) * @param string $jobId * @return void */ + #[\Override] public function recordSuccessfulJob(string $jobId) { // @@ -108,6 +111,7 @@ public function recordSuccessfulJob(string $jobId) * @param string $jobId * @return void */ + #[\Override] public function decrementPendingJobs(string $jobId) { // @@ -120,6 +124,7 @@ public function decrementPendingJobs(string $jobId) * @param \Throwable $e * @return void */ + #[\Override] public function recordFailedJob(string $jobId, $e) { // @@ -131,6 +136,7 @@ public function recordFailedJob(string $jobId, $e) * @param string $jobId * @return \Illuminate\Bus\UpdatedBatchJobCounts */ + #[\Override] public function incrementFailedJobs(string $jobId) { return new UpdatedBatchJobCounts; @@ -141,6 +147,7 @@ public function incrementFailedJobs(string $jobId) * * @return void */ + #[\Override] public function cancel() { $this->cancelledAt = Carbon::now(); @@ -151,6 +158,7 @@ public function cancel() * * @return void */ + #[\Override] public function delete() { $this->deleted = true; diff --git a/src/Illuminate/Support/composer.json b/src/Illuminate/Support/composer.json index 404eff091464..9032e8eda274 100644 --- a/src/Illuminate/Support/composer.json +++ b/src/Illuminate/Support/composer.json @@ -14,15 +14,15 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-ctype": "*", "ext-filter": "*", "ext-mbstring": "*", "doctrine/inflector": "^2.0", - "illuminate/collections": "^12.0", - "illuminate/conditionable": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/conditionable": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", "nesbot/carbon": "^3.8.4", "voku/portable-ascii": "^2.0.2" }, @@ -43,11 +43,11 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/filesystem": "Required to use the Composer class (^12.0).", + "illuminate/filesystem": "Required to use the Composer class (^13.0).", "laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).", "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.7).", "league/uri": "Required to use the Uri class (^7.5.1).", diff --git a/src/Illuminate/Testing/composer.json b/src/Illuminate/Testing/composer.json index 0f4286aba64c..3f0fac602180 100644 --- a/src/Illuminate/Testing/composer.json +++ b/src/Illuminate/Testing/composer.json @@ -14,12 +14,12 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-mbstring": "*", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0" + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -28,14 +28,14 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", - "illuminate/console": "Required to assert console commands (^12.0).", - "illuminate/database": "Required to assert databases (^12.0).", - "illuminate/http": "Required to assert responses (^12.0).", + "illuminate/console": "Required to assert console commands (^13.0).", + "illuminate/database": "Required to assert databases (^13.0).", + "illuminate/http": "Required to assert responses (^13.0).", "mockery/mockery": "Required to use mocking (^1.6).", "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1)." }, diff --git a/src/Illuminate/Translation/composer.json b/src/Illuminate/Translation/composer.json index 1b0dfa7a5d4b..3dfb306e89e1 100755 --- a/src/Illuminate/Translation/composer.json +++ b/src/Illuminate/Translation/composer.json @@ -14,12 +14,12 @@ } ], "require": { - "php": "^8.2", - "illuminate/collections": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/filesystem": "^12.0", - "illuminate/support": "^12.0" + "php": "^8.3", + "illuminate/collections": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/filesystem": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index 21577ce4eb87..d71eb083d742 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -1527,13 +1527,7 @@ public function validateJson($attribute, $value) return false; } - if (function_exists('json_validate')) { - return json_validate($value); - } - - json_decode($value); - - return json_last_error() === JSON_ERROR_NONE; + return json_validate($value); } /** diff --git a/src/Illuminate/Validation/composer.json b/src/Illuminate/Validation/composer.json index 020433ac0016..d748bdfb510b 100755 --- a/src/Illuminate/Validation/composer.json +++ b/src/Illuminate/Validation/composer.json @@ -14,17 +14,17 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-filter": "*", "ext-mbstring": "*", "brick/math": "^0.11|^0.12", "egulias/email-validator": "^3.2.5|^4.0", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0", - "illuminate/translation": "^12.0", + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0", + "illuminate/translation": "^13.0", "symfony/http-foundation": "^7.2", "symfony/mime": "^7.2" }, @@ -35,11 +35,11 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "suggest": { - "illuminate/database": "Required to use the database presence verifier (^12.0).", + "illuminate/database": "Required to use the database presence verifier (^13.0).", "ramsey/uuid": "Required to use Validator::validateUuid() (^4.7)." }, "config": { diff --git a/src/Illuminate/View/composer.json b/src/Illuminate/View/composer.json index fd32f9538711..b6dab80ff9da 100644 --- a/src/Illuminate/View/composer.json +++ b/src/Illuminate/View/composer.json @@ -14,15 +14,15 @@ } ], "require": { - "php": "^8.2", + "php": "^8.3", "ext-tokenizer": "*", - "illuminate/collections": "^12.0", - "illuminate/container": "^12.0", - "illuminate/contracts": "^12.0", - "illuminate/events": "^12.0", - "illuminate/filesystem": "^12.0", - "illuminate/macroable": "^12.0", - "illuminate/support": "^12.0" + "illuminate/collections": "^13.0", + "illuminate/container": "^13.0", + "illuminate/contracts": "^13.0", + "illuminate/events": "^13.0", + "illuminate/filesystem": "^13.0", + "illuminate/macroable": "^13.0", + "illuminate/support": "^13.0" }, "autoload": { "psr-4": { @@ -31,7 +31,7 @@ }, "extra": { "branch-alias": { - "dev-master": "12.x-dev" + "dev-master": "13.0.x-dev" } }, "config": { diff --git a/tests/Database/DatabaseEloquentBelongsToManyCreateOrFirstTest.php b/tests/Database/DatabaseEloquentBelongsToManyCreateOrFirstTest.php index fc9597378357..254d925cd2c0 100644 --- a/tests/Database/DatabaseEloquentBelongsToManyCreateOrFirstTest.php +++ b/tests/Database/DatabaseEloquentBelongsToManyCreateOrFirstTest.php @@ -84,7 +84,7 @@ public function testCreateOrFirstMethodAssociatesExistingRelated(): void $source->getConnection() ->expects('select') - ->with('select * from "related_table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "related_table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([[ 'id' => 456, 'attr' => 'foo', @@ -128,6 +128,7 @@ public function testFirstOrCreateMethodRetrievesExistingRelatedAlreadyAssociated 'select "related_table".*, "pivot_table"."source_id" as "pivot_source_id", "pivot_table"."related_id" as "pivot_related_id" from "related_table" inner join "pivot_table" on "related_table"."id" = "pivot_table"."related_id" where "pivot_table"."source_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([[ 'id' => 456, @@ -176,7 +177,7 @@ public function testCreateOrFirstMethodRetrievesExistingRelatedAssociatedJustNow $source->getConnection() ->expects('select') - ->with('select * from "related_table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "related_table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([[ 'id' => 456, 'attr' => 'foo', @@ -199,6 +200,7 @@ public function testCreateOrFirstMethodRetrievesExistingRelatedAssociatedJustNow 'select "related_table".*, "pivot_table"."source_id" as "pivot_source_id", "pivot_table"."related_id" as "pivot_related_id" from "related_table" inner join "pivot_table" on "related_table"."id" = "pivot_table"."related_id" where "pivot_table"."source_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], false, + [], ) ->andReturn([[ 'id' => 456, @@ -243,6 +245,7 @@ public function testFirstOrCreateMethodRetrievesExistingRelatedAndAssociatesIt() 'select "related_table".*, "pivot_table"."source_id" as "pivot_source_id", "pivot_table"."related_id" as "pivot_related_id" from "related_table" inner join "pivot_table" on "related_table"."id" = "pivot_table"."related_id" where "pivot_table"."source_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([]); @@ -252,6 +255,7 @@ public function testFirstOrCreateMethodRetrievesExistingRelatedAndAssociatesIt() 'select * from "related_table" where ("attr" = ?) limit 1', ['foo'], true, + [], ) ->andReturn([[ 'id' => 456, @@ -326,6 +330,7 @@ protected function newBelongsToMany(Builder $query, Model $parent, $table, $fore 'select "related_table".*, "pivot_table"."source_id" as "pivot_source_id", "pivot_table"."related_id" as "pivot_related_id" from "related_table" inner join "pivot_table" on "related_table"."id" = "pivot_table"."related_id" where "pivot_table"."source_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([]); @@ -335,6 +340,7 @@ protected function newBelongsToMany(Builder $query, Model $parent, $table, $fore 'select * from "related_table" where ("attr" = ?) limit 1', ['foo'], true, + [], ) ->andReturn([]); diff --git a/tests/Database/DatabaseEloquentBuilderCreateOrFirstTest.php b/tests/Database/DatabaseEloquentBuilderCreateOrFirstTest.php index 87fc0c43e24f..e957362691f7 100755 --- a/tests/Database/DatabaseEloquentBuilderCreateOrFirstTest.php +++ b/tests/Database/DatabaseEloquentBuilderCreateOrFirstTest.php @@ -66,7 +66,7 @@ public function testCreateOrFirstMethodRetrievesExistingRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], false) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], false, []) ->andReturn([[ 'id' => 123, 'attr' => 'foo', @@ -95,7 +95,7 @@ public function testFirstOrCreateMethodRetrievesExistingRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([[ 'id' => 123, 'attr' => 'foo', @@ -124,7 +124,7 @@ public function testFirstOrCreateMethodCreatesNewRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([]); $model->getConnection()->expects('insert')->with( @@ -152,7 +152,7 @@ public function testFirstOrCreateMethodRetrievesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([]); $sql = 'insert into "table" ("attr", "val", "updated_at", "created_at") values (?, ?, ?, ?)'; @@ -165,7 +165,7 @@ public function testFirstOrCreateMethodRetrievesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], false) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], false, []) ->andReturn([[ 'id' => 123, 'attr' => 'foo', @@ -194,7 +194,7 @@ public function testUpdateOrCreateMethodUpdatesExistingRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([[ 'id' => 123, 'attr' => 'foo', @@ -231,7 +231,7 @@ public function testUpdateOrCreateMethodCreatesNewRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([]); $model->getConnection()->expects('insert')->with( @@ -259,7 +259,7 @@ public function testUpdateOrCreateMethodUpdatesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([]); $sql = 'insert into "table" ("attr", "val", "updated_at", "created_at") values (?, ?, ?, ?)'; @@ -272,7 +272,7 @@ public function testUpdateOrCreateMethodUpdatesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], false) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], false, []) ->andReturn([[ 'id' => 123, 'attr' => 'foo', @@ -309,7 +309,7 @@ public function testIncrementOrCreateMethodIncrementsExistingRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([[ 'id' => 123, 'attr' => 'foo', @@ -351,7 +351,7 @@ public function testIncrementOrCreateMethodCreatesNewRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([]); $model->getConnection()->expects('insert')->with( @@ -379,7 +379,7 @@ public function testIncrementOrCreateMethodIncrementParametersArePassed(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([[ 'id' => 123, 'attr' => 'foo', @@ -423,7 +423,7 @@ public function testIncrementOrCreateMethodRetrievesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], true, []) ->andReturn([]); $sql = 'insert into "table" ("attr", "count", "updated_at", "created_at") values (?, ?, ?, ?)'; @@ -436,7 +436,7 @@ public function testIncrementOrCreateMethodRetrievesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], false) + ->with('select * from "table" where ("attr" = ?) limit 1', ['foo'], false, []) ->andReturn([[ 'id' => 123, 'attr' => 'foo', diff --git a/tests/Database/DatabaseEloquentBuilderTest.php b/tests/Database/DatabaseEloquentBuilderTest.php index 09146044a349..c72159bba519 100755 --- a/tests/Database/DatabaseEloquentBuilderTest.php +++ b/tests/Database/DatabaseEloquentBuilderTest.php @@ -1056,6 +1056,7 @@ public function testNestedWhere() $nestedRawQuery = $this->getMockQueryBuilder(); $nestedQuery->shouldReceive('getQuery')->once()->andReturn($nestedRawQuery); $nestedQuery->shouldReceive('getEagerLoads')->once()->andReturn([]); + $nestedQuery->shouldReceive('removedScopes')->once()->andReturn([]); $model = $this->getMockModel()->makePartial(); $model->shouldReceive('newQueryWithoutRelationships')->once()->andReturn($nestedQuery); $builder = $this->getBuilder(); @@ -1118,6 +1119,7 @@ public function testWhereNot() $nestedRawQuery = $this->getMockQueryBuilder(); $nestedQuery->shouldReceive('getQuery')->once()->andReturn($nestedRawQuery); $nestedQuery->shouldReceive('getEagerLoads')->once()->andReturn([]); + $nestedQuery->shouldReceive('removedScopes')->once()->andReturn([]); $model = $this->getMockModel()->makePartial(); $model->shouldReceive('newQueryWithoutRelationships')->once()->andReturn($nestedQuery); $builder = $this->getBuilder(); @@ -1147,6 +1149,7 @@ public function testOrWhereNot() $nestedRawQuery = $this->getMockQueryBuilder(); $nestedQuery->shouldReceive('getQuery')->once()->andReturn($nestedRawQuery); $nestedQuery->shouldReceive('getEagerLoads')->once()->andReturn([]); + $nestedQuery->shouldReceive('removedScopes')->once()->andReturn([]); $model = $this->getMockModel()->makePartial(); $model->shouldReceive('newQueryWithoutRelationships')->once()->andReturn($nestedQuery); $builder = $this->getBuilder(); diff --git a/tests/Database/DatabaseEloquentGlobalScopesTest.php b/tests/Database/DatabaseEloquentGlobalScopesTest.php index 3b5a379d4fdb..8e6423797fdd 100644 --- a/tests/Database/DatabaseEloquentGlobalScopesTest.php +++ b/tests/Database/DatabaseEloquentGlobalScopesTest.php @@ -147,6 +147,38 @@ public function testHasQueryWhereBothModelsHaveGlobalScopes() $this->assertEquals($mainQuery, $query->toSql()); $this->assertEquals(['bar', 1, 'baz', 1], $query->getBindings()); } + + public function testRegularScopesThatRemoveGlobalScopes() + { + $query = EloquentClosureGlobalScopesTestModel::where('foo', 'foo')->approved()->notApproved(); + + $this->assertSame('select * from "table" where "foo" = ? and ("approved" = ? or "should_approve" = ?) and ("approved" = ? or "should_approve" = ?) order by "name" asc', $query->toSql()); + $this->assertEquals(['foo', 1, 0, 0, 1], $query->getBindings()); + } + + public function testRegularScopesThatRemoveGlobalScopesCalledInNestedWhereCondition() + { + $query = EloquentClosureGlobalScopesTestModel::where('foo', 'foo')->where(function ($query) { + $query->approved(); + $query->orWhere(function ($query) { + $query->notApproved(); + }); + }); + + $this->assertSame('select * from "table" where "foo" = ? and (("approved" = ? or "should_approve" = ?) or (("approved" = ? or "should_approve" = ?))) order by "name" asc', $query->toSql()); + $this->assertEquals(['foo', 1, 0, 0, 1], $query->getBindings()); + } + + public function testRemovingGlobalScopeInNestedWhereCondition() + { + $query = EloquentClosureGlobalScopesTestModel::where('foo', 'foo')->where(function ($query) { + $query->approved(); + $query->withoutGlobalScope('active_scope'); + }); + + $this->assertSame('select * from "table" where "foo" = ? and (("approved" = ? or "should_approve" = ?)) order by "name" asc', $query->toSql()); + $this->assertEquals(['foo', 1, 0], $query->getBindings()); + } } class EloquentClosureGlobalScopesTestModel extends Model @@ -171,6 +203,11 @@ public function scopeApproved($query) return $query->where('approved', 1)->orWhere('should_approve', 0); } + public function scopeNotApproved($query) + { + return $query->where('approved', 0)->orWhere('should_approve', 1)->withoutGlobalScope('active_scope'); + } + public function scopeOrApproved($query) { return $query->orWhere('approved', 1)->orWhere('should_approve', 0); diff --git a/tests/Database/DatabaseEloquentHasManyCreateOrFirstTest.php b/tests/Database/DatabaseEloquentHasManyCreateOrFirstTest.php index b7a055a66958..855ac0665fa3 100755 --- a/tests/Database/DatabaseEloquentHasManyCreateOrFirstTest.php +++ b/tests/Database/DatabaseEloquentHasManyCreateOrFirstTest.php @@ -70,7 +70,7 @@ public function testCreateOrFirstMethodRetrievesExistingRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], false) + ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], false, []) ->andReturn([[ 'id' => 456, 'parent_id' => 123, @@ -102,7 +102,7 @@ public function testFirstOrCreateMethodCreatesNewRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true) + ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true, []) ->andReturn([]); $model->getConnection()->expects('insert')->with( @@ -132,7 +132,7 @@ public function testFirstOrCreateMethodRetrievesExistingRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true) + ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true, []) ->andReturn([[ 'id' => 456, 'parent_id' => 123, @@ -164,7 +164,7 @@ public function testFirstOrCreateMethodRetrievesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true) + ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true, []) ->andReturn([]); $sql = 'insert into "child_table" ("attr", "val", "parent_id", "updated_at", "created_at") values (?, ?, ?, ?, ?)'; @@ -177,7 +177,7 @@ public function testFirstOrCreateMethodRetrievesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], false) + ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], false, []) ->andReturn([[ 'id' => 456, 'parent_id' => 123, @@ -209,7 +209,7 @@ public function testUpdateOrCreateMethodCreatesNewRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true) + ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true, []) ->andReturn([]); $model->getConnection()->expects('insert')->with( @@ -239,7 +239,7 @@ public function testUpdateOrCreateMethodUpdatesExistingRecord(): void $model->getConnection() ->expects('select') - ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true) + ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true, []) ->andReturn([[ 'id' => 456, 'parent_id' => 123, @@ -276,7 +276,7 @@ public function testUpdateOrCreateMethodUpdatesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true) + ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], true, []) ->andReturn([]); $sql = 'insert into "child_table" ("attr", "val", "parent_id", "updated_at", "created_at") values (?, ?, ?, ?, ?)'; @@ -289,7 +289,7 @@ public function testUpdateOrCreateMethodUpdatesRecordCreatedJustNow(): void $model->getConnection() ->expects('select') - ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], false) + ->with('select * from "child_table" where "child_table"."parent_id" = ? and "child_table"."parent_id" is not null and ("attr" = ?) limit 1', [123, 'foo'], false, []) ->andReturn([[ 'id' => 456, 'parent_id' => 123, diff --git a/tests/Database/DatabaseEloquentHasManyThroughCreateOrFirstTest.php b/tests/Database/DatabaseEloquentHasManyThroughCreateOrFirstTest.php index 63c69a6175bb..9a5dc0e26daf 100644 --- a/tests/Database/DatabaseEloquentHasManyThroughCreateOrFirstTest.php +++ b/tests/Database/DatabaseEloquentHasManyThroughCreateOrFirstTest.php @@ -75,6 +75,7 @@ public function testCreateOrFirstMethodRetrievesExistingRecord(): void 'select "child".*, "pivot"."parent_id" as "laravel_through_key" from "child" inner join "pivot" on "pivot"."id" = "child"."pivot_id" where "pivot"."parent_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([[ 'id' => 789, @@ -114,6 +115,7 @@ public function testFirstOrCreateMethodCreatesNewRecord(): void 'select "child".*, "pivot"."parent_id" as "laravel_through_key" from "child" inner join "pivot" on "pivot"."id" = "child"."pivot_id" where "pivot"."parent_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([]); @@ -148,6 +150,7 @@ public function testFirstOrCreateMethodRetrievesExistingRecord(): void 'select "child".*, "pivot"."parent_id" as "laravel_through_key" from "child" inner join "pivot" on "pivot"."id" = "child"."pivot_id" where "pivot"."parent_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([[ 'id' => 789, @@ -187,6 +190,7 @@ public function testFirstOrCreateMethodRetrievesRecordCreatedJustNow(): void 'select "child".*, "pivot"."parent_id" as "laravel_through_key" from "child" inner join "pivot" on "pivot"."id" = "child"."pivot_id" where "pivot"."parent_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([]); @@ -204,6 +208,7 @@ public function testFirstOrCreateMethodRetrievesRecordCreatedJustNow(): void 'select "child".*, "pivot"."parent_id" as "laravel_through_key" from "child" inner join "pivot" on "pivot"."id" = "child"."pivot_id" where "pivot"."parent_id" = ? and ("attr" = ? and "val" = ?) limit 1', [123, 'foo', 'bar'], true, + [], ) ->andReturn([[ 'id' => 789, @@ -243,6 +248,7 @@ public function testUpdateOrCreateMethodCreatesNewRecord(): void 'select "child".*, "pivot"."parent_id" as "laravel_through_key" from "child" inner join "pivot" on "pivot"."id" = "child"."pivot_id" where "pivot"."parent_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([]); @@ -280,6 +286,7 @@ public function testUpdateOrCreateMethodUpdatesExistingRecord(): void 'select "child".*, "pivot"."parent_id" as "laravel_through_key" from "child" inner join "pivot" on "pivot"."id" = "child"."pivot_id" where "pivot"."parent_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([[ 'id' => 789, @@ -327,6 +334,7 @@ public function testUpdateOrCreateMethodUpdatesRecordCreatedJustNow(): void 'select "child".*, "pivot"."parent_id" as "laravel_through_key" from "child" inner join "pivot" on "pivot"."id" = "child"."pivot_id" where "pivot"."parent_id" = ? and ("attr" = ?) limit 1', [123, 'foo'], true, + [], ) ->andReturn([]); @@ -344,6 +352,7 @@ public function testUpdateOrCreateMethodUpdatesRecordCreatedJustNow(): void 'select "child".*, "pivot"."parent_id" as "laravel_through_key" from "child" inner join "pivot" on "pivot"."id" = "child"."pivot_id" where "pivot"."parent_id" = ? and ("attr" = ? and "val" = ?) limit 1', [123, 'foo', 'bar'], true, + [], ) ->andReturn([[ 'id' => 789, diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index d7f6f1538b72..54c2673b3b6f 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -3330,6 +3330,21 @@ public function testUseFactoryAttribute() $this->assertEquals(EloquentModelWithUseFactoryAttribute::class, $factory->modelName()); $this->assertEquals('test name', $instance->name); // Small smoke test to ensure the factory is working } + + public function testNestedModelBootingIsDisallowed() + { + $this->expectExceptionMessageMatches('/The \[(.+)] method may not be called on model \[(.+)\] while it is being booted\./'); + + $model = new class extends Model + { + protected static function boot() + { + parent::boot(); + + $tableName = (new static())->getTable(); + } + }; + } } class EloquentTestObserverStub diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 9c89ef66eac9..700d64a9502c 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -82,12 +82,12 @@ public function testBasicSelectUseWritePdo() { $builder = $this->getMySqlBuilderWithProcessor(); $builder->getConnection()->shouldReceive('select')->once() - ->with('select * from `users`', [], false); + ->with('select * from `users`', [], false, []); $builder->useWritePdo()->select('*')->from('users')->get(); $builder = $this->getMySqlBuilderWithProcessor(); $builder->getConnection()->shouldReceive('select')->once() - ->with('select * from `users`', [], true); + ->with('select * from `users`', [], true, []); $builder->select('*')->from('users')->get(); } @@ -1777,31 +1777,31 @@ public function testUnionAggregate() { $expected = 'select count(*) as aggregate from ((select * from `posts`) union (select * from `videos`)) as `temp_table`'; $builder = $this->getMySqlBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true); + $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true, []); $builder->getProcessor()->shouldReceive('processSelect')->once(); $builder->from('posts')->union($this->getMySqlBuilder()->from('videos'))->count(); $expected = 'select count(*) as aggregate from ((select `id` from `posts`) union (select `id` from `videos`)) as `temp_table`'; $builder = $this->getMySqlBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true); + $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true, []); $builder->getProcessor()->shouldReceive('processSelect')->once(); $builder->from('posts')->select('id')->union($this->getMySqlBuilder()->from('videos')->select('id'))->count(); $expected = 'select count(*) as aggregate from ((select * from "posts") union (select * from "videos")) as "temp_table"'; $builder = $this->getPostgresBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true); + $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true, []); $builder->getProcessor()->shouldReceive('processSelect')->once(); $builder->from('posts')->union($this->getPostgresBuilder()->from('videos'))->count(); $expected = 'select count(*) as aggregate from (select * from (select * from "posts") union select * from (select * from "videos")) as "temp_table"'; $builder = $this->getSQLiteBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true); + $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true, []); $builder->getProcessor()->shouldReceive('processSelect')->once(); $builder->from('posts')->union($this->getSQLiteBuilder()->from('videos'))->count(); $expected = 'select count(*) as aggregate from (select * from (select * from [posts]) as [temp_table] union select * from (select * from [videos]) as [temp_table]) as [temp_table]'; $builder = $this->getSqlServerBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true); + $builder->getConnection()->shouldReceive('select')->once()->with($expected, [], true, []); $builder->getProcessor()->shouldReceive('processSelect')->once(); $builder->from('posts')->union($this->getSqlServerBuilder()->from('videos'))->count(); } @@ -1811,7 +1811,7 @@ public function testHavingAggregate() $expected = 'select count(*) as aggregate from (select (select `count(*)` from `videos` where `posts`.`id` = `videos`.`post_id`) as `videos_count` from `posts` having `videos_count` > ?) as `temp_table`'; $builder = $this->getMySqlBuilder(); $builder->getConnection()->shouldReceive('getDatabaseName'); - $builder->getConnection()->shouldReceive('select')->once()->with($expected, [0 => 1], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with($expected, [0 => 1], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2293,7 +2293,7 @@ public function testHavingFollowedBySelectGet() { $builder = $this->getBuilder(); $query = 'select "category", count(*) as "total" from "item" where "department" = ? group by "category" having "total" > ?'; - $builder->getConnection()->shouldReceive('select')->once()->with($query, ['popular', 3], true)->andReturn([['category' => 'rock', 'total' => 5]]); + $builder->getConnection()->shouldReceive('select')->once()->with($query, ['popular', 3], true, [])->andReturn([['category' => 'rock', 'total' => 5]]); $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2304,7 +2304,7 @@ public function testHavingFollowedBySelectGet() // Using \Raw value $builder = $this->getBuilder(); $query = 'select "category", count(*) as "total" from "item" where "department" = ? group by "category" having "total" > 3'; - $builder->getConnection()->shouldReceive('select')->once()->with($query, ['popular'], true)->andReturn([['category' => 'rock', 'total' => 5]]); + $builder->getConnection()->shouldReceive('select')->once()->with($query, ['popular'], true, [])->andReturn([['category' => 'rock', 'total' => 5]]); $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2419,7 +2419,7 @@ public function testGetCountForPaginationWithBindings() $q->select('body')->from('posts')->where('id', 4); }, 'post'); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2435,7 +2435,7 @@ public function testGetCountForPaginationWithColumnAliases() $columns = ['body as post_body', 'teaser', 'posts.created as published']; $builder->from('posts')->select($columns); - $builder->getConnection()->shouldReceive('select')->once()->with('select count("body", "teaser", "posts"."created") as aggregate from "posts"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count("body", "teaser", "posts"."created") as aggregate from "posts"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2449,7 +2449,7 @@ public function testGetCountForPaginationWithUnion() $builder = $this->getBuilder(); $builder->from('posts')->select('id')->union($this->getBuilder()->from('videos')->select('id')); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from ((select "id" from "posts") union (select "id" from "videos")) as "temp_table"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from ((select "id" from "posts") union (select "id" from "videos")) as "temp_table"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2463,7 +2463,7 @@ public function testGetCountForPaginationWithUnionOrders() $builder = $this->getBuilder(); $builder->from('posts')->select('id')->union($this->getBuilder()->from('videos')->select('id'))->latest(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from ((select "id" from "posts") union (select "id" from "videos")) as "temp_table"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from ((select "id" from "posts") union (select "id" from "videos")) as "temp_table"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -2477,7 +2477,7 @@ public function testGetCountForPaginationWithUnionLimitAndOffset() $builder = $this->getBuilder(); $builder->from('posts')->select('id')->union($this->getBuilder()->from('videos')->select('id'))->take(15)->skip(1); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from ((select "id" from "posts") union (select "id" from "videos")) as "temp_table"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from ((select "id" from "posts") union (select "id" from "videos")) as "temp_table"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3428,7 +3428,7 @@ public function testRawExpressionsInSelect() public function testFindReturnsFirstResultByID() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true)->andReturn([['foo' => 'bar']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true, [])->andReturn([['foo' => 'bar']]); $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturnUsing(function ($query, $results) { return $results; }); @@ -3452,7 +3452,7 @@ public function testFindOrReturnsFirstResultByID() public function testFirstMethodReturnsFirstResult() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true)->andReturn([['foo' => 'bar']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true, [])->andReturn([['foo' => 'bar']]); $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturnUsing(function ($query, $results) { return $results; }); @@ -3463,7 +3463,7 @@ public function testFirstMethodReturnsFirstResult() public function testFirstOrFailMethodReturnsFirstResult() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true)->andReturn([['foo' => 'bar']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true, [])->andReturn([['foo' => 'bar']]); $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturnUsing(function ($query, $results) { return $results; }); @@ -3474,7 +3474,7 @@ public function testFirstOrFailMethodReturnsFirstResult() public function testFirstOrFailMethodThrowsRecordNotFoundException() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true)->andReturn([]); + $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true, [])->andReturn([]); $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [])->andReturn([]); @@ -3506,7 +3506,7 @@ public function testPluckMethodGetsCollectionOfColumnValues() public function testPluckAvoidsDuplicateColumnSelection() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select "foo" from "users" where "id" = ?', [1], true)->andReturn([['foo' => 'bar']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select "foo" from "users" where "id" = ?', [1], true, [])->andReturn([['foo' => 'bar']]); $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturnUsing(function ($query, $results) { return $results; }); @@ -3538,7 +3538,7 @@ public function testImplode() public function testValueMethodReturnsSingleColumn() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select "foo" from "users" where "id" = ? limit 1', [1], true)->andReturn([['foo' => 'bar']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select "foo" from "users" where "id" = ? limit 1', [1], true, [])->andReturn([['foo' => 'bar']]); $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturn([['foo' => 'bar']]); $results = $builder->from('users')->where('id', '=', 1)->value('foo'); $this->assertSame('bar', $results); @@ -3547,7 +3547,7 @@ public function testValueMethodReturnsSingleColumn() public function testRawValueMethodReturnsSingleColumn() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select UPPER("foo") from "users" where "id" = ? limit 1', [1], true)->andReturn([['UPPER("foo")' => 'BAR']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select UPPER("foo") from "users" where "id" = ? limit 1', [1], true, [])->andReturn([['UPPER("foo")' => 'BAR']]); $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['UPPER("foo")' => 'BAR']])->andReturn([['UPPER("foo")' => 'BAR']]); $results = $builder->from('users')->where('id', '=', 1)->rawValue('UPPER("foo")'); $this->assertSame('BAR', $results); @@ -3556,7 +3556,7 @@ public function testRawValueMethodReturnsSingleColumn() public function testAggregateFunctions() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3574,7 +3574,7 @@ public function testAggregateFunctions() $this->assertTrue($results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select max("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select max("id") as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3582,7 +3582,7 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select min("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select min("id") as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3590,7 +3590,7 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select sum("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select sum("id") as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3598,7 +3598,7 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select avg("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select avg("id") as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3606,7 +3606,7 @@ public function testAggregateFunctions() $this->assertEquals(1, $results); $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select avg("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select avg("id") as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3657,9 +3657,9 @@ public function testDoesntExistsOr() public function testAggregateResetFollowedByGet() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); - $builder->getConnection()->shouldReceive('select')->once()->with('select sum("id") as aggregate from "users"', [], true)->andReturn([['aggregate' => 2]]); - $builder->getConnection()->shouldReceive('select')->once()->with('select "column1", "column2" from "users"', [], true)->andReturn([['column1' => 'foo', 'column2' => 'bar']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select sum("id") as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 2]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select "column1", "column2" from "users"', [], true, [])->andReturn([['column1' => 'foo', 'column2' => 'bar']]); $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3675,8 +3675,8 @@ public function testAggregateResetFollowedByGet() public function testAggregateResetFollowedBySelectGet() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count("column1") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); - $builder->getConnection()->shouldReceive('select')->once()->with('select "column2", "column3" from "users"', [], true)->andReturn([['column2' => 'foo', 'column3' => 'bar']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count("column1") as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select "column2", "column3" from "users"', [], true, [])->andReturn([['column2' => 'foo', 'column3' => 'bar']]); $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3690,8 +3690,8 @@ public function testAggregateResetFollowedBySelectGet() public function testAggregateResetFollowedByGetWithColumns() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count("column1") as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); - $builder->getConnection()->shouldReceive('select')->once()->with('select "column2", "column3" from "users"', [], true)->andReturn([['column2' => 'foo', 'column3' => 'bar']]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count("column1") as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select "column2", "column3" from "users"', [], true, [])->andReturn([['column2' => 'foo', 'column3' => 'bar']]); $builder->getProcessor()->shouldReceive('processSelect')->andReturnUsing(function ($builder, $results) { return $results; }); @@ -3705,7 +3705,7 @@ public function testAggregateResetFollowedByGetWithColumns() public function testAggregateWithSubSelect() { $builder = $this->getBuilder(); - $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true)->andReturn([['aggregate' => 1]]); + $builder->getConnection()->shouldReceive('select')->once()->with('select count(*) as aggregate from "users"', [], true, [])->andReturn([['aggregate' => 1]]); $builder->getProcessor()->shouldReceive('processSelect')->once()->andReturnUsing(function ($builder, $results) { return $results; }); @@ -5191,12 +5191,12 @@ public function testSelectWithLockUsesWritePdo() { $builder = $this->getMySqlBuilderWithProcessor(); $builder->getConnection()->shouldReceive('select')->once() - ->with(m::any(), m::any(), false); + ->with(m::any(), m::any(), false, []); $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock()->get(); $builder = $this->getMySqlBuilderWithProcessor(); $builder->getConnection()->shouldReceive('select')->once() - ->with(m::any(), m::any(), false); + ->with(m::any(), m::any(), false, []); $builder->select('*')->from('foo')->where('bar', '=', 'baz')->lock(false)->get(); } diff --git a/tests/Integration/Database/QueryBuilderTest.php b/tests/Integration/Database/QueryBuilderTest.php index c323ff0e1513..57a1593dac69 100644 --- a/tests/Integration/Database/QueryBuilderTest.php +++ b/tests/Integration/Database/QueryBuilderTest.php @@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Schema; use Illuminate\Testing\Assert as PHPUnit; use Orchestra\Testbench\Attributes\DefineEnvironment; +use PDO; use PDOException; class QueryBuilderTest extends DatabaseTestCase @@ -634,6 +635,56 @@ public function testPluck() $this->assertSame([ 'Lorem Ipsum.' => 'Bar Post', ], DB::table('posts')->pluck('title', 'content')->toArray()); + + // Test custom select query before calling pluck. + $result = DB::table('posts') + ->selectSub(DB::table('posts')->selectRaw('COUNT(*)'), 'total_posts_count') + ->pluck('total_posts_count') + ->toArray(); + // Cast for database compatibility. + $this->assertSame(2, (int) $result[0]); + $this->assertSame(2, (int) $result[1]); + } + + public function testFetchUsing() + { + // Fetch column as a list. + $this->assertSame([ + 'Foo Post', + 'Bar Post', + ], DB::table('posts')->select(['title'])->fetchUsing(PDO::FETCH_COLUMN)->get()->toArray()); + + // Fetch the second column as a list (zero-indexed). + $this->assertSame([ + 'Lorem Ipsum.', + 'Lorem Ipsum.', + ], DB::table('posts')->select(['title', 'content'])->fetchUsing(PDO::FETCH_COLUMN, 1)->get()->toArray()); + + // Fetch two columns as key value pairs. + $this->assertSame([ + 1 => 'Foo Post', + 2 => 'Bar Post', + ], DB::table('posts')->select(['id', 'title'])->fetchUsing(PDO::FETCH_KEY_PAIR)->get()->toArray()); + + // Fetch data as associative array with custom key. + $result = DB::table('posts')->select(['id', 'title'])->fetchUsing(PDO::FETCH_UNIQUE)->get()->toArray(); + // Note: results are keyed by their post id here. + $this->assertSame('Foo Post', $result[1]->title); + $this->assertSame('Bar Post', $result[2]->title); + + // Use a cursor. + $this->assertSame([ + 'Foo Post', + 'Bar Post', + ], DB::table('posts')->select(['title'])->fetchUsing(PDO::FETCH_COLUMN)->cursor()->collect()->toArray()); + + // Test the default 'object' fetch mode. + $result = DB::table('posts')->select(['title'])->fetchUsing(PDO::FETCH_OBJ)->get()->toArray(); + $result2 = DB::table('posts')->select(['title'])->fetchUsing()->get()->toArray(); + $this->assertSame('Foo Post', $result[0]->title); + $this->assertSame('Bar Post', $result[1]->title); + $this->assertSame('Foo Post', $result2[0]->title); + $this->assertSame('Bar Post', $result2[1]->title); } protected function defineEnvironmentWouldThrowsPDOException($app)