PHP
Drupal
What is Drupal
Drupal is a free and open-source content management system (CMS) written in PHP and distributed under the GNU General Public License. It is used as a back-end system for at least 2.3% of all websites worldwide ranging from personal blogs to corporate, political, and government sites including whitehouse.gov and data.gov.uk.
Installation
Composer
> composer create-project drupal/recommended-project drupal
With a specific version
$ composer create-project drupal/recommended-project:9.3.12 my_site_name
Settings
Redis
Install drupal/redis
$ composer require drupal/redis
Edit sites/default/settings.php
/**
* Redis configuration.
*/
$settings['cache']['default'] = 'cache.backend.redis';
$settings['redis.connection']['interface'] = 'PhpRedis'; // or 'Predis'.
$settings['redis.connection']['host'] = '127.0.0.1';
$settings['redis.connection']['port'] = '6379';
$settings['redis.connection']['base'] = 0;
$settings['container_yamls'][] = 'modules/contrib/redis/example.services.yml';
$settings['container_yamls'][] = 'modules/contrib/redis/redis.services.yml';
$settings['cache_prefix'] = 'tonylabs';
// Bypass the cache bootstrap for anonymous users (optional).
$settings['cache']['bins']['bootstrap'] = 'cache.backend.chainedfast';
$settings['cache']['bins']['discovery'] = 'cache.backend.chainedfast';
// Use Redis for specific cache bins if needed.
$settings['cache']['bins']['render'] = 'cache.backend.redis';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.redis';
// Use Redis for Session Storage
$settings['redis.session']['client'] = 'PhpRedis'; // Or 'Predis'.
$settings['redis.session']['host'] = '127.0.0.1';
$settings['redis.session']['port'] = 6379;
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379');
// Disable Drupal’s Default Internal Page Cache
$settings['cache']['bins']['page'] = 'cache.backend.redis';
PhpRedis 和 Predis 的区别
语言与实现
- PhpRedis:
- 它是用 C 语言编写的 PHP 扩展
- 作为一个本地扩展,它直接与 Redis 进行低级别的交互,因此性能更快、效率更高
- Predis:
- 它是用 PHP 编写的 PHP 库
- 因为是纯 PHP 实现,安装更简单(通过 Composer 即可),但性能不如 PhpRedis,因为它是在较高级别的 PHP 中运行。
性能
- PhpRedis:
- 通常比 Predis 更快,因为它是编译的 PHP 扩展,能够直接在系统级别运行
- 适合高性能应用或大型系统
- Predis:
- 由于是用 PHP 实现的,通常比 PhpRedis 慢。但对于不需要极高性能的应用,仍然适用
安装
- PhpRedis:
- 作为本地 PHP 扩展,必须通过包管理器(如 apt、yum 或 brew)安装,或者手动编译
- 需要服务器级别的访问权限,因此在共享主机环境中可能无法使用
- Predis:
- 只需要通过 Composer 安装,使用非常方便,不需要服务器级权限或额外的系统库
兼容性
- PhpRedis:
- 作为 C 扩展,在不同平台上的安装会有一些限制,比如 Windows、macOS 和 Linux 的安装步骤可能不同
- 由 Redis 官方维护,确保与 Redis 的功能和改进保持同步
- Predis:
- 由于完全是用 PHP 编写的,具有跨平台兼容性,适用于任何支持 PHP 的环境,兼容性更强
- 作为第三方库,可能对最新的 Redis 功能支持较慢
持久性与维护
- PhpRedis:
- 作为 Redis 项目的一部分,官方支持和定期更新
- 由 Redis 官方维护,适合长期使用的生产环境
- Predis:
- 虽然 Predis 曾是 PHP 开发者中的热门选择,但其 维护速度曾有所减慢。不过,最近推出了 Predis v2 版本,提高了对 Redis 6+ 的支持,但 PhpRedis 依然是现代应用的首选。
功能支持
- PhpRedis:
- 支持 所有 Redis 的功能,包括发布/订阅、Lua 脚本等高级功能
- Predis:
- Predis 支持大多数 Redis 功能,但由于依赖 PHP,有时对最新功能的支持可能滞后
使用场景
- PhpRedis:
- 适用于高性能应用、企业级项目或大量使用 Redis 的生产环境,因为它提供更好的速度和资源管理
- 需要对托管环境有更多控制,因此更常见于开发者拥有 root 权限或控制服务器配置的环境中
- Predis:
- 更适合 小型应用,共享主机环境或需要简化安装和跨平台兼容性的场景
- 适合托管环境受限,或无法安装扩展的项目
集群支持
- PhpRedis:
- 原生支持 Redis 集群,是分布式数据系统中 Redis 集群的最佳选择
- Predis:
- Predis 也支持集群,但由于是 PHP 实现,处理大规模集群时性能不如 PhpRedis
持久性
- PhpRedis:
- 作为 Redis 的官方维护项目,拥有更高的持久性和更强的支持
- Predis:
- 虽然它曾被广泛使用和支持,但其更新依赖于外部开发者
How to make a custom module
File Structure
module_name.info.yml
创建扩展模块首先创建 info.yml 文件,用来声明该模块的基本信息
name: 'Module Name'
type: module
description: 'A custom module for Drupal'
core_version_requirement: ^10 || ^11
package: 'Custom'
version: '1.0'
dependencies:
- drupal:node
module_name.module
包含模块的函数方法和功能实现
'Stores athletics events.',
'fields' => [
'event_id' => [
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => '',
],
],
'primary key' => ['event_id'],
];
$schema['athletics_teams'] = [
'description' => 'Stores athletics teams.',
'fields' => [
'team_id' => [
'type' => 'serial',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => '',
],
'name' => [
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'description' => '',
],
'description' => [
'type' => 'text',
'size' => 'medium',
'not null' => false,
'description' => '',
]
],
'primary key' => ['team_id'],
];
$database = \Drupal::database();
$schema_manager = $database->schema();
foreach ($schema as $table_name => $definition) {
if (!$schema_manager->tableExists($table_name)) {
$schema_manager->createTable($table_name, $definition);
}
}
}
/**
* Implements hook_uninstall().
*/
function athletics_uninstall()
{
$database = \Drupal::database();
$schema_manager = $database->schema();
if ($schema_manager->tableExists('athletics_events')) {
$schema_manager->dropTable('athletics_events');
}
if ($schema_manager->tableExists('athletics_teams')) {
$schema_manager->dropTable('athletics_teams');
}
}
/**
* Implements hook_theme().
*
* Register a module or theme's theme implementations.
* The implementations declared by this hook specify how a
* particular render array is to be rendered as HTML.
*
* See: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21theme.api.php/function/hook_theme
*
* If you change this method, clear theme registry and routing
* table 'drush cc theme-registry' and 'drush cc router'.
*/
function athletics_theme($existing, $type, $theme, $path)
{
return [
// Name of the theme hook. This is used in the controller to trigger the hook.
'event_index' => [
'render element' => 'children',
// If no template name is defined here,
// it defaults to the name of the theme hook
'template' => 'event/index',
// Optionally define path to Twig template files.
// Defaults to the module's ./templates/ directory.
'path' => $path . '/templates',
// Optionally define variables that will be passed to the Twig
// template and set default values for them.
'variables' => [
'variable1' => 'Yet another default text.',
'variable2' => 0,
'variable3' => [0, 0, 0],
],
],
];
}
module_name.routing.yml
定义模块的路由
hello_world.content:
path: '/hello'
defaults:
_controller: '\Drupal\hello_world\Controller\HelloController::content'
_title: 'Hello World'
requirements:
_permission: 'access content'
module_name.settings.yml
定义模块的配置, settings.yml
文件通常存储在模块工程文件夹下的 config/install/module_name.settings.yml
# Configuration settings for the Hello World module.
# This file is used to store the module's configuration settings.
# The settings are stored in the 'config' table and can be overridden
# by settings in the 'config_override' table.
# The settings are exported to the 'config/install' directory when the
# module is installed and can be imported from there.
# An example configuration setting.
# This setting is a simple text field.
# The key is the name of the setting.
# The value is the default value of the setting.
# The 'type' key is the data type of the setting.
# The 'label' key is the human-readable name of the setting.
# The 'description' key is a description of the setting.
# The 'required' key is a boolean value that determines if the setting is required.
# The 'default_value' key is the default value of the setting.
# The 'dependencies' key is an array of module dependencies.
# The 'module' key is the name of the module that provides the setting.
# The 'locked' key is a boolean value that determines if the setting is locked.
# The 'schema' key is an array of schema information for the setting.
module_name.links.menu.yml
hello_world.admin:
title: 'Hello module settings'
description: 'example of how to make an admin settings page link'
parent: system.admin_config_development
route_name: hello_world.content
weight: 100
node.type.example_type.yml
Reference URL to an external site.
如果开发的新模块中需要用到一种新的内容类型,类似 Structure 中的 Article, Post 等等,在目录 module_name/config/install 目录下放置 node.type.example_type.yml文件,可以在 node.type.example_type.yml 中定义其属性:
type: example_mytype
name: Example
description: 'Use example content to get to Drupal 8 development better.'
help: ''
new_revision: false
display_submitted: true
preview_mode: 1
status: true
langcode: en
dependencies:
module:
- example
enforced:
module:
- example