Repository: laravel/framework (php)

Issue:
MySQL custom primary key creation still broken in 8.48.1
- Laravel Version: 8.48.1
- PHP Version: 8.0.7
- Database Driver & Version: MySQL (Percona server) 8.0.23-14

### Description:

Some old migrations have suddenly broken with a recent Laravel update.

### Steps To Reproduce:

Create a new Laravel project:

    composer create-project laravel/laravel laravel-example

Add this migration:

```php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class CreateSystemTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up(): void
    {
        Schema::create(
            'system',
            static function (Blueprint $table) {
                $table->string('key')
                    ->charset('ascii')
                    ->collation('ascii_bin')
                    ->primary();
                $table->string('value');
            }
        );
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down(): void
    {
        Schema::dropIfExists('system');
    }
}
```

run `php artisan migrate`.

It fails with this error:

```sh
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (19.89ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (13.41ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (16.19ms)
Migrating: 2020_02_09_111130_create_system_table

   Illuminate\Database\QueryException

  SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'character set ascii collate 'ascii_bin' not null, `value` varchar(255) not null)' at line 1 (SQL: create table `system` (`key` varchar(255) primary key character set ascii collate 'ascii_bin' not null, `value` varchar(255) not null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')

  at vendor/laravel/framework/src/Illuminate/Database/Connection.php:692
    688▕         // If an exception occurs when attempting to run a query, we'll format the error
    689▕         // message to include the bindings with SQL, which will make this exception a
    690▕         // lot more helpful to the developer instead of just the database's errors.
    691▕         catch (Exception $e) {
  ➜ 692▕             throw new QueryException(
    693▕                 $query, $this->prepareBindings($bindings), $e
    694▕             );
    695▕         }
    696▕

      +9 vendor frames
  10  database/migrations/2020_02_09_111130_create_system_table.php:25
      Illuminate\Support\Facades\Facade::__callStatic("create")

      +21 vendor frames
  32  artisan:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
```

The SQL it generates is incorrect:

```sql
create table `system` (`key` varchar(255) primary key character set ascii collate 'ascii_bin' not null, `value` varchar(255) not null) default character set utf8mb4 collate 'utf8mb4_unicode_ci'
```

I think the problem is that the clauses are in the wrong order, in particular the position of the `primary key` phrase. This query works fine:

```sql
create table `system` (`key` varchar(255) character set ascii collate 'ascii_bin' primary key not null, `value` varchar(255) not null) default character set utf8mb4 collate 'utf8mb4_unicode_ci'
```

This issue seems to have introduced after Laravel 8.47, presumably in 8.48 or 8.48.1.

<!-- laravel new bug-report --github="--public" -->


Pull request:
[8.x] Move primary after collate
This simply changes the clause order in the MySQL grammar, and appears to fix #37811 in a similar way to the fix that resulted in the 8.48.1 release (which failed for me). I don't know what the definitive order of clauses should be, but this change fixes the issue I found.

Patch:
diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.md b/.github/ISSUE_TEMPLATE/1_Bug_report.md
index 2c7803339b..276d2235fc 100644
--- a/.github/ISSUE_TEMPLATE/1_Bug_report.md
+++ b/.github/ISSUE_TEMPLATE/1_Bug_report.md
@@ -6,8 +6,8 @@
 <!-- DO NOT THROW THIS AWAY -->
 <!-- Fill out the FULL versions with patch versions -->
 
-- Laravel Version: #.#.# <!-- php artisan --version -->
-- PHP Version: #.#.# <!-- php --version -->
+- Laravel Version: #.#.#
+- PHP Version: #.#.#
 - Database Driver & Version:
 
 ### Description:
diff --git a/src/Illuminate/Database/Eloquent/Factories/Sequence.php b/src/Illuminate/Database/Eloquent/Factories/Sequence.php
index 5efa73c105..169cc1d196 100644
--- a/src/Illuminate/Database/Eloquent/Factories/Sequence.php
+++ b/src/Illuminate/Database/Eloquent/Factories/Sequence.php
@@ -16,14 +16,14 @@ class Sequence
      *
      * @var int
      */
-    protected $count;
+    public $count;
 
     /**
-     * The current index of the sequence.
+     * The current index of the sequence iteration.
      *
      * @var int
      */
-    protected $index = 0;
+    public $index = 0;
 
     /**
      * Create a new sequence instance.
@@ -44,11 +44,7 @@ public function __construct(...$sequence)
      */
     public function __invoke()
     {
-        if ($this->index >= $this->count) {
-            $this->index = 0;
-        }
-
-        return tap(value($this->sequence[$this->index]), function () {
+        return tap(value($this->sequence[$this->index % $this->count], $this), function () {
             $this->index = $this->index + 1;
         });
     }
diff --git a/src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php b/src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php
index ad773a433e..4142ddc127 100755
--- a/src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php
+++ b/src/Illuminate/Database/Schema/Grammars/MySqlGrammar.php
@@ -15,7 +15,7 @@ class MySqlGrammar extends Grammar
      * @var string[]
      */
     protected $modifiers = [
-        'Unsigned', 'Primary', 'Charset', 'Collate', 'VirtualAs', 'StoredAs', 'Nullable',
+        'Unsigned', 'Charset', 'Primary', 'Collate', 'VirtualAs', 'StoredAs', 'Nullable',
         'Srid', 'Default', 'Increment', 'Comment', 'After', 'First',
     ];
 
diff --git a/src/Illuminate/Foundation/Console/RouteListCommand.php b/src/Illuminate/Foundation/Console/RouteListCommand.php
index 8a24c5dfb8..2f0725edfa 100644
--- a/src/Illuminate/Foundation/Console/RouteListCommand.php
+++ b/src/Illuminate/Foundation/Console/RouteListCommand.php
@@ -91,7 +91,7 @@ protected function getRoutes()
             return $this->getRouteInformation($route);
         })->filter()->all();
 
-        if ($sort = $this->option('sort')) {
+        if (($sort = $this->option('sort')) !== 'precedence') {
             $routes = $this->sortRoutes($sort, $routes);
         }
 
@@ -269,7 +269,7 @@ protected function getOptions()
             ['path', null, InputOption::VALUE_OPTIONAL, 'Only show routes matching the given path pattern'],
             ['except-path', null, InputOption::VALUE_OPTIONAL, 'Do not display the routes matching the given path pattern'],
             ['reverse', 'r', InputOption::VALUE_NONE, 'Reverse the ordering of the routes'],
-            ['sort', null, InputOption::VALUE_OPTIONAL, 'The column (domain, method, uri, name, action, middleware) to sort by', 'uri'],
+            ['sort', null, InputOption::VALUE_OPTIONAL, 'The column (precedence, domain, method, uri, name, action, middleware) to sort by', 'uri'],
         ];
     }
 }


Test patch:
diff --git a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithContainer.php b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithContainer.php
index b86ad5ac36..f17208ae6d 100644
--- a/src/Illuminate/Foundation/Testing/Concerns/InteractsWithContainer.php
+++ b/src/Illuminate/Foundation/Testing/Concerns/InteractsWithContainer.php
@@ -86,6 +86,8 @@ protected function spy($abstract, Closure $mock = null)
      */
     protected function singletonInstance($abstract, $instance)
     {
+        $abstract = $this->app->getAlias($abstract);
+
         $this->app->singleton($abstract, function () use ($instance) {
             return $instance;
         });
diff --git a/tests/Database/DatabaseEloquentFactoryTest.php b/tests/Database/DatabaseEloquentFactoryTest.php
index 2d1def2395..80e7518488 100644
--- a/tests/Database/DatabaseEloquentFactoryTest.php
+++ b/tests/Database/DatabaseEloquentFactoryTest.php
@@ -404,6 +404,13 @@ public function test_sequences()
         $this->assertCount(2, $user->roles->filter(function ($role) {
             return $role->pivot->admin === 'N';
         }));
+
+        $users = FactoryTestUserFactory::times(2)->sequence(function ($sequence) {
+            return ['name' => 'index: '.$sequence->index];
+        })->create();
+
+        $this->assertSame('index: 0', $users[0]->name);
+        $this->assertSame('index: 1', $users[1]->name);
     }
 
     public function test_resolve_nested_model_factories()
diff --git a/tests/Foundation/Testing/Concerns/InteractsWithContainerTest.php b/tests/Foundation/Testing/Concerns/InteractsWithContainerTest.php
index d8f9e6d254..5bb975ea97 100644
--- a/tests/Foundation/Testing/Concerns/InteractsWithContainerTest.php
+++ b/tests/Foundation/Testing/Concerns/InteractsWithContainerTest.php
@@ -3,6 +3,8 @@
 namespace Illuminate\Tests\Foundation\Testing\Concerns;
 
 use Illuminate\Foundation\Mix;
+use Illuminate\Http\Request;
+use Mockery\MockInterface;
 use Orchestra\Testbench\TestCase;
 use stdClass;
 
@@ -35,4 +37,16 @@ public function testSingletonBoundInstancesCanBeResolved()
         $this->assertEquals('bar', $this->app->make('foo'));
         $this->assertEquals('bar', $this->app->make('foo', ['with' => 'params']));
     }
+
+    public function testSingletonRebindsAlias()
+    {
+        $this->app->instance('request', Request::create('/example'));
+
+        $this->mock(Request::class, function (MockInterface $mock) {
+            //
+        });
+
+        $this->assertInstanceOf(MockInterface::class, resolve(Request::class));
+        $this->assertInstanceOf(MockInterface::class, resolve('request'));
+    }
 }