hyperf 二十八 修改器 一

news2024/11/17 4:46:08

教程:Hyperf

一 修改器和访问器

根据教程,可设置相关函数,如set属性名Attribute()、get属性名Attribute(),设置和获取属性。这在thinkphp中也常见。

修改器:set属性名Attribute();访问器:get属性名Attribute()。

1.1 原理

模型的父类Hyperf\Database\Model\Model,定义__set()、_get()、__isset()、__unset()函数。

设置属性调用__set(),获取属性调用_get()。

__set()调用set属性名Attribute(),和格式化数据。先通过set属性名Attribute()获取值,再判断是否为日期格式化日期数据。若设置字段类型,会根据设定的字段类型匹配对应的类,返回对应类。会判断是否为json数据返回json格式字符换。若调用的对应字符串含有“->”,则将该对应类对象格式化为json字符串返回。

1.2 测试

#App\Controller\Test
public function testmodifier() {
        $result = Article::query()->find(2)->toArray();
        var_dump($result);
        $article = Article::firstOrCreate(
            ['title' => 'test4'],
            ['user_id' => 2]
        );
        $result = Article::query()->where(['title' => '&test4'])->first()->toArray();
        var_dump($result);
    }
#App1\Model\Article
class Article extends Model implements CacheableInterface {
    use Cacheable;
    use SoftDeletes;
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'articles';
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['title', 'user_id']; //允许批量赋值
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = ['id' => 'integer', 'created_at' => 'datetime', 'updated_at' => 'datetime'];

    public function setTitleAttribute($value) {
        $this->attributes['title'] = "&" . $value;
    }
    public function getTitleAttribute($value) {
        return "标题:" . $value;
    }
}

 测试结果

array(7) {
  ["id"]=>
  int(2)
  ["user_id"]=>
  int(1)
  ["title"]=>
  string(14) "标题:test2"
  ["created_at"]=>
  string(19) "2024-01-13 10:06:04"
  ["updated_at"]=>
  string(19) "2024-01-13 10:06:06"
  ["deleted_at"]=>
  NULL
  ["pv_num"]=>
  int(0)
}

array(7) {
  ["id"]=>
  int(10)
  ["user_id"]=>
  int(2)
  ["title"]=>
  string(15) "标题:&test4"
  ["created_at"]=>
  string(19) "2024-03-19 08:07:24"
  ["updated_at"]=>
  string(19) "2024-03-19 08:07:24"
  ["deleted_at"]=>
  NULL
  ["pv_num"]=>
  int(0)
}

数据保存使用Hyperf\Database\Model\Builder::firstOrCreate()。firstOrNew()仅在对象中增加数据,未保存进数据库,这是和firstOrCreate()的区别。

过程中创建Hyperf\Database\Model\Model类对象是__construct(),会调用Model::fill()。Model::fill()使用Model::isFillable()调用Model::fillable属性,结果为true,才能设置属性,否则报错。

因为在Article::setTitleAttribute()对传入的属性增加数据。根据测试代码,查询的使用也应该加上“&”。

也是因为使用Builder::firstOrCreate()和Article::setTitleAttribute()修改传入属性,设置查询数据时不会查询到相应数据,因为查询值有差异。

tp中也遇到过相似情况。解决方法,对查询条件中数据也进行数据的换装,保证修改方式和保存之前的数据方式一样。

1.3 源码

#App1\Model\Article 

use Hyperf\DbConnection\Model\Model;

class Article extends Model implements CacheableInterface {
    use Cacheable;
    use SoftDeletes;
}


#Hyperf\DbConnection\Model\Model

use Hyperf\Database\Model\Model as BaseModel;

class Model extends BaseModel
{
    use HasContainer;
    use HasRepository;
}
#Hyperf\Database\Model\Model

abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, 
CompressInterface {
    use Concerns\HasAttributes;
    use Concerns\HasEvents;
    use Concerns\HasGlobalScopes;
    use Concerns\HasRelationships;
    use Concerns\HasTimestamps;
    use Concerns\HidesAttributes;
    use Concerns\GuardsAttributes;

    /**
     * Dynamically retrieve attributes on the model.
     *
     * @param string $key
     */
    public function __get($key) {
        return $this->getAttribute($key);
    }

    /**
     * Dynamically set attributes on the model.
     *
     * @param string $key
     * @param mixed $value
     */
    public function __set($key, $value) {
        $this->setAttribute($key, $value);
    }

    /**
     * Determine if an attribute or relation exists on the model.
     *
     * @param string $key
     * @return bool
     */
    public function __isset($key) {
        return $this->offsetExists($key);
    }

    /**
     * Unset an attribute on the model.
     *
     * @param string $key
     */
    public function __unset($key) {
        $this->offsetUnset($key);
    }
   
}
# Hyperf\Database\Model\Concerns\HasAttributes
 /**
     * Set a given attribute on the model.
     *
     * @param string $key
     * @param mixed $value
     */
    public function setAttribute($key, $value)
    {
        // First we will check for the presence of a mutator for the set operation
        // which simply lets the developers tweak the attribute as it is set on
        // the model, such as "json_encoding" an listing of data for storage.
        if ($this->hasSetMutator($key)) {
            return $this->setMutatedAttributeValue($key, $value);
        }

        // If an attribute is listed as a "date", we'll convert it from a DateTime
        // instance into a form proper for storage on the database tables using
        // the connection grammar's date format. We will auto set the values.
        if ($value && $this->isDateAttribute($key)) {
            $value = $this->fromDateTime($value);
        }

        if ($this->isClassCastable($key)) {
            $this->setClassCastableAttribute($key, $value);

            return $this;
        }

        if ($this->isJsonCastable($key) && !is_null($value)) {
            $value = $this->castAttributeAsJson($key, $value);
        }

        // If this attribute contains a JSON ->, we'll set the proper value in the
        // attribute's underlying array. This takes care of properly nesting an
        // attribute in the array's value in the case of deeply nested items.
        if (Str::contains($key, '->')) {
            return $this->fillJsonAttribute($key, $value);
        }

        $this->attributes[$key] = $value;

        return $this;
    }
    /**
     * Set the value of an attribute using its mutator.
     *
     * @param string $key
     * @param mixed $value
     */
    protected function setMutatedAttributeValue($key, $value)
    {
        return $this->{'set' . Str::studly($key) . 'Attribute'}($value);
    }
     /**
     * Convert a DateTime to a storable string.
     *
     * @param mixed $value
     * @return null|string
     */
    public function fromDateTime($value)
    {
        return empty($value) ? $value : $this->asDateTime($value)->format(
            $this->getDateFormat()
        );
    }
     /**
     * Get the format for database stored dates.
     *
     * @return string
     */
    public function getDateFormat()
    {
        return $this->dateFormat ?: $this->getConnection()->getQueryGrammar()->getDateFormat();
    }
/**
     * Set the value of a class castable attribute.
     *
     * @param string $key
     * @param mixed $value
     */
    protected function setClassCastableAttribute($key, $value)
    {
        $caster = $this->resolveCasterClass($key);

        if (is_null($value)) {
            $this->attributes = array_merge($this->attributes, array_map(
                function () {
                },
                $this->normalizeCastClassResponse($key, $caster->set(
                    $this,
                    $key,
                    $this->{$key},
                    $this->attributes
                ))
            ));
        } else {
            $this->attributes = array_merge(
                $this->attributes,
                $this->normalizeCastClassResponse($key, $caster->set(
                    $this,
                    $key,
                    $value,
                    $this->attributes
                ))
            );
        }

        if ($caster instanceof CastsInboundAttributes || !is_object($value)) {
            unset($this->classCastCache[$key]);
        } else {
            $this->classCastCache[$key] = $value;
        }
    }
 /**
     * Cast the given attribute to JSON.
     *
     * @param string $key
     * @param mixed $value
     * @return string
     */
    protected function castAttributeAsJson($key, $value)
    {
        $value = $this->asJson($value);

        if ($value === false) {
            throw JsonEncodingException::forAttribute(
                $this,
                $key,
                json_last_error_msg()
            );
        }

        return $value;
    }
 /**
     * Set a given JSON attribute on the model.
     *
     * @param string $key
     * @param mixed $value
     * @return $this
     */
    public function fillJsonAttribute($key, $value)
    {
        [$key, $path] = explode('->', $key, 2);

        $this->attributes[$key] = $this->asJson($this->getArrayAttributeWithValue(
            $path,
            $key,
            $value
        ));

        return $this;
    }

二 日期转化及时间格式化

模型会将 created_atupdated_at 字段转换为 Carbon\Carbon 实例,它继承了 PHP 原生的 DateTime 类并提供了各种有用的方法。可以通过设置模型的 $dates 属性来添加其他日期属性。

2.1 原理

调用Model::_get()、Model::_set()时,会判断字段类型,为日期则转换为Carbon\Carbon类对象。可以设置日期格式。

$date为日期类型字段,$dateFormat为日期格式字符串,都在Hyperf\Database\Model\Concerns\HasAttributes中设置,也是由其转换数据类型。

HasAttributes::castAttribute()处理各种字段类型,HasAttributes::asDate()执行日期类型转换,HasAttributes::getDateFormat()获取日期格式。

日期类型默认包括created_at 、updated_at。日期默认格式"Y-m-d H:i:s"。

2.2 测试

 #App1\Model\Article  
 protected $dateFormat = 'Y-m-d H:i';
 public function setTitleAttribute($value) {
        $this->attributes['title'] = $value;
    }
    public function getTitleAttribute($value) {
        return $value;
    }
#App\Controller\TestController
public function testmodifier() {
        $article = Article::firstOrCreate(
            ['title' => 'test4'],
            ['user_id' => 2]
        );
        var_dump($article->toArray());
    }

 测试结果

array(7) {
  ["id"]=>
  int(11)
  ["user_id"]=>
  int(2)
  ["title"]=>
  string(5) "test4"
  ["created_at"]=>
  string(16) "2024-03-22 09:04"
  ["updated_at"]=>
  string(16) "2024-03-22 09:04"
  ["deleted_at"]=>
  NULL
  ["pv_num"]=>
  int(0)
}

 

测试可见 数据库中时间格式还是h:i:s,仅获取的时候是h:i格式。

Model::CREATED_AT、Model::UPDATED_AT使用Carbon::now()获取时间,并没有使用$dateFormat属性。

2.3 源码

#Hyperf\Database\Model\Model
public function __get($key) {
        return $this->getAttribute($key);
    }
public function __set($key, $value) {
        $this->setAttribute($key, $value);
    }
 /**
     * 新增时使用
     *
     * @param \Hyperf\Database\Model\Builder $query
     * @return bool
     */
    protected function performInsert(Builder $query) {
        if ($event = $this->fireModelEvent('creating')) {
            if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) {
                return false;
            }
        }

        // First we'll need to create a fresh query instance and touch the creation and
        // update timestamps on this model, which are maintained by us for developer
        // convenience. After, we will just continue saving these model instances.
        if ($this->usesTimestamps()) {
            $this->updateTimestamps();
        }

        // If the model has an incrementing key, we can use the "insertGetId" method on
        // the query builder, which will give us back the final inserted ID for this
        // table from the database. Not all tables have to be incrementing though.
        $attributes = $this->getAttributes();

        if ($this->getIncrementing()) {
            $this->insertAndSetId($query, $attributes);
        }

        // If the table isn't incrementing we'll simply insert these attributes as they
        // are. These attribute arrays must contain an "id" column previously placed
        // there by the developer as the manually determined key for these models.
        else {
            if (empty($attributes)) {
                return true;
            }

            $query->insert($attributes);
        }

        // We will go ahead and set the exists property to true, so that it is set when
        // the created event is fired, just in case the developer tries to update it
        // during the event. This will allow them to do so and run an update here.
        $this->exists = true;

        $this->wasRecentlyCreated = true;

        $this->fireModelEvent('created');

        return true;
    }
/**
     * 修改时使用
     *
     * @param \Hyperf\Database\Model\Builder $query
     * @return bool
     */
    protected function performUpdate(Builder $query) {
        // If the updating event returns false, we will cancel the update operation so
        // developers can hook Validation systems into their models and cancel this
        // operation if the model does not pass validation. Otherwise, we update.
        if ($event = $this->fireModelEvent('updating')) {
            if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) {
                return false;
            }
        }

        // First we need to create a fresh query instance and touch the creation and
        // update timestamp on the model which are maintained by us for developer
        // convenience. Then we will just continue saving the model instances.
        if ($this->usesTimestamps()) {
            $this->updateTimestamps();
        }

        // Once we have run the update operation, we will fire the "updated" event for
        // this model instance. This will allow developers to hook into these after
        // models are updated, giving them a chance to do any special processing.
        $dirty = $this->getDirty();

        if (count($dirty) > 0) {
            $this->setKeysForSaveQuery($query)->update($dirty);

            $this->syncChanges();

            $this->fireModelEvent('updated');
        }

        return true;
    }
 public function save(array $options = []): bool {
        $this->mergeAttributesFromClassCasts();

        $query = $this->newModelQuery();

        // If the "saving" event returns false we'll bail out of the save and return
        // false, indicating that the save failed. This provides a chance for any
        // listeners to cancel save operations if validations fail or whatever.
        if ($saving = $this->fireModelEvent('saving')) {
            if ($saving instanceof StoppableEventInterface && $saving->isPropagationStopped()) {
                return false;
            }
        }

        // If the model already exists in the database we can just update our record
        // that is already in this database using the current IDs in this "where"
        // clause to only update this model. Otherwise, we'll just insert them.
        if ($this->exists) {
            $saved = $this->isDirty() ? $this->performUpdate($query) : true;
        } else {
            // If the model is brand new, we'll insert it into our database and set the
            // ID attribute on the model to the value of the newly inserted row's ID
            // which is typically an auto-increment value managed by the database.
            $saved = $this->performInsert($query);

            if (!$this->getConnectionName() && $connection = $query->getConnection()) {
                $this->setConnection($connection->getName());
            }
        }

        // If the model is successfully saved, we need to do a few more things once
        // that is done. We will call the "saved" method here to run any actions
        // we need to happen after a model gets successfully saved right here.
        if ($saved) {
            $this->finishSave($options);
        }

        return $saved;
    }
#Hyperf\Database\Model\Concerns\HasAttributes
 /**
     * Set a given attribute on the model.
     *
     * @param string $key
     * @param mixed $value
     */
public function setAttribute($key, $value)
    {
        // First we will check for the presence of a mutator for the set operation
        // which simply lets the developers tweak the attribute as it is set on
        // the model, such as "json_encoding" an listing of data for storage.
        if ($this->hasSetMutator($key)) {
            return $this->setMutatedAttributeValue($key, $value);
        }

        // If an attribute is listed as a "date", we'll convert it from a DateTime
        // instance into a form proper for storage on the database tables using
        // the connection grammar's date format. We will auto set the values.
        if ($value && $this->isDateAttribute($key)) {
            $value = $this->fromDateTime($value);
        }

        if ($this->isClassCastable($key)) {
            $this->setClassCastableAttribute($key, $value);

            return $this;
        }

        if ($this->isJsonCastable($key) && !is_null($value)) {
            $value = $this->castAttributeAsJson($key, $value);
        }

        // If this attribute contains a JSON ->, we'll set the proper value in the
        // attribute's underlying array. This takes care of properly nesting an
        // attribute in the array's value in the case of deeply nested items.
        if (Str::contains($key, '->')) {
            return $this->fillJsonAttribute($key, $value);
        }

        $this->attributes[$key] = $value;

        return $this;
    }
 public function fromDateTime($value)
    {
        return empty($value) ? $value : $this->asDateTime($value)->format(
            $this->getDateFormat()
        );
    }
/**
     * Get an attribute from the model.
     *
     * @param string $key
     */
    public function getAttribute($key)
    {
        if (!$key) {
            return;
        }

        // If the attribute exists in the attribute array or has a "get" mutator we will
        // get the attribute's value. Otherwise, we will proceed as if the developers
        // are asking for a relationship's value. This covers both types of values.
        if (array_key_exists($key, $this->getAttributes())
            || $this->hasGetMutator($key)
            || $this->isClassCastable($key)) {
            return $this->getAttributeValue($key);
        }
        // Here we will determine if the model base class itself contains this given key
        // since we don't want to treat any of those methods as relationships because
        // they are all intended as helper methods and none of these are relations.
        if (method_exists(self::class, $key)) {
            return;
        }
        return $this->getRelationValue($key);
    }
public function getAttributeValue($key)
    {
        return $this->transformModelValue($key, $this->getAttributeFromArray($key));
    }
 protected function transformModelValue($key, $value)
    {
        // If the attribute has a get mutator, we will call that then return what
        // it returns as the value, which is useful for transforming values on
        // retrieval from the model to a form that is more useful for usage.
        if ($this->hasGetMutator($key)) {
            return $this->mutateAttribute($key, $value);
        }

        // If the attribute exists within the cast array, we will convert it to
        // an appropriate native PHP type dependent upon the associated value
        // given with the key in the pair. Dayle made this comment line up.
        if ($this->hasCast($key)) {
            return $this->castAttribute($key, $value);
        }

        // If the attribute is listed as a date, we will convert it to a DateTime
        // instance on retrieval, which makes it quite convenient to work with
        // date fields without having to create a mutator for each property.
        if ($value !== null
            && \in_array($key, $this->getDates(), false)) {
            return $this->asDateTime($value);
        }

        return $value;
    }
 protected function castAttribute($key, $value)
    {
        $castType = $this->getCastType($key);

        if (is_null($value) && in_array($castType, static::$primitiveCastTypes)) {
            return $value;
        }

        switch ($castType) {
            case 'int':
            case 'integer':
                return (int) $value;
            case 'real':
            case 'float':
            case 'double':
                return $this->fromFloat($value);
            case 'decimal':
                return $this->asDecimal($value, explode(':', $this->getCasts()[$key], 2)[1]);
            case 'string':
                return (string) $value;
            case 'bool':
            case 'boolean':
                return (bool) $value;
            case 'object':
                return $this->fromJson($value, true);
            case 'array':
            case 'json':
                return $this->fromJson($value);
            case 'collection':
                return new BaseCollection($this->fromJson($value));
            case 'date':
                return $this->asDate($value);
            case 'datetime':
            case 'custom_datetime':
                return $this->asDateTime($value);
            case 'timestamp':
                return $this->asTimestamp($value);
        }

        if ($this->isClassCastable($key)) {
            return $this->getClassCastableAttributeValue($key, $value);
        }

        return $value;
    }
protected function asDate($value)
    {
        return $this->asDateTime($value)->startOfDay();
    }
protected function asDateTime($value)
    {
        // If this value is already a Carbon instance, we shall just return it as is.
        // This prevents us having to re-instantiate a Carbon instance when we know
        // it already is one, which wouldn't be fulfilled by the DateTime check.
        if ($value instanceof Carbon || $value instanceof CarbonInterface) {
            return Carbon::instance($value);
        }

        // If the value is already a DateTime instance, we will just skip the rest of
        // these checks since they will be a waste of time, and hinder performance
        // when checking the field. We will just return the DateTime right away.
        if ($value instanceof DateTimeInterface) {
            return Carbon::parse(
                $value->format('Y-m-d H:i:s.u'),
                $value->getTimezone()
            );
        }

        // If this value is an integer, we will assume it is a UNIX timestamp's value
        // and format a Carbon object from this timestamp. This allows flexibility
        // when defining your date fields as they might be UNIX timestamps here.
        if (is_numeric($value)) {
            return Carbon::createFromTimestamp($value);
        }

        // If the value is in simply year, month, day format, we will instantiate the
        // Carbon instances from that format. Again, this provides for simple date
        // fields on the database, while still supporting Carbonized conversion.
        if ($this->isStandardDateFormat($value)) {
            return Carbon::instance(Carbon::createFromFormat('Y-m-d', $value)->startOfDay());
        }

        $format = $this->getDateFormat();

        // Finally, we will just assume this date is in the format used by default on
        // the database connection and use that format to create the Carbon object
        // that is returned back out to the developers after we convert it here.
        if (Carbon::hasFormat($value, $format)) {
            return Carbon::createFromFormat($format, $value);
        }

        return Carbon::parse($value);
    }
public function getDateFormat()
    {
        return $this->dateFormat ?: $this->getConnection()->getQueryGrammar()->getDateFormat();
    }
#Hyperf\Database\Grammar
public function getDateFormat()
    {
        return 'Y-m-d H:i:s';
    }
#Hyperf\Database\Model\Concerns\HasTimestamps
protected function updateTimestamps()
    {
        $time = $this->freshTimestamp();

        if (! is_null(static::UPDATED_AT) && ! $this->isDirty(static::UPDATED_AT)) {
            $this->setUpdatedAt($time);
        }

        if (! $this->exists && ! is_null(static::CREATED_AT)
            && ! $this->isDirty(static::CREATED_AT)) {
            $this->setCreatedAt($time);
        }
    }
public function setCreatedAt($value)
    {
        $this->{static::CREATED_AT} = $value;

        return $this;
    }

public function setUpdatedAt($value)
    {
        $this->{static::UPDATED_AT} = $value;

        return $this;
    }
public function freshTimestamp()
    {
        return Carbon::now();
    }

 

#Carbon\Traits\Creator
public function __construct($time = null, $tz = null)
    {
        if ($time instanceof DateTimeInterface) {
            $time = $this->constructTimezoneFromDateTime($time, $tz)->format('Y-m-d H:i:s.u');
        }

        if (is_numeric($time) && (!\is_string($time) || !preg_match('/^\d{1,14}$/', $time))) {
            $time = static::createFromTimestampUTC($time)->format('Y-m-d\TH:i:s.uP');
        }

        // If the class has a test now set and we are trying to create a now()
        // instance then override as required
        $isNow = empty($time) || $time === 'now';

        if (method_exists(static::class, 'hasTestNow') &&
            method_exists(static::class, 'getTestNow') &&
            static::hasTestNow() &&
            ($isNow || static::hasRelativeKeywords($time))
        ) {
            static::mockConstructorParameters($time, $tz);
        }

        // Work-around for PHP bug https://bugs.php.net/bug.php?id=67127
        if (!str_contains((string) .1, '.')) {
            $locale = setlocale(LC_NUMERIC, '0'); // @codeCoverageIgnore
            setlocale(LC_NUMERIC, 'C'); // @codeCoverageIgnore
        }

        try {
            parent::__construct($time ?: 'now', static::safeCreateDateTimeZone($tz) ?: null);
        } catch (Exception $exception) {
            throw new InvalidFormatException($exception->getMessage(), 0, $exception);
        }

        $this->constructedObjectId = spl_object_hash($this);

        if (isset($locale)) {
            setlocale(LC_NUMERIC, $locale); // @codeCoverageIgnore
        }

        self::setLastErrors(parent::getLastErrors());
    }
 public static function now($tz = null)
    {
        return new static(null, $tz);
    }

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

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

相关文章

StarRocks-2.5.13部署安装

1、安装jdk11 tar xf jdk-11.0.16.1_linux-x64_bin.tar.gz mv jdk-11.0.16.1 /data/soft/jdk-11 # 配置在/etc/profile中 export JAVA_HOME/data/soft/jdk-11 export CLASSPATH.:/data/soft/jdk-11/lib export PATH/data/soft/jdk-11/bin:$PATH # 验证jdk [rootdb-public-03 s…

基于ArcGIS的2015-2020辽宁省土地利用变化分析

数据准备 栅格转面 运行ArcToolbox,打开【转换工具】,选择【从栅格转出】里面的【栅格转面工具】,调出面板进行参数设置。输入栅格选择裁剪的2015年中国土地利用遥感监测数据(…

Jupyter R绘图 汉字显示乱码的解决办法

1.Jupyte中,R绘图,汉字显示乱码 2.如何解决? (1)R中安装showtext 登录linux服务器 #R > install.packages(“showtext”) … 出错 (2)退出R,安装freetype-config #apt install libfreetype6-dev 出错 (3)进入R&…

嵌入式Linux 内核启动过程详解(第一阶段:汇编语言部分)

目录 概述 1 简述PC Linux 启动过程 2 嵌入式Linux内核启动流程 2.1 嵌入式Linux内核启动分析 2.2 启动Linux内核前的准备 2.3 启动内核第一阶段流程图 3 嵌入式Linux内核启动分析 3.1 链接文件 vmlinux.lds 3.2 启动文件head.S 3.2 启动文件head-common.S 概述 本文…

2024蓝桥杯每日一题(哈希)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一:星空之夜 试题二:模拟散列表 试题三:字符串哈希 试题四:四数方和 试题五:扫雷 试题一:星空之夜 【题目描述】 夜空深…

【JavaScript 漫游】【041】File 对象、FileList 对象、FileReader 对象

文章简介 本篇文章为【JavaScript 漫游】专栏的第 041 篇文章,主要对浏览器模型中 File 对象、FileList 对象和 FileReader 对象的知识点进行了简记。 File 对象 File 对象代表一个文件,用来读写文件信息。它继承了 Blob 对象,或者说是一种…

Springboot+vue的四川美食分享网站+数据库+报告+免费远程调试

项目介绍: Springbootvue的四川美食分享网站。Javaee项目,springboot vue前后端分离项目 本文设计了一个基于Springbootvue的前后端分离的四川美食分享网站,采用M(model)V(view)C(controller&am…

计算机视觉之三维重建(3)---单视几何

文章目录 一、问题提出二、无穷远点、无穷远线、无穷远平面2.1 2D空间2.2 3D空间 三、影消点和影消线3.1 2D平面上的无穷远点,无穷远线变换3.2 影消点3.3 影消线 四、单视重构 一、问题提出 1. 当摄像机标定后,内部参数 K K K 已知,外部参数…

界面控件DevExpress ASP.NET Ribbon组件 - 完美复刻Office 365体验!

无论用户是喜欢传统工具栏菜单外观、样式,还是想在下一个项目中复制Office 365 web UI,DevExpress ASP.NET都提供了所需要的工具,帮助用户打造更好的应用程序界面。 P.S:DevExpress ASP.NET Web Forms Controls拥有针对Web表单&a…

JavaWeb -- HTTP -- WEB服务器TOMCAT

一.HTTP介绍: HTTP(Hyper Text Protocol) 实际上是一种超文本传输的协议,规定了浏览器跟服务器之间的一些数据传输的规则 例如B/S 对于浏览器的请求,以及相应服务器的响应,都必须依靠这种协议,规范,才能够彼此之间相互 理解 HTTP的协议特点: 1.基于TCP协议: 面向连接 更加安全…

Vscode初建Vue时几个需要注意的问题

首先放图 注意点1.打开文件夹时,可以是VUE2 或者其他,但不能是VUE,会报错 注意点2.终端输入命令“npm init -y" npm init -y -y 的含义:yes的意思,在init的时候省去了敲回车的步骤,生成的默认的packag…

【目标检测】YOLOv9理论解读与代码分析

前言 YOLO这个系列的故事已经很完备了,比如一些Decoupled-Head或者Anchor-Free等大的策略改动已经在YOLOv8固定下来,后面已经估计只有拿一些即插即用的tricks进行小改。 mmdetection框架的作者深度眸也在知乎上对“是否会有YOLOv9”这一观点发表看法&a…

搞了半天blender整动画这么爽,骨骼重定向一回,动作就可以到处套用,和音频对轨也好使

我们搞到了运动数据(可能是bvh文件,也可能是fbx文件)之后,想要让某个静态的模型动起来。 我们假定用的是Tpose的模型(因为我这个bvh文件是Tpose用的,所以为了动作映射不出问题,优先整的这种模型…

C语言——利用冒泡排序模拟实现qsort函数

一.冒泡排序 冒泡排序是C语言中众多排序中的一种。它的排序逻辑为(升序):从第一个元素开始和相邻的比较,如果第一个元素大于第二个元素,则交换,反之不交换;第二个再与第三个元素比较&#xff0…

jsvmp逆向实战X-Bogus篇,算法还原

jsvmp逆向实战X-Bogus篇,算法还原 前言X-Bogus算法逻辑寻找log插桩位置第四步第三步 前言 看过很多大佬关于X-Bogus算法还原的文章,都是通过log插桩,分析日志信息再结合动态调试一步步抽丝剥茧,最终还原算法,但是不同…

第1篇:Mysql数据库表结构导出字段到Excel(一个sheet中)

package com.xx.util;import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.sql.*; import java.io.*;public class DatabaseToExcel {public static void main(String[] args) throws Exception {// 数据库连接配置String u…

基于SpringBoot和HeatMap的全球地震热力图可视化实践

目录 前言 一、关于热力图 1、HeatMap简介 2、属性和方法介绍 二、全球地震热力图反演 1、地震信息查询开发 2、前端地图开发 三、地震带反演成果 1、三大地震带反演 2、地震区域分析 总结 前言 众所周知,全球的地震带主要可以分为三处地震带——环太平洋地…

利用API打造卓越的用户体验

🍎个人博客:个人主页 🏆个人专栏:日常聊聊 ⛳️ 功不唐捐,玉汝于成 目录 正文 1. 数据驱动的设计 2. 功能扩展与整合 3. 实时性与响应性 4. 个性化推荐与定制化服务 结语 我的其他博客 正文 随着数字化时代的…

我的电脑win11系统安装了谷歌浏览器,桌面的快捷方式打不开

安装好浏览器以后双击打不开右键打开文件位置也弹窗报错提示 但是我发现开始栏里面可以打开 说明我的软件应该是没有问题的,研究了一下 我实际的安装目录在:C:\Program Files\Google\Chrome\Application 桌面的快捷方式右键查看属性显示的地址却不对&a…

js生成笛卡尔集合

let arr[[黑, 金, 白],[16G, 32G],[电信, 移动, 联通], ]let listarr.reduce((a, b) > { return a.flatMap(x > b.map(y > [...x, y]))}, [[]] )console.log(list)生成结果