当前位置: 首页 > news >正文

hyperf 二十八 修改器 一

教程: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\Modeluse Hyperf\Database\Model\Model as BaseModel;class Model extends BaseModel
{use HasContainer;use HasRepository;
}
#Hyperf\Database\Model\Modelabstract 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=67127if (!str_contains((string) .1, '.')) {$locale = setlocale(LC_NUMERIC, '0'); // @codeCoverageIgnoresetlocale(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);}

相关文章:

hyperf 二十八 修改器 一

教程:Hyperf 一 修改器和访问器 根据教程,可设置相关函数,如set属性名Attribute()、get属性名Attribute(),设置和获取属性。这在thinkphp中也常见。 修改器:set属性名Attribute();访问器:get属性名Attri…...

ubuntu20.04安裝輸入法

文章目录 前言一、操作過程1、安装fcitx-googlepinyin2、配置language support 前言 參考文獻 一、操作過程 1、安装fcitx-googlepinyin sudo apt-get install fcitx-googlepinyin2、配置language support 第一次點擊進去,會讓你安裝 點擊ctrl和空格切換中英文…...

2024年【熔化焊接与热切割】考试报名及熔化焊接与热切割找解析

题库来源:安全生产模拟考试一点通公众号小程序 熔化焊接与热切割考试报名考前必练!安全生产模拟考试一点通每个月更新熔化焊接与热切割找解析题目及答案!多做几遍,其实通过熔化焊接与热切割实操考试视频很简单。 1、【单选题】 下…...

聚类分析|基于层次的聚类方法及其Python实现

聚类分析|基于层次的聚类方法及其Python实现 0. 基于层次的聚类方法1. 簇间距离度量方法1.1 最小距离1.2 最大距离1.3 平均距离1.4 中心法1.5 离差平方和 2. 基于层次的聚类算法2.1 凝聚(Agglomerative)2.3 分裂(Divisive) 3. 基于…...

前端实现导出xlsx功能

1.安装xlsx插件 npm install xlsx 2.示例 import XLSX from xlsx;// 示例数据 const data [[Name, Age, Country],[Alice, 25, USA],[Bob, 30, Canada],[Charlie, 28, UK] ];// 创建一个 Workbook 对象 const wb XLSX.utils.book_new(); const ws XLSX.utils.aoa_to_sheet…...

算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1)

💕"我们好像在池塘的水底,从一个月亮走向另一个月亮。"💕 作者:Mylvzi 文章主要内容:算法系列–动态规划–⼦数组、⼦串系列(数组中连续的⼀段)(1) 大家好,今天为大家带来的是算法系…...

RESTful架构

RESTful架构中的URI设计与传统的URL设计有一些区别。让我通过具体的例子来解释一下: 传统的URL设计通常将操作和资源混合在一起,例如: 获取所有图书:GET /getBooks获取特定图书:GET /getBookById/{id}创建新图书&…...

从IO操作与多线程的思考到Redis-6.0

IO操作->线程阻塞->释放CPU资源->多线程技术提升CPU利用率 在没有涉及磁盘操作和网络请求的程序中,通常不会出现线程等待状态。线程等待状态通常是由于线程需要等待某些事件的发生,比如I/O操作完成、网络请求返回等。如果程序只是进行计算或者简…...

MNN介绍、安装和编译

MNN是一个轻量级的深度学习推理框架,由阿里巴巴公司开发。它支持多种硬件平台,包括CPU、GPU和NPU,并提供高效、高性能的深度学习模型推理服务。下面是MNN的安装和编译步骤: 下载MNN源代码 在MNN的GitHub页面(https://g…...

【计算机图形学】AO-Grasp: Articulated Object Grasp Generation

对AO-Grasp: Articulated Object Grasp Generation的简单理解 文章目录 1. 做的事情2. AO-Grasp数据集2.1 抓取参数化和label标准2.2 语义和几何感知的抓取采样 3. AO-Grasp抓取预测3.1 预测抓取点3.2 抓取方向预测 4. 总结 1. 做的事情 引入AO-Grasp,grasp propo…...

「媒体宣传」财经类媒体邀约资源有哪些?-51媒体

传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 财经类媒体邀约资源包括但不限于以下几类: 商业杂志和报纸:可以邀请如《财经》、《新财富》、《经济观察报》等主流商业杂志和报纸。这些媒体通常具有较强的品牌影…...

学习资料记录

http://interview.wzcu.com/Golang/%E4%BB%A3%E7%A0%81%E8%80%83%E9%A2%98.html map底层 https://zhuanlan.zhihu.com/p/616979764 go修养 https://www.yuque.com/aceld/golang/ga6pb1#4b19dba5 https://golang.dbwu.tech/performance/map_pre_alloc/ https://juejin.cn/pos…...

数据结构进阶篇 之 【二叉树】详细概念讲解(带你认识何为二叉树及其性质)

有朋自远方来,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,鞭数十,驱之别院 一、二叉树 1、二叉树的概念 1.1 二叉树中组分构成名词概念 1.2 二叉树的结构概念 1.3 特殊的二叉树 2、二叉树的存储结构 …...

vue.js制作学习计划表案例

通俗易懂,完成“学习计划表”用于对学习计划进行管理,包括对学习计划进行添加、删除、修改等操作。 一. 初始页面效果展示 二.添加学习计划页面效果展示 三.修改学习计划完成状态的页面效果展示 四.删除学习计划 当学习计划处于“已完成”状态时&…...

nginx localtion 匹配规则

1、语法规则 语法规则:location[|~|^~*|^~]/uri/{… } 表示精确匹配,这个优先级也是最高的 ^~ 表示 uri 以某个常规字符串开头,理解为匹配 url 路径即可。 nginx 不对 url 做编码,因此请求为 /image/20%/aa,可以被规则^~ /imag…...

Git:分布式版本控制系统

目录 Git的特点和功能常见的功能和对应的命令 Git的特点和功能 Git是一个分布式版本控制系统,用于跟踪和管理项目的代码变更。它是由Linus Torvalds在2005年创建的,旨在管理Linux内核的开发。Git具有以下特点和功能: 分布式版本控制&#xf…...

[STL]priority_queue类及反向迭代器的模拟实现

🪐🪐🪐欢迎来到程序员餐厅💫💫💫 今日主菜: priority_queue类及反向迭代器 主厨:邪王真眼 主厨的主页:Chef‘s blog 所属专栏:c大冒险 向着c&…...

vue2 脚手架

安装 文档:https://cli.vuejs.org/zh/ 第一步:全局安装(仅第一次执行) npm install -g vue/cli 或 yarn global add vue/cli 备注:如果出现下载缓慢:请配置npm 淘宝镜像: npm config set regis…...

【OpenStack】OpenStack实战之开篇

目录 那么,OpenStack是什么?云又是什么?关于容器应用程序OpenStack如何适配其中?如何设置它?如何学会使用它?推荐超级课程: Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战我的整个职业生涯到目前为止一直围绕着为离线或隔离网络设计和开发应用程…...

Python实现WebSocket通信

WebSocket是一种在单个TCP连接上进行全双工通信的协议,位于 OSI 模型的应用层。 与传统的HTTP请求-响应模型不同,WebSocket的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,实现实时性和互动性…...

接口测试中缓存处理策略

在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

python打卡day49

知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

C++使用 new 来创建动态数组

问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...