hyperf 二十六 数据迁移 二

news2024/11/17 9:46:32

教程:Hyperf

参考文章hyperf 二十五 数据迁移 一-CSDN博客

根据之前写的数据迁移的文章,已经说明Hyperf\Database\Schema\Schema::create()实际运行Hyperf\Database\Schema\Grammars\MySqlGrammar::compileCreate()生成的sql字符串。

文档所谓"在迁移文件中主要通过 Hyperf\Database\Schema\Schema 类来定义数据表和管理迁移流程。",就是使用Schema来执行具体的迁移sql。生成迁移sql的内容由回调设置。

一 数据表

1.1 创建数据表

使用Hyperf\Database\Schema\Blueprint类对象设置表结构。

属性解释类型

engine

指定表存储引擎string

charset

指定表默认字符集string

collation

指定表默认排序规则string

temporary

指定是否为临时表boolen

after

在该列之后添加新列string

Blueprint::temporary()设置temporary为true,设置为临时表。

1.2 重命名数据表

可以使用 $table->rename($to),或者Schema::rename($from,$to)。

 1.2.1 $table->rename($to)

Blueprint::rename($to)重命名表名,$to为重新定义的表名。

执行的是Blueprint::rename(),其将执行内容设置为Hyperf\Utils\Fluent类的name属性,并将其放到数组commands中,之后获取sql时调用Blueprint::toSql()。

Blueprint::toSql()遍历数组commands,执行以compile开头的Hyperf\Database\Schema\Grammars\Grammar或其子类的对应方法。

1.2.2 Schema::rename($from, $to)

Hyperf\Database\Schema\Schema::__callStatic()获取对应驱动的Connection子类,再获取Builder或其子类执行对应方法。

以musql驱动为例,$table->rename($to)执行Hyperf\Database\Schema\Blueprint::rename($to),Schema::rename($from,$to)通过子类Hyperf\Database\Schema\MySqlBuilder执行Hyperf\Database\Schema\Builder::rename($from,$to)。

Builder::rename($from,$to)中调用Builder::createBlueprint(),返回Hyperf\Database\Schema\Blueprint类对象。即Schema::rename($from,$to)其实最后也是执行Blueprint类方法。

使用Blueprint需要在回调当中使用。根据源码Schema::table()中可以设置回调。

注:在重命名表之前,应判断该表是否为其他表外键。

1.3 删除数据表

在删除表之前应判断表是否存在。

1.3.1 删除表

使用Schema::drop($table),或者$table::drop()。

根据以上逻辑,$table::drop()执行Hyperf\Database\Schema\Blueprint::drop(),Schema::drop($table)执行Hyperf\Database\Schema\Builder::drop($table)。

Builder::drop($table)中也调用Builder::createBlueprint()。

1.3.2 判断表是否存在

使用Schema::dropIfExists($table),或者$table::dropIfExists()。

根据以上逻辑,$table::drop()执行Hyperf\Database\Schema\Blueprint::dropIfExists(),Schema::drop($table)执行Hyperf\Database\Schema\Builder::dropIfExists($table)。

Builder::dropIfExists($table)中也调用Builder::createBlueprint()。

1.3.3 检查表是否存在

使用Schema::hasTable($table),执行Hyperf\Database\Schema\Builder::hasTable($table)。

Schema\Builder::hasTable($table)直接执行Hyperf\Database\Schema\Grammars\Grammar或其子类compileTableExists()返回的sql字符串。

1.3.4 检查字段是否存在

使用Schema::hasColumn($table, $column),执行Hyperf\Database\Schema\Builder::hasColumn($table, $column)。也是直接执行查询出列名,再用in_array()做判断。

1.4 数据库链接选项

设置connection属性,其值为数据库配置文件中数组最外层key值。

为多个数据库连接设置对应配置……这样根据之前文章的修改内容就不用改了……

这里的内容,若迁移使用不同数据库配置,而且不修改源码的情况下,需要在前文件中设置连接。

这样确实安全点……但是执行迁移时,参数中--database会无效而且还不能回滚,除非设置成和命令一样的表。

/(ㄒoㄒ)/~~ 还是一次性看完比较好,当时就想到会有这样的设计,但是感觉不太合理。

二 字段

2.1 创建字段

可用字段定义方法

$table->bigIncrements('id');递增 ID(主键),相当于「UNSIGNED BIG INTEGER」
$table->bigInteger('votes');相当于 BIGINT
$table->binary('data');相当于 BLOB
$table->boolean('confirmed');相当于 BOOLEAN
$table->char('name', 100);相当于带有长度的 CHAR
$table->date('created_at');相当于 DATE
$table->dateTime('created_at');相当于 DATETIME
$table->dateTimeTz('created_at');相当于带时区 DATETIME
$table->decimal('amount', 8, 2);相当于带有精度与基数 DECIMAL
$table->double('amount', 8, 2);相当于带有精度与基数 DOUBLE
$table->enum('level', ['easy', 'hard']);相当于 ENUM
$table->float('amount', 8, 2);相当于带有精度与基数 FLOAT
$table->geometry('positions');相当于 GEOMETRY
$table->geometryCollection('positions');相当于 GEOMETRYCOLLECTION
$table->increments('id');递增的 ID (主键),相当于「UNSIGNED INTEGER」
$table->integer('votes');相当于 INTEGER
$table->ipAddress('visitor');相当于 IP 地址
$table->json('options');相当于 JSON
$table->jsonb('options');相当于 JSONB
$table->lineString('positions');相当于 LINESTRING
$table->longText('description');相当于 LONGTEXT
$table->macAddress('device');相当于 MAC 地址
$table->mediumIncrements('id');递增 ID (主键) ,相当于「UNSIGNED MEDIUM INTEGER」
$table->mediumInteger('votes');相当于 MEDIUMINT
$table->mediumText('description');相当于 MEDIUMTEXT
$table->morphs('taggable');相当于加入递增的 taggable_id 与字符串 taggable_type
$table->multiLineString('positions');相当于 MULTILINESTRING
$table->multiPoint('positions');相当于 MULTIPOINT
$table->multiPolygon('positions');相当于 MULTIPOLYGON
$table->nullableMorphs('taggable');相当于可空版本的 morphs() 字段
$table->nullableTimestamps();相当于可空版本的 timestamps() 字段
$table->point('position');相当于 POINT
$table->polygon('positions');相当于 POLYGON
$table->rememberToken();相当于可空版本的 VARCHAR (100) 的 remember_token 字段
$table->smallIncrements('id');递增 ID (主键) ,相当于「UNSIGNED SMALL INTEGER」
$table->smallInteger('votes');相当于 SMALLINT
$table->softDeletes();相当于为软删除添加一个可空的 deleted_at 字段
$table->softDeletesTz();相当于为软删除添加一个可空的 带时区的 deleted_at 字段
$table->string('name', 100);相当于带长度的 VARCHAR
$table->text('description');相当于 TEXT
$table->time('sunrise');相当于 TIME
$table->timeTz('sunrise');相当于带时区的 TIME
$table->timestamp('added_on');相当于 TIMESTAMP
$table->timestampTz('added_on');相当于带时区的 TIMESTAMP
$table->timestamps();相当于可空的 created_at 和 updated_at TIMESTAMP
$table->timestampsTz();相当于可空且带时区的 created_at 和 updated_at TIMESTAMP
$table->tinyIncrements('id');相当于自动递增 UNSIGNED TINYINT
$table->tinyInteger('votes');相当于 TINYINT
$table->unsignedBigInteger('votes');相当于 Unsigned BIGINT
$table->unsignedDecimal('amount', 8, 2);相当于带有精度和基数的 UNSIGNED DECIMAL
$table->unsignedInteger('votes');相当于 Unsigned INT
$table->unsignedMediumInteger('votes');相当于 Unsigned MEDIUMINT
$table->unsignedSmallInteger('votes');相当于 Unsigned SMALLINT
$table->unsignedTinyInteger('votes');相当于 Unsigned TINYINT
$table->uuid('id');相当于 UUID
$table->year('birth_year');相当于 YEAR
$table->comment('Table Comment');设置表注释,相当于 COMMENT

 大概运行都是Grammar或其子类,简称为Grammar类。运行Grammar类方法compileAdd(),Grammar::compileAdd()中运行Grammar::getType(),调用以type开头的Grammar类对应方法,用于返回sql字符串。

2.2 修改字段

composer require "doctrine/dbal:^3.0"

 根据文档

Schema::table('users', function (Blueprint $table) {
    // 将字段的长度修改为 50 并允许为空
    $table->string('name', 50)->nullable()->change();
});

$table->string()返回\Hyperf\Database\Schema\ColumnDefinition类对象。ColumnDefinition父类Hyperf\Utils\Fluent::__call()实际执行nullable()和change()。

Fluent::__call()返回$this,所以用“->”继续调用。其仅设置以方法名设置的属性值。

Hyperf\Database\Schema\Blueprint::toSql()时使用对应属性,具体执行Hyperf\Database\Schema\Grammars\Grammar::compileChange(),最终执行Doctrine\DBAL\Platforms\AbstractMySQLPlatform::getAlterTableSQL()。

所以必须安装doctrine/dbal。

只有下面的字段类型能被 "修改": bigInteger、 binary、 boolean、date、dateTime、dateTimeTz、decimal、integer、json、 longText、mediumText、smallInteger、string、text、time、 unsignedBigInteger、unsignedInteger and unsignedSmallInteger。

2.3 重命名字段

$table->renameColumn('from', 'to')->change();

执行Hyperf\Database\Schema\Grammars\Grammar::compileRenameColumn(),然后执行Hyperf\Database\Schema\Grammars\RenameColumn::compile(),最后也是执行Doctrine\DBAL\Platforms\AbstractMySQLPlatform::getAlterTableSQL()。

2.4 删除字段

$table->dropColumn('name');

$table->dropColumn(['name', 'age']);

根据以上逻辑执行Hyperf\Database\Schema\Grammars\Grammar:compileDropColumn(),直接生成sql字符串。

三 测试

3.1 表

测试流程

  1. 创建表
  2. 重命名表
  3. 删除表

3.1.1 创建表

use test1;
show tables;

 

php bin/hyperf gen:migration create_test_table
#migrations\2024_03_06_082623_create_userinfo_table.php
class CreateUserinfoTable extends Migration {
    protected $connection = 'default2';
    /**
     * Run the migrations.
     */
    public function up(): void {
        Schema::create('userinfo', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void {
        Schema::dropIfExists('userinfo');
    }
}
#migrations\2024_03_11_070103_create_test_table.php
class CreateTestTable extends Migration {

    protected $connection = 'default2';
    /**
     * Run the migrations.
     */
    public function up(): void {
        Schema::create('test', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
            $table->engine = 'MyISAM';
            // 指定数据表的默认字符集
            $table->charset = 'utf8mb4';
            // 指定数据表默认的排序规则
            $table->collation = 'utf8mb4_unicode_ci';
            // 创建临时表
            $table->temporary();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void {
        Schema::dropIfExists('test');
    }
}
php bin/hyperf.php   migrate --database=default2
Migrating: 2024_03_06_082623_create_userinfo_table
Migrated:  2024_03_06_082623_create_userinfo_table
Migrating: 2024_03_11_070103_create_test_table
Migrated:  2024_03_11_070103_create_test_table

 

 migration中有test表的记录,但是实际库中没有test表。可能和设置为临时表有关。

经查询mysql临时表仅在当前会话(session)中有效,会话结束时自动消失。

所以把临时表去掉再试下,但是记录未删除的话不会执行。

再次执行,从数据库表看,执行正常。

 3.1.2 重命名表

php bin/hyperf.php gen:migration update_test_table --table=test

[INFO] Created Migration: 2024_03_11_074311_update_test_table
#migrations\2024_03_11_074311_update_test_table.php
class UpdateTestTable extends Migration {
    protected $connection = 'default2';
    /**
     * Run the migrations.
     */
    public function up(): void {
        Schema::table('test', function (Blueprint $table) {
            $table->rename("test1");
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void {
        Schema::table('test', function (Blueprint $table) {
            //
        });
    }
}
php bin/hyperf.php   migrate --database=default2

Migrating: 2024_03_11_074311_update_test_table
Migrated:  2024_03_11_074311_update_test_table

  3.1.3 删除表

php bin/hyperf.php gen:migration update_test2_table --table=test

[INFO] Created Migration:2024_03_11_075322_update_test2_table.php

因为down函数仅在回滚时执行,所以在up()中设置表删除。

#migrations\2024_03_11_075322_update_test2_table.php
class UpdateTest2Table extends Migration {
    protected $connection = 'default2';
    /**
     * Run the migrations.
     */
    public function up(): void {
        Schema::table('test1', function (Blueprint $table) {
            $table->dropIfExists();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void {
        Schema::table('test1', function (Blueprint $table) {
            //
        });
    }
}
php bin/hyperf.php   migrate --database=default2

Migrating: 2024_03_11_075322_update_test2_table
Migrated:  2024_03_11_075322_update_test2_table

3.2 字段

测试流程

  1. 设置字段
  2. 修改字段
  3. 删除字段

3.2.1 设置字段

php bin/hyperf.php gen:migration update_userinfo_table --table=userinfo

[INFO] Created Migration: 2024_03_11_080602_update_userinfo_table
#migrations\2024_03_11_080602_update_userinfo_table.php
class UpdateUserinfoTable extends Migration {
    protected $connection = 'default2';
    /**
     * Run the migrations.
     */
    public function up(): void {
        Schema::table('userinfo', function (Blueprint $table) {
            $table->string('name', 255);
            $table->tinyInteger('age');
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void {
        Schema::table('userinfo', function (Blueprint $table) {
            //
        });
    }
}
php bin/hyperf.php   migrate --database=default2

Migrating: 2024_03_11_080602_update_userinfo_table
Migrated:  2024_03_11_080602_update_userinfo_table
DESCRIBE userinfo;

3.2.2 修改字段

php bin/hyperf.php gen:migration update_userinfo2_table --table=userinfo

[INFO] Created Migration: 2024_03_11_081819_update_userinfo2_table
#migrations\2024_03_11_081819_update_userinfo2_table.php
class UpdateUserinfo2Table extends Migration {
    protected $connection = 'default2';
    /**
     * Run the migrations.
     */
    public function up(): void {
        Schema::table('userinfo', function (Blueprint $table) {
            $table->string("name")->nullable()->change();
            $table->renameColumn('age', 'age1')->nullable()->change();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void {
        Schema::table('userinfo', function (Blueprint $table) {
            //
        });
    }
}
php bin/hyperf.php   migrate --database=default2

Migrating: 2024_03_11_081819_update_userinfo2_table
Migrated:  2024_03_11_081819_update_userinfo2_table
DESCRIBE userinfo;

执行回滚,然会修改文件再次执行。

php bin/hyperf.php migrate:rollback --database=default2

Rolling back: 2024_03_11_081819_update_userinfo2_table
Rolled back:  2024_03_11_081819_update_userinfo2_table

但是数据库字段没变……因为down里没设置语句……

#migrations\2024_03_11_081819_update_userinfo2_table.php
class UpdateUserinfo2Table extends Migration {
    protected $connection = 'default2';
    /**
     * Run the migrations.
     */
    public function up(): void {
        Schema::table('userinfo', function (Blueprint $table) {
             $table->string("name")->nullable()->change();
            //$table->tinyInteger('age')->nullable()->change();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void {
        Schema::table('userinfo', function (Blueprint $table) {
            $table->string("name")->change();
            $table->tinyInteger('age')->change();
        });
    }
}

经过手动改动后,此时数据表结构:

 测试时用$table->tinyInteger('age')测试修改,确实报错PHP Fatal error:  Uncaught Doctrine\DBAL\Exception: Unknown column type "tinyinteger" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType().

因为这种字段类型不能修改。所以将代码改为上面图中内容,再次执行。

php bin/hyperf.php   migrate --database=default2

Migrating: 2024_03_11_081819_update_userinfo2_table
Migrated:  2024_03_11_081819_update_userinfo2_table

 测试发现写notnull无效,因为改前和改后表差异对比时返回false,但是Hyperf\Utils\Fluent属性notnull确实设置为true。

对应源码

#Hyperf\Database\Schema\Grammars\ChangeColumn
public static function compile($grammar, Blueprint $blueprint, Fluent $command, Connection $connection) {
        if (!$connection->isDoctrineAvailable()) {
            throw new RuntimeException(sprintf(
                'Changing columns for table "%s" requires Doctrine DBAL; install "doctrine/dbal".',
                $blueprint->getTable()
            ));
        }

        $tableDiff = static::getChangedDiff(
            $grammar,
            $blueprint,
            $schema = $connection->getDoctrineSchemaManager()
        );
        if ($tableDiff !== false) {
            return (array) $schema->getDatabasePlatform()->getAlterTableSQL($tableDiff);
        }

        return [];
    }

#$tableDiff 为false
#Hyperf\Database\Schema\Grammars\ChangeColumn
protected static function getTableWithColumnChanges(Blueprint $blueprint, Table $table) {
        $table = clone $table;
        foreach ($blueprint->getChangedColumns() as $fluent) {
            $column = static::getDoctrineColumn($table, $fluent);
            // Here we will spin through each fluent column definition and map it to the proper
            // Doctrine column definitions - which is necessary because Laravel and Doctrine
            // use some different terminology for various column attributes on the tables.
            foreach ($fluent->getAttributes() as $key => $value) {
                if (!is_null($option = static::mapFluentOptionToDoctrine($key))) {
                    if (method_exists($column, $method = 'set' . ucfirst($option))) {
                        $column->{$method}(static::mapFluentValueToDoctrine($option, $value));
                    }
                }
            }
        }

        return $table;
    }

protected static function getTableWithColumnChanges(Blueprint $blueprint, Table $table) {
        $table = clone $table;
        foreach ($blueprint->getChangedColumns() as $fluent) {
            $column = static::getDoctrineColumn($table, $fluent);
            // Here we will spin through each fluent column definition and map it to the proper
            // Doctrine column definitions - which is necessary because Laravel and Doctrine
            // use some different terminology for various column attributes on the tables.
            foreach ($fluent->getAttributes() as $key => $value) {
                if (!is_null($option = static::mapFluentOptionToDoctrine($key))) {
                    if (method_exists($column, $method = 'set' . ucfirst($option))) {
                        $column->{$method}(static::mapFluentValueToDoctrine($option, $value));
                    }
                }
            }
        }

        return $table;
    }

#column 
/***
object(Doctrine\DBAL\Schema\Column)#901 (16) {
  ["_type":protected]=>
  object(Doctrine\DBAL\Types\StringType)#884 (0) {
  }
  ["_length":protected]=>
  int(255)
  ["_precision":protected]=>
  int(10)
  ["_scale":protected]=>
  int(0)
  ["_unsigned":protected]=>
  bool(false)
  ["_fixed":protected]=>
  bool(false)
  ["_notnull":protected]=>
  bool(false)
  ["_default":protected]=>
  NULL
  ["_autoincrement":protected]=>
  bool(false)
  ["_platformOptions":protected]=>
  array(2) {
    ["charset"]=>
    string(7) "utf8mb4"
    ["collation"]=>
    string(18) "utf8mb4_unicode_ci"
  }
  ["_columnDefinition":protected]=>
  NULL
  ["_comment":protected]=>
  NULL
  ["_customSchemaOptions":protected]=>
  array(0) {
  }
  ["_name":protected]=>
  string(4) "name"
  ["_namespace":protected]=>
  NULL
  ["_quoted":protected]=>
  bool(false)
}
***/

#$fluent
/***
array(5) {
  ["type"]=>
  string(6) "string"
  ["name"]=>
  string(4) "name"
  ["length"]=>
  int(255)
  ["notnull"]=>
  bool(true)
  ["change"]=>
  bool(true)
}
***/
#Hyperf\Database\Schema\Grammars\ChangeColumn
protected static function mapFluentOptionToDoctrine($attribute) {
        switch ($attribute) {
        case 'type':
        case 'name':
            return;
        case 'nullable':
            return 'notnull';
        case 'total':
            return 'precision';
        case 'places':
            return 'scale';
        default:
            return $attribute;
        }
    }
#Hyperf\Utils\Fluent
public function __call($method, $parameters)
    {
        $this->attributes[$method] = count($parameters) > 0 ? $parameters[0] : true;

        return $this;
    }
#Doctrine\DBAL\Schema\Column
/** @return mixed[] */
    public function toArray()
    {
        return array_merge([
            'name'          => $this->_name,
            'type'          => $this->_type,
            'default'       => $this->_default,
            'notnull'       => $this->_notnull,
            'length'        => $this->_length,
            'precision'     => $this->_precision,
            'scale'         => $this->_scale,
            'fixed'         => $this->_fixed,
            'unsigned'      => $this->_unsigned,
            'autoincrement' => $this->_autoincrement,
            'columnDefinition' => $this->_columnDefinition,
            'comment' => $this->_comment,
        ], $this->_platformOptions, $this->_customSchemaOptions);
    }
#Doctrine\DBAL\Platforms\DB2Platform
private function getAlterColumnClausesSQL(ColumnDiff $columnDiff): array
    {
        $newColumn = $columnDiff->getNewColumn()->toArray();

        $alterClause = 'ALTER COLUMN ' . $columnDiff->getNewColumn()->getQuotedName($this);

        if ($newColumn['columnDefinition'] !== null) {
            return [$alterClause . ' ' . $newColumn['columnDefinition']];
        }
    ……
}

 

根据源码意思,应该是看Doctrine\DBAL\Schema\Column类中是否有对应的set方法。果然Column类中没有setNotnull(),仅有setNullable()。所以能用的就是Column类中以set开头的方法。

方法调用解释
Column::setType()type()字段类型
Column::setNamename()字段名
Column::setLength()length()字段长度

Column::setPrecision()

total()或者precision()

字段浮点精度

setScale()

places()或者scale()小数点后位数

setUnsigned()

unsigned()无符号

setFixed()

fixed()双精度浮点

setNotnull()

notnull()设置是否不为空

setDefault()

default()设置默认值

setPlatformOptions()

platformOptions()批量设置其他属性

setPlatformOption()

platformOption()单个设置其他属性

setColumnDefinition()

columnDefinition()大概是直接定义的语句

 

应该notnull这样的属性没被处理。 结合属性的定义,可以尝试传参数。比如nullable(false)。

执行代码改为

#migrations\2024_03_11_081819_update_userinfo2_table.php
class UpdateUserinfo2Table extends Migration {
    protected $connection = 'default2';
    /**
     * Run the migrations.
     */
    public function up(): void {
        Schema::table('userinfo', function (Blueprint $table) {
             $table->string("name")->nullable(false)->change();
            //$table->tinyInteger('age')->nullable()->change();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void {
        Schema::table('userinfo', function (Blueprint $table) {
            $table->string("name")->change();
            $table->tinyInteger('age')->change();
        });
    }
}
php bin/hyperf.php   migrate --database=default2

Migrating: 2024_03_11_081819_update_userinfo2_table
Migrated:  2024_03_11_081819_update_userinfo2_table

修改成功

3.2.3 删除字段

php bin/hyperf.php gen:migration update_userinfo3_table --table=userinfo

[INFO] Created Migration: 2024_03_11_094726_update_userinfo3_table
#migrations\2024_03_11_094726_update_userinfo3_table.php
class UpdateUserinfo3Table extends Migration {
    protected $connection = 'default2';
    /**
     * Run the migrations.
     */
    public function up(): void {
        Schema::table('userinfo', function (Blueprint $table) {
            $table->dropColumn(['name', 'age']);
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void {
        Schema::table('userinfo', function (Blueprint $table) {
            //
        });
    }
}
php bin/hyperf.php   migrate --database=default2

Migrating: 2024_03_11_094726_update_userinfo3_table
Migrated:  2024_03_11_094726_update_userinfo3_table
DESCRIBE userinfo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1509677.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Games101笔记-计算机图形学概述

光栅化:把三维空间的几何形体显示在屏幕上 实时:每秒30帧的画面 曲线和曲面: 如何表示一条光滑曲线,如何表示曲面如何用简单的曲面通过细分的方法得到更复杂的曲面在形状发生变化时,面要如何变化,如何保…

STM32F103 CubeMX 定时器输出PWM控制呼吸灯

STM32F103 CubeMX 定时器输出PWM控制呼吸灯 1. 生成代码1. 1 配置外部时钟,SWD口1.2 配置定时器31.3 配置定时器2 2. 代码编写的部分 使用的cubmx 软件的版本:6.2.0 最新版本 6.10(2024年3月11日) 1. 生成代码 1. 1 配置外部时钟…

从零学算法287

287.给定一个包含 n 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。 你设计的解决方案必须 不修改 数组 nums 且只…

数字电子技术笔记——组合逻辑功能

1.Adder(加法器) Half-Adder(半加器) Full-Adder(全加器) 74LS283(4-bit parallel adders) carry look-ahead adder (超前进位加法器) 2.Comparator(比较器)…

基于Python3的数据结构与算法 - 14 队列

目录 一、定义 1. 环形队列 2. 自定义队列 二、队列的内置模块 1. 双向队列 一、定义 队列(Queue)是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除。进行插入的一端称为队尾(rear)&#…

python请求url下载网站中的视频

举例网站:Mini Impresora Trmica Bluetooth Porttil Inalmbrico | Envo gratis ctrlF4 先搜mp4 搜不到就搜m3u8 了 视频格式如下 ( AVI(Audio Video Interleave):是一种由微软公司开发的音频和视频文件格式。MOV&…

02_electron快速建立项目

一、安装 yarn 在此之前可以先安装 git:Git - Downloads (git-scm.com) 下面就是 yarn 安装的代码,在终端输入即可。 npm install --global yarn 检查是否安装成功: yarn --version 二、快速建立一个electron项目 其实在Getting Started - …

【HarmonyOS】鸿蒙开发之工具安装与工程项目简介——第1章

鸿蒙开发工具包下载与使用 鸿蒙开发工具包下载 下载deveco studio开发工具包 系统要求: Windows 操作系统:Windows 10/11 64 位 内存:8GB 及以上 硬盘:100GB 及以上 分辨率:1280*800 像素及以上macOS 操作系统:mac…

【rk3229 android7.1.2 替换默认输入法】

问题平台描述 问题描述解决方法 郑重声明:本人原创博文,都是实战,均经过实际项目验证出货的 转载请标明出处:攻城狮2015 Platform: Rockchip CPU:rk3229 OS:Android 7.1.2 Kernel: 3.10 问题描述 国内客户,觉得安卓自带的输入法不好用&#x…

LeetCode刷题---每月交易I

LeetCode官方题解 解题思想: 首先按照日期和国家/地区进行分组 对分组后的结果求解,使用IF函数进行过滤 涉及函数 1.在对日期截取时,使用了MySQL中的DATE_FORMAT函数,将日期转换为指定格式的日期 //2024-03-11,截取为 2024-03-…

【数据可视化】数据可视化入门前的了解

个人主页 : zxctscl 如有转载请先通知 文章目录 1. 前言2. 数据可视化概述2.1 数据可视化的定义及特性2.1.1 数据可视化的定义2.1.2 特性 2.2 数据中蕴含的信息2.3 数据可视化的作用2.3.1 模式2.3.2 关系2.3.3 异常 3. 数据可视化流程4. 数据可视化工具4.1 ECharts4…

如何在Linux部署FastDFS文件服务并实现无公网IP远程访问内网文件——“cpolar内网穿透”

文章目录 前言1. 本地搭建FastDFS文件系统1.1 环境安装1.2 安装libfastcommon1.3 安装FastDFS1.4 配置Tracker1.5 配置Storage1.6 测试上传下载1.7 与Nginx整合1.8 安装Nginx1.9 配置Nginx 2. 局域网测试访问FastDFS3. 安装cpolar内网穿透4. 配置公网访问地址5. 固定公网地址5.…

记录一下某外资的面试

文章目录 标题English introduction标题What did u do in this gap time标题What’S the big challenge in your work experience标题 4、介绍一个自己熟悉的项目或最近的项目,包括项目的背景,使用的技术,在里面的角色标题5、项目中有多少个微…

力扣--深度优先算法/回溯算法78.子集

思路分析: 首先,定义了一个类 Solution,其中包含一个成员变量 result 用于存储最终的所有子集。在类中定义了一个私有成员函数 dfs,用于执行深度优先搜索,生成所有可能的子集。主函数 subsets 初始化结果,…

Vue2(4)——iHRM组织架构

组织架构-树组件应用 树形组件-用层级结构展示信息,可展开或折叠。 属性设置 data(绑定数据)props(设置属性)- children(设置子节点的字段名)/ label(设置显示内容的字段名)default-expand-all(默认展开所有节点) 组织架构-树组件自定义结构 显示右侧结构 节点结…

个人商城系统开源(配置支付宝支付!)

原文地址:个人商城系统开源(配置支付宝支付!) - Pleasure的博客 下面是正文内容: 前言 由于近期实在没有什么话题可写和一些有趣的项目教程可以分享。所以我只能决定将我自己亲手编写的一个迷你迷你商城系统进行开源…

npm install报错,error <https://npm.community>解决方法

报错信息如下: 分析原因: 1.可能是由于node版本过低,或者过高,解决方法看我另一文章:npm install报错,npm版本过高,需要切换低版本node,过程记录 2.网络问题导致 3.切换node版本后&#xff0…

Material UI 5 学习03-Text Field文本输入框

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Text Field文本输入框 一、最基本的本文输入框1、基础示例2、一些表单属性3、验证 二、多行文本 一、最基本的本文输入框 1、基础示例 import {Box, TextField} from "…

Linux第76步_“gpio子系统”下的LED驱动

使用新字符设备驱动的一般模板和“gpio子系统”,以及设备树,驱动LED。 1、添加“gpio_led”节点 打开虚拟机上“VSCode”,点击“文件”,点击“打开文件夹”,点击“zgq”,点击“linux”,点击“…

LLM - 大语言模型的自注意力(Self-Attention)机制基础 概述

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/136623432 注意力(Attention)机制是大型语言模型中的一个重要组成部分,帮助模型决定在处理信息时,所应该关注的部…