首页 » SEO优化 » PHP数据库模子设计技巧_Thinkphp 模型和数据库数据库架构根本

PHP数据库模子设计技巧_Thinkphp 模型和数据库数据库架构根本

访客 2024-11-16 0

扫一扫用手机浏览

文章目录 [+]

ThinkPHP5.0的数据库设计比较之前版本更加合理,数据访问层划分的更细化,把数据访问工具分成了连接器、查询器、天生器等多个工具,并通过数据库访问入口类统一调用,分工更明确,各司其职,欲知详情且听我逐步道来。

ThinkPHP数据访问层设计示意图:

PHP数据库模子设计技巧_Thinkphp 模型和数据库数据库架构根本

5.1版本的架构略微进行了一些调度,变成:

PHP数据库模子设计技巧_Thinkphp 模型和数据库数据库架构根本
(图片来自网络侵删)

数据库入口类Db

平常我们的数据库操作利用的类库一样平常都是数据库的入口类think\Db。
这个类非常的大略,紧张便是一个connect方法,根据数据库配置参数连接数据库(把稳这里的连接并非真正的连接数据库,只是做好了随时连接的准备事情,只有在实际查询的时候才会真正去连接数据库,是一种惰性连接)并获取到数据库连接工具的实例。

Db类都是静态方法调用,但看起来这个类啥都没实现,那是怎么操作数据库的呢,实在便是封装了数据库操作方法的静态调用(利用__callStatic方法),下面是代码实现:

// 调用驱动类的方法public static function __callStatic($method, $params){ // 自动初始化数据库 return call_user_func_array([self::connect(), $method], $params);}

理论上来说,框架并不依赖Db类,该类的存在只是为了简化数据库抽象层的操作而供应的一个工厂类,否则你就须要单独实例化不同的数据库连接类。
因此,看似可有可无的Db类就成了数据访问层实现的点睛之笔了。

所有的数据库操作都是经由Db类调用,并且Db类是一个静态类,但Db类自身只有一个公共方法connect。

连接器类Connection

顾名思义,连接类的浸染便是连接数据库,也称为连接器。
我们知道,不同的数据库的连接办法和参数都是不同的,连接类便是要办理这个差异问题。

数据库入口类里面实例化的类实在便是对应数据库的连接类,连接类的基类是think\db\Connection。
例如,须要连接Mysql数据库的话,就必须定义一个Mysql连接类(内置由think\db\connector\Mysql类实现,继续了think\db\Connection类),当然详细的连接类名没有固定的规范(例如,MongoDb的连接类便是think\mongo\Connection)。
如果某个数据库的连接扩展类没有继续think\db\Connection,那就意味着所有的数据库底层操作有可能被接管,在个别分外的数据库的扩展中就有类似的实现,例如MongoDb数据库扩展。

数据库连接都是惰性的,只有终极实行SQL的时候才会进行连接。

连接器是数据访问层的根本,基于PHP本身的PDO实现(如果你还不理解PDO,请参考PHP官方手册中PDO部分,不在本书的谈论范畴),连接类的紧张浸染便是连接详细的数据库,以及完成基本的数据库底层操作,包括对分布式、存储过程和事务的完善处理。
而更多的数据操作则交由查询类完成。

框架内置的连接类包括:

数据库 连接类 Mysql think\db\connector\Mysql Pgsql think\db\connector\Pgsql Sqlite think\db\connector\Sqlite Sqlsrv think\db\connector\Sqlsrv

如果是仅仅利用原生SQL查询的话,只须要利用连接类就可以了(通过调用Db类完成)

连接器类的浸染小结:

连接数据库;获取数据表和字段信息;根本查询(原生查询);事务支持;分布式支持;查询器类Query

除了根本的原生查询可以在连接类完成之外,其它的查询操作都是调用查询类的方法,查询类内完成了数据访问层最主要的事情,衔接了连接类和天生类,统一了数据库的查询用法,以是查询类是不须要单独驱动合营的,我们也称之为查询器。
无论采取什么数据库,我们的查询办法是统一的,由于数据访问层核心只有一个唯一的查询类:think\db\Query。

Query类封装了所有的数据库CURD方法的优雅实现,包括链式方法及各种查询,并自动利用了PDO参数绑定(参数自动绑定是在天生器类解析天生SQL时完成),最大程度地保护你的程序避免受数据库注入攻击,查询操作会调用天生类天生对应数据库的SQL语句,然后再调用连接类供应的底层原生查询方法实行终极的数据库查询操作。

所有的数据库查询都利用了PDO的预处理和参数绑定机制。
你所看到的大部分数据库方法都来自于查询类而并非Db类,这一点很关键,也便是说虽然我们始终利用Db类操作数据库,而实际上大部分方法都是由查询器类供应的方法。

天生器类Builder

天生类的浸染是吸收Query类的所有查询参数,并卖力解析天生对应数据库的原生SQL语法,然后返回给Query类进行后续的处理(包括交给连接类进行SQL实行和返回结果处理),也称为(语法)天生器。
天生类的浸染实在便是办理不同的数据库查询语法之间的差异。
查询类实现了统一的查询接口,而天生类卖力数据库底层的查询对接。

天生类一样平常不须要自己调用,而是由查询类自动调用的。
也可以这么理解,天生类和查询类是一体的,事实上它们合起来便是常日我们所说的查询布局器(由于实际的查询操作还是在连接器中实行的)。

常日每一个数据库连接类都会对应一个天生类,框架内置的天生类包括:

数据库 天生类 Mysql think\db\builder\Mysql Pgsql think\db\builder\Pgsql Sqlite think\db\builder\Sqlite Sqlsrv think\db\builder\Sqlsrv

这些天生类都继续了核心供应的天生器基类think\db\Builder,每个天生器类只须要供应差异部分的实现。

数据库配置

数据库的配置参数有很大的学问,也是你节制数据库操作的根本,紧张用于数据库的连接以及查询的干系设置。

数据库的配置参数用于连接类的架构方法,而由于我们并不直接操作连接类,以是,配置参数紧张通过Db类传入并设置到当前的数据库连接类。

数据库配置分为静态配置和动态配置两种办法,静态配置是指在数据库配置文件中进行配置,动态配置是指在Db类或者Query类的connect方法中传入动态的配置参数。

安装好ThinkPHP5之后,默认在application目录下面会有一个database.php文件,这便是运用的数据库配置文件,如果你的模块须要单独的数据库配置文件,那么只须要在模块目录下面创建一个database.php文件即可,并且只须要定义和运用数据库配置文件有差异的部分。

数据库配置文件中配置的是默认的数据库连接配置,如果你有多个数据库连接,额外的数据库连接是在运用配置文件中完成的(参考后面的动态数据库连接)。

├─application │ ├─index │ │ ├─database.php (模块)数据库配置文件│ │ └─ ... │ ├─database.php (运用)数据库配置文件│ └─ ...

我们下面的数据库配置文件都以运用数据库配置文件为例解释。

默认的运用数据库配置文件如下:

return [ // 数据库类型 'type' => 'mysql', // 做事器地址 'hostname' => '127.0.0.1', // 数据库名 'database' => '', // 用户名 'username' => 'root', // 密码 'password' => '', // 端口 'hostport' => '', // 连接dsn 'dsn' => '', // 数据库连接参数 'params' => [], // 数据库编码默认采取utf8 'charset' => 'utf8', // 数据库表前缀 'prefix' => '', // 数据库调试模式 'debug' => true, // 数据库支配办法:0 集中式(单一做事器),1 分布式(主从做事器) 'deploy' => 0, // 数据库读写是否分离 主从式有效 'rw_separate' => false, // 读写分离后 主理事器数量 'master_num' => 1, // 指定从做事器序号 'slave_no' => '', // 是否严格检讨字段是否存在 'fields_strict' => true, // 数据集返回类型 'resultset_type' => 'array', // 自动写入韶光戳字段 'auto_timestamp' => false, // 韶光字段取出后的默认韶光格式 'datetime_format' => 'Y-m-d H:i:s', // 是否须要进行SQL性能剖析 'sql_explain' => false, // Builder类 'builder' => '', // Query类 'query' => '\\think\\db\\Query',];

最关键的参数便是下面几个(其它参数后面会陆续涉及):

参数名 浸染 type 数据库类型或者连接类名 hostname 数据库做事器地址(一样平常是IP地址,默认为127.0.0.1) username 数据库用户名(默认为root) password 数据库用户密码(默认为空) database 利用的数据库名称 charset 数据库编码(默认为utf8)

type参数严格来说实在配置的是连接类名(而不是数据库类型),支持命名空间完全定义,不带命名空间定义的话,默认采取\think\db\connector作为命名空间(内置连接类的命名空间)。
你完备可以在运用中扩展自己的数据库连接类,例如配置为:

// 配置数据库类型(连接类)为自定义'type' => '\app\db\Mysql',

这样就可以自己更换或者扩展一些额外的数据库操作方法。

自定义连接类的时候,请把稳设置数据库配置中的builder参数避免找不到对应天生器类。

ThinkPHP5.0采取PDO来统一操作数据库,而连接类的最关键的浸染便是通过配置连接到数据库,PDO的连接方法参数如下:

PDO::__construct ( 'DSN' ,'用户名','密码','连接参数(数组)' )

数据库的数据源名称(DSN)是最关键的一个参数,连接类卖力把数据库配置参数自动转换为一个有效的DSN数据源名称。
如果你有分外的连接语法需求,则可以通过配置数据库配置文件中的dsn参数来办理,该配置参数的值会直接用于PDO连接,例如:

数据库支持断线重连机制(默认关闭),可以设置(V5.0.6+版本仅支持Mysql数据库,V5.0.9+版本开始支持内置所有数据库):// 连接dsn'dsn' => 'mysql:unix_socket=/tmp/mysql.sock;dbname=demo',

数据库支持断线重连机制(默认关闭),可以设置(V5.0.6+版本仅支持Mysql数据库,V5.0.9+版本开始支持内置所有数据库):// 开启断线重连'break_reconnect' => true,除了DSN数据源名称,PDO的连接参数也可以单独设置,每个连接驱动都有自己的连接参数设置,Mysql连接器内置采取的参数包括如下:

PDO::ATTR_CASE => PDO::CASE_NATURAL,PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,PDO::ATTR_STRINGIFY_FETCHES => false,PDO::ATTR_EMULATE_PREPARES => false,

可以在数据库配置文件中设置params参数,会和内置的连接参数合并,例如:

// 数据库连接参数 'params' => [ // 利用长连接 \PDO::ATTR_PERSISTENT => true, // 数据表字段统一转换为小写 \PDO::ATTR_CASE => \PDO::CASE_LOWER, ],

常用数据库连接参数(params)可以参考PHP在线手册中的以PDO::ATTR_开头的常量。

如何开始查询

在开始学习查询之前,我们首先在demo数据库中创建一个data测试表。

CREATE TABLE IF NOT EXISTS `data`( `id` int(8) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL COMMENT '名称', PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

然后设置数据库配置文件内容为(如果有密码请自行修正):

return [ // 数据库类型 'type' => 'mysql', // 做事器地址 'hostname' => '127.0.0.1', // 数据库名 'database' => 'demo', // 用户名 'username' => 'root', // 密码 'password' => '', // 开启数据库调试 'debug' => true,];

特殊把稳我们在配置中开启了debug参数,表示开启数据库的调试模型,开启后会记录数据库的连接信息和SQL日志,数据库的调试模式和运用的调试模式是两个不同的观点。

配置完数据库连接信息后,我们就可以直策应用Db类进行数据库运行原生SQL操作了,你无需关心数据库的连接操作,系统会自动利用数据库配置参数进行数据库的连接操作。

Db类的方法都是静态调用(不须要去实例化think\Db类),Db类的查询方法有很多(大部分查询都是利用的查询布局器),本章内容暂时只讲两个用于原生查询的方法,包括query(查询操作)和execute(写入操作),更多的查询方法会在查询布局器章节作出详细讲解。

数据库查询的所有示例都须要写到一个掌握器的方法里面,我们现在假设你已经定义了一个下面的掌握器操作方法:

<?phpnamespace app\index\controller;use think\Db;class Index{ public function index() { // 这里是数据库操作的测试代码 // ... return; }}

一样平常来说并不建议在掌握器的操作方法中直接操作数据库Db类,但由于我们还没涉及到模型章节的内容,因此,目前的写法仅为了演示数据库的示例代码。

并且在运用配置文件中开启页面Trace显示: // 运用Trace 'app_trace' => true,开启页面Trace的浸染是为了方便我们查看当前要求的SQL语句信息以及实行韶光(须要开启数据库调试模式后有效)。

然后在index操作方法中添加下面测试代码:

Db::execute('insert into data (id, name) values (1, "hinkphp")');Db::query('select from data where id=1');

对数据表的CURD操作,除了select和存储过程调用利用query方法之外,其它的操作都利用execute方法,这里就不再逐一演示了。

访问页面后,显示空缺,点击右下角的

就可以打开页面Trace信息,切换到SQL一栏,可以看到下面的类似信息

第一条表示数据库的连接信息(连接花费韶光以及连接的DSN),后面的两条就表示当前操作实行的SQL语句,由于我们利用的是原生查询,以是SQL语句和你的代码里面的SQL语句是同等的,每条SQL语句末了会显示该SQL语句的实行花费韶光。

细心的朋友会创造Db类里面并没有query和execute方法,其实在调用Db类的方法(connect方法除外)之前,都会先调用connect方法进行数据库的初始化(前面提过的__callStatic方法),由于connect方法会返回一个数据库连接类的工具实例(根据配置参数实现了单例),以是Db类调用的query和execute方法实在便是连接器类(Connection)的方法,这一点必须理解,否则你很难明得数据库的查询操作。

利用参数绑定

上面的例子是实际开拓中实在并不建议,原则上我们在利用原生查询的时候最好利用参数绑定避免SQL注入,例如:

Db::execute('insert into data (id, name) values (?, ?)',[2,'kancloud']);Db::query('select from data where id=?',[2]);

页面Trace信息中会显示实际运行的SQL语句

也支持命名占位符绑定,例如:

Db::execute('insert into data (id, name) values (:id, :name)',['id'=>3,'name'=>'topthink']);Db::query('select from data where id=:id',['id'=>3]);

参数绑定的变量不须要利用引号

同样显示的实际实行SQL如下:

我们看到查询语句中的id的值是字符串的,由于参数绑定默认都是利用的字符串,如果须要指定为数字类型,可以利用下面的办法:

Db::execute('insert into data (id, name) values (:id, :name)',['id'=>[4,\PDO::PARAM_INT],'name'=>'onethink']);Db::query('select from data where id=:id',['id'=>[4,\PDO::PARAM_INT]]);

这次查看实际的实行SQL会有细微的变革

PDO命名占位绑定不支持一个参数多处绑定,下面的用法会报错:

Db::execute('insert into data (name) values (:name),(:name)',['name'=>'thinkphp']);

该缺点信息表示你的参数绑定参数数量不符。

查询返回值

利用Db类查询数据库的话,query方法的返回值是一个二维数组的数据集,每个元素便是一条记录,例如:

array (size=1) 0 => array (size=5) 'id' => int 8 'name' => string 'thinkphp' (length=8)

比较query方法,execute方法的返回值就比较纯挚,一样平常便是返回影响(包括新增和更新)的记录数,如果没有影响任何记录,则返回值为0,以是千万不要用布尔值来判断execute是否实行成功,事实上,在5.0里面不须要判断是否成功,由于如果发生缺点一定会抛出非常。

动态连接数据库

当你须要利用多个数据库连接的时候,就须要利用connect方法动态切换到其余一个数据库连接,假设存在其余一个数据库test,并且复制data过去更名为test,然后测试下面的示例:

Db::query('select from data where id = 2');Db::connect([ // 数据库类型 'type' => 'mysql', // 做事器地址 'hostname' => '127.0.0.1', // 数据库名 'database' => 'test', // 用户名 'username' => 'root', // 密码 'password' => '', // 开启调试模式 'debug' => true,])->query('select from test where id = 1');Db::query('select from data where id = 3');

页面Trace的显示信息可以看出来利用了两次数据库连接和实行了三次查询,并且数据库连接切换并没有影响默认的查询(第三个查询还是利用的默认数据库配置连接,test数据库中并不存在data表,如果连接的还是第二个数据库连接的话肯定会报错)。

有时候,我们只须要设置一些基本的数据库配置参数,可以简化成一个字符串格式定义(该格式为ThinkPHP利用规范,而不是PDO连接规范,不要和DSN稠浊起来):

Db::connect('mysql://root@127.0.0.1/demo#utf8') ->query('select from data where id = 1');

字符串格式的连接信息规范格式如下:

数据库类型://用户名[:用户密码]@数据库做事器地址[:端口]/数据库名[?参数1=值&参数2=值]#数据库编码

Db类的connect方法会返回一个数据库连接工具实例,相同的连接参数返回的是同一个工具实例,除非你逼迫重新实例化,例如:

Db::connect([ // 数据库类型 'type' => 'mysql', // 做事器地址 'hostname' => '127.0.0.1', // 数据库名 'database' => 'demo', // 用户名 'username' => 'root', // 密码 'password' => '',],true)->query('select from data where id = 1');

这样,每次调用都会重新实例化数据库的连接类。

为了便于统一管理,你可以把数据库配置参数纳入配置文件,例如在运用配置文件中添加:

'db_config' => [ // 数据库类型 'type' => 'mysql', // 做事器地址 'hostname' => '127.0.0.1', // 数据库名 'database' => 'demo', // 用户名 'username' => 'root', // 密码 'password' => '',],

或者利用字符串办法定义

'db_config' => 'mysql://root@127.0.0.1/demo',

上面的db_config配置参数不是在数据库配置文件中定义,而是在运用配置文件或者模块配置文件中定义。

然后,利用下面的办法来动态连接获取切换连接

Db::connect('db_config') ->query('select from data where id=:id', ['id'=>3]);

当connect方法传入的连接参数是字符串并且不包含/等分外符号的话,表示利用的是预定义数据库配置参数。

分布式支持

数据访问层支持分布式数据库,包括读写分离,要启用分布式数据库,须要开启数据库配置文件中的deploy参数:

return [ // 启用分布式数据库 'deploy' => 1, // 数据库类型 'type' => 'mysql', // 做事器地址 'hostname' => '192.168.1.1,192.168.1.2', // 数据库名 'database' => 'demo', // 数据库用户名 'username' => 'root', // 数据库密码 'password' => '', // 数据库连接端口 'hostport' => '',];

启用分布式数据库后,hostname参数是关键,hostname的个数决定了分布式数据库的数量,默认情形下第一个地址便是主理事器。

主从做事器支持设置不同的连接参数,包括:

连接参数 username password hostport database dsn charset

如果主从做事器的上述参数同等的话,只须要设置一个,对付不同的参数,可以分别设置,例如:

return [ // 启用分布式数据库 'deploy' => 1, // 数据库类型 'type' => 'mysql', // 做事器地址 'hostname' => '192.168.1.1,192.168.1.2,192.168.1.3', // 数据库名 'database' => 'demo', // 数据库用户名 'username' => 'root,slave,slave', // 数据库密码 'password' => '123456', // 数据库连接端口 'hostport' => '', // 数据库字符集 'charset' => 'utf8',];

记住,要么相同,要么每个都要设置。

还可以设置分布式数据库的读写是否分离,默认的情形下读写不分离,也便是每台做事器都可以进行读写操作,对付主从式数据库而言,须要设置读写分离,通过下面的设置就可以:

'rw_separate' => true,

在读写分离的情形下,默认第一个数据库配置是主理事器的配置信息,卖力写入数据,如果设置了master_num参数,则可以支持多个主理事器写入(每次随机连接个中一个主理事器)。
其它的地址都是从数据库,卖力读取数据,数量不限定。
每次连接从做事器并且进行读取操作的时候,系统会随机进行在从做事器中选择。
同一个数据库连接的每次要求只会连接一次主理事器和从做事器,如果某次要求的从做事器连接不上,会自动切换到主理事器进行查询操作。

如果不肯望随机读取,或者某种情形下其它从做事器暂时不可用,还可以设置slave_no 指定固定做事器进行读操作,slave_no指定的序号表示hostname中数据库地址的序号,从0开始。

调用查询类或者模型的CURD操作的话,系统会自动判断当前实行的方法是读操作还是写操作并自动连接主从做事器,如果你用的是原生SQL,那么须要把稳系统的默认规则: 写操作必须用数据库的execute方法,读操作必须用数据库的query方法,否则会发生主从读写错乱的情形。

发生下列情形的话,会自动连接主理事器:

利用了数据库的写操作方法(execute/insert/update/delete以及衍生方法);如果调用了数据库事务方法的话,会自动连接主理事器;从做事器连接失落败,会自动连接主理事器;调用了查询布局器的lock方法;调用了查询布局器的master方法

主从数据库的数据同步事情不在框架实现,须要数据库考虑自身的同步或者复制机制。
如果在大数据量或者分外的情形下写入数据后可能会存在同步延迟的情形,可以调用master()方法进行主库查询操作。

在实际生产环境中,很多云主机的数据库分布式实现机制和本地开拓会有所差异,但常日会采下面用两种办法:

第一种:供应了写IP和读IP(一样平常是虚拟IP),进行数据库的读写分离操作; 第二种:始终保持同一个IP连接数据库,内部会进行读写分离IP调度(阿里云便是采取该办法)。

存储过程调用

数据访问层支持存储过程调用,调用数据库存储过程利用下面的方法:

$resultSet = Db::query('call procedure_name');foreach ($resultSet as $result) {}

存储过程返回的是一个数据集,如果你的存储过程不须要返回任何的数据,那么也可以利用execute方法:

Db::execute('call procedure_name');

存储过程可以支持输入和输出参数,以及进行参数绑定操作。

$resultSet = Db::query('call procedure_name(:in_param1,:in_param2,:out_param)', [ 'in_param1' => $param1, 'in_param2' => [$param2, PDO::PARAM_INT], 'out_param' => [$outParam, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 4000],]);

输出参数的绑定必须额外利用PDO::PARAM_INPUT_OUTPUT,并且可以和输入参数公用一个参数。

无论存储过程内部做了什么操作,每次存储过程调用仅仅被当成一次查询。

数据库事务

5.0对数据库事务的封装更为完善,事务的支持由连接器类来完成,但查询器类中也对事务进行了封装调用,不过我们仍旧只须要通过Db类便可完成事务操作。

利用事务处理的话,须要数据库引擎支持事务处理。
比如MySQL的MyISAM类型不支持事务处理,须要利用InnoDB引擎。

最大略的方法是利用transaction方法操作数据库事务,会自动掌握事务处理,当发生任何非常会自动回滚,例如:

Db::transaction(function () { Db::table('user')->find(1); Db::table('user')->where('id', 1)->save(['name' => 'thinkphp']); Db::table('user')->delete(1);});

也可以手动掌握事务,例如:

// 启动事务Db::startTrans();try{ Db::table('user')->find(1); Db::table('user')->where('id',1)->save(['name'=>'thinkphp']); Db::table('user')->delete(1); // 提交事务 Db::commit(); } catch (\Exception $e) { // 回滚事务 Db::rollback();}

在事务操作的时候,确保你的数据库连接是同一个,否则事务会失落效,V5.0.9版本之前的db助手函数都是默认重新链接数据库的,请不要在事务中利用。

总结

通过本章的学习,你该当理解了5.0的数据库架构设计和数据库抽象访问层的组成,以及如何配置数据库信息和利用根本的原生查询,节制了用Db类的connect方法切换不同的数据库连接,基本理解了存储过程及事务的用法。
后面一章,我们会先来理解下数据库的创建和数据迁移,之后就会进入真正的数据库查询的学习了。

作者:寒冬夜行人_51a4链接:https://www.jianshu.com/p/4926734b954c著作权归作者所有。
商业转载请联系作者得到授权,非商业转载请注明出处。

标签:

相关文章

今日头条算法岗三面算法工程师的面试之路

大数据和人工智能技术逐渐成为各行各业的热门话题。今日头条作为中国领先的资讯平台,其算法岗位一直是求职者争相竞逐的焦点。本文将针对今...

SEO优化 2025-01-31 阅读0 评论0

今日头条算法如何打造个化内容推荐

在移动互联网时代,信息爆炸已成为常态。如何在海量信息中找到自己感兴趣的内容,成为了一个亟待解决的问题。今日头条作为一款备受瞩目的新...

SEO优化 2025-01-31 阅读0 评论0

今日头条算法推荐其弊端与反思

算法推荐已经成为各大平台的核心竞争力。今日头条作为国内领先的资讯平台,凭借其强大的算法推荐系统,吸引了大量用户。在享受算法带来的便...

SEO优化 2025-01-31 阅读0 评论0

今日头条算法思维导图信息推荐的奥秘

信息传播速度越来越快,用户对信息的需求也越来越多样化。今日头条作为一款备受关注的新闻资讯平台,其背后的算法推荐机制一直是业界关注的...

SEO优化 2025-01-31 阅读0 评论0