Technical Documentation: lizhipay/acg-faka
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
法律声明
本商城程序基于 MIT 协议开源,并且完全免费。该程序的初衷是为开发者提供学习和研究的机会。未取得合法资质,严禁将本程序用于任何商业用途,尤其是禁止利用本程序搭建平台进行商品销售。
用户在使用或学习本程序时,必须严格遵守法律法规。我们提倡依法行事,尊重法律,坚守法律,避免对社会产生不良影响。
使用本程序即表示您已充分理解并同意本法律声明的所有内容。
广告
🚀 ARM AI — GPT / Claude / Gemini / Grok Token 服务平台,超低倍率、余额长期有效并支持无理由退款。立即体验:https://ai.arm.moe/
在线演示
| 地址 | 账号 | 密码 | |
|---|---|---|---|
| 前台 | https://demo.faka.wiki | 为了明天美好而战斗 | 123456 |
| 后台 | https://demo.faka.wiki/admin | [email protected] | 123456 |
功能一览
- 商品与发货:卡密自动发货、手动发货(可开启「付款即发货」)、卡密预选(买家自选卡号,可单独加价)、种类与 SKU 规格、批发价、限时秒杀、优惠券、限购、强制登录购买、自定义下单控件、邮件通知。
- 价格与会员:游客价与会员价分开设置,会员等级、商户等级完全自定义,每个商品都能按会员等级单独定价。
- 支付:支付网关全部插件化,几乎任何支付渠道都能接入;内置余额支付与在线充值。
- 分站:会员可以开通自己的分站并绑定独立域名,自行上架商品,也可以代售主站商品。
- 推广分成:会员等级即代理等级,推广人赚取买家实付金额与自身等级价之间的差价。
- 店铺对接:在后台直接对接其他店铺的商品,用余额自动进货、自动发货。
- 应用商店:在后台安装插件与模板;核心程序可一键在线升级。
- 多语言与多币种:内置简体中文、繁体中文、English、日本語,可自定义站点货币与汇率。
- 安全:两步验证与通行密钥(Passkey)登录、后台安全入口、内容安全策略(CSP)等多层防护。
- 界面:PC 与手机端完整适配,应用商店里有多套风格各异的模板。
- 二次开发:80 多个 Hook 埋点,插件可以接管下单、发货、支付等流程。比如:游戏道具购买后即时发到玩家背包、商业软件自动授权与余额充值、论坛 / 社区 VIP 自动开通。
安装
方式一:Docker(推荐)
docker run -d --name faka -p 80:80 -v acg_data:/data --restart unless-stopped ghcr.io/lizhipay/acg-faka:latest镜像自带 MariaDB 与 Redis,启动后打开 http://服务器IP 即可进入安装向导,数据库信息已经自动填好。站点的全部数据都在 /data 卷里,务必挂载。需要使用独立的 MySQL 时,请参考 Docker 安装文档。
方式二:宝塔面板 / 手动安装
| 项目 | 要求 |
|---|---|
| PHP | 8.0 及以上(推荐 8.2) |
| MySQL | 5.7 及以上(MariaDB 10.3+ 亦可) |
| PHP 扩展 | gd、curl、pdo、pdo_mysql、date、json、session、zip、bcmath |
| 伪静态 | 必须配置,见下方 |
获取源码:
composer create-project lizhipay/acg-faka,或从 GitHub、faka.wiki/download.php 下载压缩包。配置伪静态:Apache 无需配置,根目录已自带
.htaccess;Nginx 请把下面整段粘进站点配置(宝塔:网站 → 伪静态)。nginxif ($uri ~* "^/(?!(?-i:index\.php)(/|$)).*\.php(/|$)") { return 404; } location ~* ^/(runtime|kernel|config|vendor)/ { return 404; } location ~ (^|/)(runtime|\.acgcache)(/|$) { return 404; } location ~ /\.(?!well-known) { return 404; } location ~* \.(log|sql|sqlite|db|db-wal|db-shm|bak|old|save|orig|swp|swo|tmp|ini|lock|key|pem|crt|cer|der|p12|pfx|p8|keystore|jks|asc|gpg|ppk|env|secret)$ { return 404; } location ~* (~|composer\.(json|lock)|package(-lock)?\.json)$ { return 404; } location / { try_files $uri $uri/ /index.php?s=$uri&$args; }请整段复制,不要只抄最后的
location /:前面几条负责挡住日志、配置、密钥等不该被访问的文件。IIS 规则见伪静态文档。确认
config、runtime、kernel/Install、assets/cache目录可写,然后访问网站首页,按安装向导完成安装。后台地址:
https://你的域名/admin
更详细的步骤(含 Windows)见安装文档。
升级
后台左下角显示当前版本号,点击即可检查新版本并一键在线升级,Docker 部署同样适用。升级前请先备份数据库;手动升级的方法见升级文档。
二次开发
插件、支付插件、Hook 与 API 对接的说明见开发者文档。
交流与反馈
- Telegram:https://t.me/mcyofficial
- QQ 群:868709021
- 问题反馈:GitHub Issues
开源协议
Overview (`docker/README.md`)
Docker 部署
最简单:一个容器
docker run -d --name acg-faka -p 80:80 -v acg_data:/data --restart unless-stopped ghcr.io/lizhipay/acg-faka:latest就这一条。 镜像自带 MariaDB 和 Redis,数据库密码首次启动随机生成,
打开 http://服务器IP 直接进安装向导 —— 数据库那一步已经替你填好,只需要设个管理员账号。
宝塔 / 1Panel 的「创建容器」里也是同样三件事:镜像填 ghcr.io/lizhipay/acg-faka:latest、
端口映射 主机端口 → 容器 80、目录映射一个卷到 /data。
⚠️ 容器内部端口是 80,不是 8080。映射错了浏览器打不开。
⚠️
/data一定要挂出来。站点的数据库、配置、上传文件、插件、模板全在里面,
不挂的话容器一删数据就没了。
要独立的 MySQL / Redis:用 compose
docker compose up -d同样不需要 .env、不需要改文件。这种方式下内置的 MariaDB/Redis 不会启动,
app 容器只跑 nginx + php-fpm,数据库走独立的 mysql 服务。
改端口:ACG_HTTP_PORT=8081 docker compose up -d
这套编排有什么
| 服务 | 镜像 | 说明 |
|---|---|---|
app |
本仓库构建 | nginx + php-fpm 8.2(+ 单容器模式下的 MariaDB/Redis),supervisord 托管,对外只开 80 |
mysql |
mysql:5.7 |
只在内网可达,不往宿主机发布端口 |
redis |
redis:7.2-alpine |
PHP 会话存储(acg_sess: 前缀,db 1) |
secrets-init |
一次性任务 | 首次启动生成随机数据库密码,之后退出 |
密码是怎么来的
镜像里不带任何默认密码。首次 up 时 secrets-init 会往 acg_secrets 卷里写两串
32 位随机密码(root 一串、应用一串,权限 600),MySQL 通过 MYSQL_*_PASSWORD_FILE
读它,安装向导则由服务端读出来直接用。
密码不会渲染进安装页面的 HTML —— 页面把密码栏留空、提交时带一个use_builtin=1 标记,服务端自己去环境变量里取。
要自己看一眼的话:
docker compose exec mysql cat /secrets/mysql_root想用外部数据库
安装向导第二步点「改用其它数据库」,手填即可,内置的那套就不会被用到。
也可以直接把 compose 里的 mysql 服务和 ACG_DB_* 环境变量删掉。
为什么是 nginx 而不是 Apache
整个程序只有 index.php 一个 web 入口,其余请求都靠 ?s= 路由。所以 nginx 配置里
只放行了它一个,其它 .php 一律返回 404 —— 上传目录里就算真被塞进一个 .php
也执行不了。config/、kernel/、runtime/、vendor/ 和点开头的文件同样直接 404。
伪静态规则随镜像发布(等价于仓库里的 .htaccess),用户不需要配置任何东西。
反向代理(Caddy / Traefik / CDN / 宝塔)放在前面时,X-Forwarded-Proto 和X-Forwarded-For 会被正确转成 $_SERVER['HTTPS'] 与真实来访 IP —— 只信任私有网段,
公网伪造的头不生效。
线程管理器插件
在应用商店装好插件后,进容器执行一次(只需一次,二进制会落在数据卷里):
docker compose exec app ./app/Plugin/ThreadManager/service.sh install
# 单容器:docker exec -it acg-faka ./app/Plugin/ThreadManager/service.sh install之后不用再管 —— 容器每次启动都会自动把它的守护进程交给 supervisord 拉起,
不需要 service.sh start。
GitHub 直连不稳导致下载不完整时,脚本会自动换镜像源重试;还是不行就手动指定:
TM_MIRRORS="https://ghfast.top/" ./app/Plugin/ThreadManager/service.sh install
线程管理器(如果你装了)
镜像会自动接管它:容器启动时若检测到 app/Plugin/ThreadManager/swoole-cli,
就把守护进程注册成 supervisord 的程序,和 nginx / php-fpm 一个待遇 ——
容器起来自动拉起、崩溃自动重启、docker stop 时按 stop_timeout 优雅收尾。
注意:托管是在容器启动时登记的,所以插件装好、二进制下完之后要
重启一次容器才会生效(docker restart <容器名>)。在那之前 service.sh start
起的进程照常能用,只是活不过容器重建。
el9 系宿主机的 xz 坑
在 RHEL 9 / AlmaLinux 9 / Rocky 9(内核 5.14.x.el9)上,容器里任何 xz 操作都会报:
xz: Failed to enable the sandbox原因是这类内核回移 Landlock 时版本号谎报(landlock_create_ruleset 查询返回 ABI 6,
实际建规则集却 EINVAL),而 xz 5.6+ 把沙箱失败当致命错误。跟下载的包无关,
包是好的。线程管理器 1.0.7 起会在这种情况下自动改用 python3 的 lzma 解包,无需干预。
已知限制
默认 PHP 8.2(Debian bookworm,仍在支持期)。需要贴合旧线上环境时可以降版本:
bashdocker compose build --build-arg PHP_VERSION=8.0 app⚠ 但 PHP 8.0 / 8.1 已停止安全维护,它们的 Debian bullseye 底座也整体进了归档 ——
构建时会自动改用archive.debian.org,代价是镜像里的系统包(包括 nginx、openssl)
拿不到任何新的安全更新。挂公网的站点不建议这么用。MySQL 5.7 官方只发 amd64 镜像。ARM 机器(Apple Silicon / Ampere / Graviton)
会通过 qemu 模拟运行 —— 能跑,但导入数据那一步明显偏慢。想要原生性能就把
compose 里的mysql服务换成mariadb:10.6并删掉platform:那行。
持久化
站点里所有会被写入的目录(配置、运行时、上传、插件、支付、模板、安装锁)在镜像里
都软链到 /data,挂这一个卷就全保住了。单容器模式下数据库和 Redis 的数据也在/data/mysql、/data/redis。
compose 方式下是 acg_data(站点)+ acg_mysql + acg_redis + acg_secrets(密码)。
常用命令
docker compose logs -f app # 看日志(访问日志只由 nginx 出,不重复)
docker compose restart app # 重启
docker compose down # 停止(数据保留)
docker compose down -v # 停止并清空所有数据,回到全新状态Overview (`vendor/doctrine/inflector/README.md`)
Doctrine Inflector
Doctrine Inflector is a small library that can perform string manipulations
with regard to uppercase/lowercase and singular/plural forms of words.
Overview (`vendor/ezyang/htmlpurifier/README.md`)
HTML Purifier [](https://github.com/ezyang/htmlpurifier/actions/workflows/ci.yml)
HTML Purifier is an HTML filtering solution that uses a unique combination
of robust whitelists and aggressive parsing to ensure that not only are
XSS attacks thwarted, but the resulting HTML is standards compliant.
HTML Purifier is oriented towards richly formatted documents from
untrusted sources that require CSS and a full tag-set. This library can
be configured to accept a more restrictive set of tags, but it won't be
as efficient as more bare-bones parsers. It will, however, do the job
right, which may be more important.
Places to go:
- See INSTALL for a quick installation guide
- See docs/ for developer-oriented documentation, code examples and
an in-depth installation guide. - See WYSIWYG for information on editors like TinyMCE and FCKeditor
HTML Purifier can be found on the web at: http://htmlpurifier.org/
Installation
Package available on Composer.
If you're using Composer to manage dependencies, you can use
$ composer require ezyang/htmlpurifierOverview (`vendor/firebase/php-jwt/README.md`)
PHP-JWT
A simple library to encode and decode JSON Web Tokens (JWT) in PHP, conforming to RFC 7519.
Installation
Use composer to manage your dependencies and download PHP-JWT:
composer require firebase/php-jwtOptionally, install the paragonie/sodium_compat package from composer if your
php env does not have libsodium installed:
composer require paragonie/sodium_compatExample
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$key = 'example_key';
$payload = [
'iss' => 'http://example.org',
'aud' => 'http://example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
/**
* IMPORTANT:
* You must specify supported algorithms for your application. See
* https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40
* for a list of spec-compliant algorithms.
*/
$jwt = JWT::encode($payload, $key, 'HS256');
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
print_r($decoded);
// Pass a stdClass in as the third parameter to get the decoded header values
$headers = new stdClass();
$decoded = JWT::decode($jwt, new Key($key, 'HS256'), $headers);
print_r($headers);
/*
NOTE: This will now be an object instead of an associative array. To get
an associative array, you will need to cast it as such:
*/
$decoded_array = (array) $decoded;
/**
* You can add a leeway to account for when there is a clock skew times between
* the signing and verifying servers. It is recommended that this leeway should
* not be bigger than a few minutes.
*
* Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef
*/
JWT::$leeway = 60; // $leeway in seconds
$decoded = JWT::decode($jwt, new Key($key, 'HS256'));Example encode/decode headers
Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by
this library. This is because without verifying the JWT, the header values could have been tampered with.
Any value pulled from an unverified header should be treated as if it could be any string sent in from an
attacker. If this is something you still want to do in your application for whatever reason, it's possible to
decode the header values manually simply by calling json_decode and base64_decode on the JWT
header part:
use Firebase\JWT\JWT;
$key = 'example_key';
$payload = [
'iss' => 'http://example.org',
'aud' => 'http://example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
$headers = [
'x-forwarded-for' => 'www.google.com'
];
// Encode headers in the JWT string
$jwt = JWT::encode($payload, $key, 'HS256', null, $headers);
// Decode headers from the JWT string WITHOUT validation
// **IMPORTANT**: This operation is vulnerable to attacks, as the JWT has not yet been verified.
// These headers could be any value sent by an attacker.
list($headersB64, $payloadB64, $sig) = explode('.', $jwt);
$decoded = json_decode(base64_decode($headersB64), true);
print_r($decoded);Example with RS256 (openssl)
/* Detailed source-code truncated for AI context efficiency. */Example with a passphrase
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
// Your passphrase
$passphrase = '[YOUR_PASSPHRASE]';
// Your private key file with passphrase
// Can be generated with "ssh-keygen -t rsa -m pem"
$privateKeyFile = '/path/to/key-with-passphrase.pem';
// Create a private key of type "resource"
$privateKey = openssl_pkey_get_private(
file_get_contents($privateKeyFile),
$passphrase
);
$payload = [
'iss' => 'example.org',
'aud' => 'example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
$jwt = JWT::encode($payload, $privateKey, 'RS256');
echo "Encode:\n" . print_r($jwt, true) . "\n";
// Get public key from the private key, or pull from from a file.
$publicKey = openssl_pkey_get_details($privateKey)['key'];
$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";Example with EdDSA (libsodium and Ed25519 signature)
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
// Public and private keys are expected to be Base64 encoded. The last
// non-empty line is used so that keys can be generated with
// sodium_crypto_sign_keypair(). The secret keys generated by other tools may
// need to be adjusted to match the input expected by libsodium.
$keyPair = sodium_crypto_sign_keypair();
$privateKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
$publicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
$payload = [
'iss' => 'example.org',
'aud' => 'example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
$jwt = JWT::encode($payload, $privateKey, 'EdDSA');
echo "Encode:\n" . print_r($jwt, true) . "\n";
$decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA'));
echo "Decode:\n" . print_r((array) $decoded, true) . "\n";Example with multiple keys
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
// Example RSA keys from previous example
// $privateKey1 = '...';
// $publicKey1 = '...';
// Example EdDSA keys from previous example
// $privateKey2 = '...';
// $publicKey2 = '...';
$payload = [
'iss' => 'example.org',
'aud' => 'example.com',
'iat' => 1356999524,
'nbf' => 1357000000
];
$jwt1 = JWT::encode($payload, $privateKey1, 'RS256', 'kid1');
$jwt2 = JWT::encode($payload, $privateKey2, 'EdDSA', 'kid2');
echo "Encode 1:\n" . print_r($jwt1, true) . "\n";
echo "Encode 2:\n" . print_r($jwt2, true) . "\n";
$keys = [
'kid1' => new Key($publicKey1, 'RS256'),
'kid2' => new Key($publicKey2, 'EdDSA'),
];
$decoded1 = JWT::decode($jwt1, $keys);
$decoded2 = JWT::decode($jwt2, $keys);
echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n";
echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n";Using JWKs
use Firebase\JWT\JWK;
use Firebase\JWT\JWT;
// Set of keys. The "keys" key is required. For example, the JSON response to
// this endpoint: https://www.gstatic.com/iap/verify/public_key-jwk
$jwks = ['keys' => []];
// JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key
// objects. Pass this as the second parameter to JWT::decode.
JWT::decode($jwt, JWK::parseKeySet($jwks));Using Cached Key Sets
The CachedKeySet class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI.
This has the following advantages:
- The results are cached for performance.
- If an unrecognized key is requested, the cache is refreshed, to accomodate for key rotation.
- If rate limiting is enabled, the JWKS URI will not make more than 10 requests a second.
use Firebase\JWT\CachedKeySet;
use Firebase\JWT\JWT;
// The URI for the JWKS you wish to cache the results from
$jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk';
// Create an HTTP client (can be any PSR-7 compatible HTTP client)
$httpClient = new GuzzleHttp\Client();
// Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory)
$httpFactory = new GuzzleHttp\Psr\HttpFactory();
// Create a cache item pool (can be any PSR-6 compatible cache item pool)
$cacheItemPool = Phpfastcache\CacheManager::getInstance('files');
$keySet = new CachedKeySet(
$jwksUri,
$httpClient,
$httpFactory,
$cacheItemPool,
null, // $expiresAfter int seconds to set the JWKS to expire
true // $rateLimit true to enable rate limit of 10 RPS on lookup of invalid keys
);
$jwt = 'eyJhbGci...'; // Some JWT signed by a key from the $jwkUri above
$decoded = JWT::decode($jwt, $keySet);Miscellaneous
Exception Handling
When a call to JWT::decode is invalid, it will throw one of the following exceptions:
use Firebase\JWT\JWT;
use Firebase\JWT\SignatureInvalidException;
use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;
use DomainException;
use InvalidArgumentException;
use UnexpectedValueException;
try {
$decoded = JWT::decode($jwt, $keys);
} catch (InvalidArgumentException $e) {
// provided key/key-array is empty or malformed.
} catch (DomainException $e) {
// provided algorithm is unsupported OR
// provided key is invalid OR
// unknown error thrown in openSSL or libsodium OR
// libsodium is required but not available.
} catch (SignatureInvalidException $e) {
// provided JWT signature verification failed.
} catch (BeforeValidException $e) {
// provided JWT is trying to be used before "nbf" claim OR
// provided JWT is trying to be used before "iat" claim.
} catch (ExpiredException $e) {
// provided JWT is trying to be used after "exp" claim.
} catch (UnexpectedValueException $e) {
// provided JWT is malformed OR
// provided JWT is missing an algorithm / using an unsupported algorithm OR
// provided JWT algorithm does not match provided key OR
// provided key ID in key/key-array is empty or invalid.
}All exceptions in the Firebase\JWT namespace extend UnexpectedValueException, and can be simplified
like this:
use Firebase\JWT\JWT;
use UnexpectedValueException;
try {
$decoded = JWT::decode($jwt, $keys);
} catch (LogicException $e) {
// errors having to do with environmental setup or malformed JWT Keys
} catch (UnexpectedValueException $e) {
// errors having to do with JWT signature and claims
}Casting to array
The return value of JWT::decode is the generic PHP object stdClass. If you'd like to handle with arrays
instead, you can do the following:
// return type is stdClass
$decoded = JWT::decode($jwt, $keys);
// cast to array
$decoded = json_decode(json_encode($decoded), true);Tests
Run the tests using phpunit:
$ pear install PHPUnit
$ phpunit --configuration phpunit.xml.dist
PHPUnit 3.7.10 by Sebastian Bergmann.
.....
Time: 0 seconds, Memory: 2.50Mb
OK (5 tests, 5 assertions)New Lines in private keys
If your private key contains \n characters, be sure to wrap it in double quotes ""
and not single quotes '' in order to properly interpret the escaped characters.
License
Overview (`vendor/guzzlehttp/guzzle/README.md`)
Guzzle, PHP HTTP client
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and
trivial to integrate with web services.
- Simple interface for building query strings, POST requests, streaming large
uploads, streaming large downloads, using HTTP cookies, uploading JSON data,
etc... - Can send both synchronous and asynchronous requests using the same interface.
- Uses PSR-7 interfaces for requests, responses, and streams. This allows you
to utilize other PSR-7 compatible libraries with Guzzle. - Supports PSR-18 allowing interoperability between other PSR-18 HTTP Clients.
- Abstracts away the underlying HTTP transport, allowing you to write
environment and transport agnostic code; i.e., no hard dependency on cURL,
PHP streams, sockets, or non-blocking event loops. - Middleware system allows you to augment and compose client behavior.
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
echo $response->getStatusCode(); // 200
echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'
echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}'
// Send an asynchronous request.
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) {
echo 'I completed! ' . $response->getBody();
});
$promise->wait();Help and docs
We use GitHub issues only to discuss bugs and new features. For support please refer to:
- Documentation
- Stack Overflow
- #guzzle channel on PHP-HTTP Slack
- Gitter
Installing Guzzle
The recommended way to install Guzzle is through
Composer.
composer require guzzlehttp/guzzleVersion Guidance
| Version | Status | Packagist | Namespace | Repo | Docs | PSR-7 | PHP Version |
|---|---|---|---|---|---|---|---|
| 3.x | EOL | guzzle/guzzle |
Guzzle |
v3 | v3 | No | >=5.3.3,<7.0 |
| 4.x | EOL | guzzlehttp/guzzle |
GuzzleHttp |
v4 | N/A | No | >=5.4,<7.0 |
| 5.x | EOL | guzzlehttp/guzzle |
GuzzleHttp |
v5 | v5 | No | >=5.4,<7.4 |
| 6.x | Security fixes | guzzlehttp/guzzle |
GuzzleHttp |
v6 | v6 | Yes | >=5.5,<8.0 |
| 7.x | Latest | guzzlehttp/guzzle |
GuzzleHttp |
v7 | v7 | Yes | >=7.2.5,<8.2 |
Security
If you discover a security vulnerability within this package, please send an email to [email protected]. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see Security Policy for more information.
License
Guzzle is made available under the MIT License (MIT). Please see License File for more information.
For Enterprise
Available as part of the Tidelift Subscription
The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.
Overview (`vendor/guzzlehttp/promises/README.md`)
Guzzle Promises
Promises/A+ implementation that handles promise
chaining and resolution iteratively, allowing for "infinite" promise chaining
while keeping the stack size constant. Read this blog post
for a general introduction to promises.
Features
- Promises/A+ implementation.
- Promise resolution and chaining is handled iteratively, allowing for
"infinite" promise chaining. - Promises have a synchronous
waitmethod. - Promises can be cancelled.
- Works with any object that has a
thenfunction. - C# style async/await coroutine promises using
GuzzleHttp\Promise\Coroutine::of().
Quick Start
A promise represents the eventual result of an asynchronous operation. The
primary way of interacting with a promise is through its then method, which
registers callbacks to receive either a promise's eventual value or the reason
why the promise cannot be fulfilled.
Callbacks
Callbacks are registered with the then method by providing an optional$onFulfilled followed by an optional $onRejected function.
use GuzzleHttp\Promise\Promise;
$promise = new Promise();
$promise->then(
// $onFulfilled
function ($value) {
echo 'The promise was fulfilled.';
},
// $onRejected
function ($reason) {
echo 'The promise was rejected.';
}
);Resolving a promise means that you either fulfill a promise with a value or
reject a promise with a reason. Resolving a promise triggers callbacks
registered with the promise's then method. These callbacks are triggered
only once and in the order in which they were added.
Resolving a Promise
Promises are fulfilled using the resolve($value) method. Resolving a promise
with any value other than a GuzzleHttp\Promise\RejectedPromise will trigger
all of the onFulfilled callbacks (resolving a promise with a rejected promise
will reject the promise and trigger the $onRejected callbacks).
use GuzzleHttp\Promise\Promise;
$promise = new Promise();
$promise
->then(function ($value) {
// Return a value and don't break the chain
return "Hello, " . $value;
})
// This then is executed after the first then and receives the value
// returned from the first then.
->then(function ($value) {
echo $value;
});
// Resolving the promise triggers the $onFulfilled callbacks and outputs
// "Hello, reader."
$promise->resolve('reader.');Promise Forwarding
Promises can be chained one after the other. Each then in the chain is a new
promise. The return value of a promise is what's forwarded to the next
promise in the chain. Returning a promise in a then callback will cause the
subsequent promises in the chain to only be fulfilled when the returned promise
has been fulfilled. The next promise in the chain will be invoked with the
resolved value of the promise.
use GuzzleHttp\Promise\Promise;
$promise = new Promise();
$nextPromise = new Promise();
$promise
->then(function ($value) use ($nextPromise) {
echo $value;
return $nextPromise;
})
->then(function ($value) {
echo $value;
});
// Triggers the first callback and outputs "A"
$promise->resolve('A');
// Triggers the second callback and outputs "B"
$nextPromise->resolve('B');Promise Rejection
When a promise is rejected, the $onRejected callbacks are invoked with the
rejection reason.
use GuzzleHttp\Promise\Promise;
$promise = new Promise();
$promise->then(null, function ($reason) {
echo $reason;
});
$promise->reject('Error!');
// Outputs "Error!"Rejection Forwarding
If an exception is thrown in an $onRejected callback, subsequent$onRejected callbacks are invoked with the thrown exception as the reason.
use GuzzleHttp\Promise\Promise;
$promise = new Promise();
$promise->then(null, function ($reason) {
throw new Exception($reason);
})->then(null, function ($reason) {
assert($reason->getMessage() === 'Error!');
});
$promise->reject('Error!');You can also forward a rejection down the promise chain by returning aGuzzleHttp\Promise\RejectedPromise in either an $onFulfilled or$onRejected callback.
use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Promise\RejectedPromise;
$promise = new Promise();
$promise->then(null, function ($reason) {
return new RejectedPromise($reason);
})->then(null, function ($reason) {
assert($reason === 'Error!');
});
$promise->reject('Error!');If an exception is not thrown in a $onRejected callback and the callback
does not return a rejected promise, downstream $onFulfilled callbacks are
invoked using the value returned from the $onRejected callback.
use GuzzleHttp\Promise\Promise;
$promise = new Promise();
$promise
->then(null, function ($reason) {
return "It's ok";
})
->then(function ($value) {
assert($value === "It's ok");
});
$promise->reject('Error!');Synchronous Wait
You can synchronously force promises to complete using a promise's wait
method. When creating a promise, you can provide a wait function that is used
to synchronously force a promise to complete. When a wait function is invoked
it is expected to deliver a value to the promise or reject the promise. If the
wait function does not deliver a value, then an exception is thrown. The wait
function provided to a promise constructor is invoked when the wait function
of the promise is called.
$promise = new Promise(function () use (&$promise) {
$promise->resolve('foo');
});
// Calling wait will return the value of the promise.
echo $promise->wait(); // outputs "foo"If an exception is encountered while invoking the wait function of a promise,
the promise is rejected with the exception and the exception is thrown.
$promise = new Promise(function () use (&$promise) {
throw new Exception('foo');
});
$promise->wait(); // throws the exception.Calling wait on a promise that has been fulfilled will not trigger the wait
function. It will simply return the previously resolved value.
$promise = new Promise(function () { die('this is not called!'); });
$promise->resolve('foo');
echo $promise->wait(); // outputs "foo"Calling wait on a promise that has been rejected will throw an exception. If
the rejection reason is an instance of \Exception the reason is thrown.
Otherwise, a GuzzleHttp\Promise\RejectionException is thrown and the reason
can be obtained by calling the getReason method of the exception.
$promise = new Promise();
$promise->reject('foo');
$promise->wait();PHP Fatal error: Uncaught exception 'GuzzleHttp\Promise\RejectionException' with message 'The promise was rejected with value: foo'
Unwrapping a Promise
When synchronously waiting on a promise, you are joining the state of the
promise into the current state of execution (i.e., return the value of the
promise if it was fulfilled or throw an exception if it was rejected). This is
called "unwrapping" the promise. Waiting on a promise will by default unwrap
the promise state.
You can force a promise to resolve and not unwrap the state of the promise
by passing false to the first argument of the wait function:
$promise = new Promise();
$promise->reject('foo');
// This will not throw an exception. It simply ensures the promise has
// been resolved.
$promise->wait(false);When unwrapping a promise, the resolved value of the promise will be waited
upon until the unwrapped value is not a promise. This means that if you resolve
promise A with a promise B and unwrap promise A, the value returned by the
wait function will be the value delivered to promise B.
Note: when you do not unwrap the promise, no value is returned.
Cancellation
You can cancel a promise that has not yet been fulfilled using the cancel()
method of a promise. When creating a promise you can provide an optional
cancel function that when invoked cancels the action of computing a resolution
of the promise.
API
Promise
When creating a promise object, you can provide an optional $waitFn and$cancelFn. $waitFn is a function that is invoked with no arguments and is
expected to resolve the promise. $cancelFn is a function with no arguments
that is expected to cancel the computation of a promise. It is invoked when thecancel() method of a promise is called.
use GuzzleHttp\Promise\Promise;
$promise = new Promise(
function () use (&$promise) {
$promise->resolve('waited');
},
function () {
// do something that will cancel the promise computation (e.g., close
// a socket, cancel a database query, etc...)
}
);
assert('waited' === $promise->wait());A promise has the following methods:
then(callable $onFulfilled, callable $onRejected) : PromiseInterfaceAppends fulfillment and rejection handlers to the promise, and returns a new promise resolving to the return value of the called handler.
otherwise(callable $onRejected) : PromiseInterfaceAppends a rejection handler callback to the promise, and returns a new promise resolving to the return value of the callback if it is called, or to its original fulfillment value if the promise is instead fulfilled.
wait($unwrap = true) : mixedSynchronously waits on the promise to complete.
$unwrapcontrols whether or not the value of the promise is returned for a
fulfilled promise or if an exception is thrown if the promise is rejected.
This is set totrueby default.cancel()Attempts to cancel the promise if possible. The promise being cancelled and
the parent most ancestor that has not yet been resolved will also be
cancelled. Any promises waiting on the cancelled promise to resolve will also
be cancelled.getState() : stringReturns the state of the promise. One of
pending,fulfilled, orrejected.resolve($value)Fulfills the promise with the given
$value.reject($reason)Rejects the promise with the given
$reason.
FulfilledPromise
A fulfilled promise can be created to represent a promise that has been
fulfilled.
use GuzzleHttp\Promise\FulfilledPromise;
$promise = new FulfilledPromise('value');
// Fulfilled callbacks are immediately invoked.
$promise->then(function ($value) {
echo $value;
});RejectedPromise
A rejected promise can be created to represent a promise that has been
rejected.
use GuzzleHttp\Promise\RejectedPromise;
$promise = new RejectedPromise('Error');
// Rejected callbacks are immediately invoked.
$promise->then(null, function ($reason) {
echo $reason;
});Promise Interoperability
This library works with foreign promises that have a then method. This means
you can use Guzzle promises with React promises
for example. When a foreign promise is returned inside of a then method
callback, promise resolution will occur recursively.
// Create a React promise
$deferred = new React\Promise\Deferred();
$reactPromise = $deferred->promise();
// Create a Guzzle promise that is fulfilled with a React promise.
$guzzlePromise = new GuzzleHttp\Promise\Promise();
$guzzlePromise->then(function ($value) use ($reactPromise) {
// Do something something with the value...
// Return the React promise
return $reactPromise;
});Please note that wait and cancel chaining is no longer possible when forwarding
a foreign promise. You will need to wrap a third-party promise with a Guzzle
promise in order to utilize wait and cancel functions with foreign promises.
Event Loop Integration
In order to keep the stack size constant, Guzzle promises are resolved
asynchronously using a task queue. When waiting on promises synchronously, the
task queue will be automatically run to ensure that the blocking promise and
any forwarded promises are resolved. When using promises asynchronously in an
event loop, you will need to run the task queue on each tick of the loop. If
you do not run the task queue, then promises will not be resolved.
You can run the task queue using the run() method of the global task queue
instance.
// Get the global task queue
$queue = GuzzleHttp\Promise\Utils::queue();
$queue->run();For example, you could use Guzzle promises with React using a periodic timer:
$loop = React\EventLoop\Factory::create();
$loop->addPeriodicTimer(0, [$queue, 'run']);TODO: Perhaps adding a futureTick() on each tick would be faster?
Implementation Notes
Promise Resolution and Chaining is Handled Iteratively
By shuffling pending handlers from one owner to another, promises are
resolved iteratively, allowing for "infinite" then chaining.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Promise\Promise;
$parent = new Promise();
$p = $parent;
for ($i = 0; $i < 1000; $i++) {
$p = $p->then(function ($v) {
// The stack size remains constant (a good thing)
echo xdebug_get_stack_depth() . ', ';
return $v + 1;
});
}
$parent->resolve(0);
var_dump($p->wait()); // int(1000)When a promise is fulfilled or rejected with a non-promise value, the promise
then takes ownership of the handlers of each child promise and delivers values
down the chain without using recursion.
When a promise is resolved with another promise, the original promise transfers
all of its pending handlers to the new promise. When the new promise is
eventually resolved, all of the pending handlers are delivered the forwarded
value.
A Promise is the Deferred
Some promise libraries implement promises using a deferred object to represent
a computation and a promise object to represent the delivery of the result of
the computation. This is a nice separation of computation and delivery because
consumers of the promise cannot modify the value that will be eventually
delivered.
One side effect of being able to implement promise resolution and chaining
iteratively is that you need to be able for one promise to reach into the state
of another promise to shuffle around ownership of handlers. In order to achieve
this without making the handlers of a promise publicly mutable, a promise is
also the deferred value, allowing promises of the same parent class to reach
into and modify the private properties of promises of the same type. While this
does allow consumers of the value to modify the resolution or rejection of the
deferred, it is a small price to pay for keeping the stack size constant.
$promise = new Promise();
$promise->then(function ($value) { echo $value; });
// The promise is the deferred value, so you can deliver a value to it.
$promise->resolve('foo');
// prints "foo"Upgrading from Function API
A static API was first introduced in 1.4.0, in order to mitigate problems with
functions conflicting between global and local copies of the package. The
function API will be removed in 2.0.0. A migration table has been provided here
for your convenience:
| Original Function | Replacement Method |
|---|---|
queue |
Utils::queue |
task |
Utils::task |
promise_for |
Create::promiseFor |
rejection_for |
Create::rejectionFor |
exception_for |
Create::exceptionFor |
iter_for |
Create::iterFor |
inspect |
Utils::inspect |
inspect_all |
Utils::inspectAll |
unwrap |
Utils::unwrap |
all |
Utils::all |
some |
Utils::some |
any |
Utils::any |
settle |
Utils::settle |
each |
Each::of |
each_limit |
Each::ofLimit |
each_limit_all |
Each::ofLimitAll |
!is_fulfilled |
Is::pending |
is_fulfilled |
Is::fulfilled |
is_rejected |
Is::rejected |
is_settled |
Is::settled |
coroutine |
Coroutine::of |
Security
If you discover a security vulnerability within this package, please send an email to [email protected]. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see Security Policy for more information.
License
Guzzle is made available under the MIT License (MIT). Please see License File for more information.
For Enterprise
Available as part of the Tidelift Subscription
The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.
Overview (`vendor/guzzlehttp/psr7/README.md`)
PSR-7 Message Implementation
This repository contains a full PSR-7
message implementation, several stream decorators, and some helpful
functionality like query string parsing.
Stream implementation
This package comes with a number of stream implementations and stream
decorators.
AppendStream
GuzzleHttp\Psr7\AppendStream
Reads from multiple streams, one after the other.
use GuzzleHttp\Psr7;
$a = Psr7\Utils::streamFor('abc, ');
$b = Psr7\Utils::streamFor('123.');
$composed = new Psr7\AppendStream([$a, $b]);
$composed->addStream(Psr7\Utils::streamFor(' Above all listen to me'));
echo $composed; // abc, 123. Above all listen to me.BufferStream
GuzzleHttp\Psr7\BufferStream
Provides a buffer stream that can be written to fill a buffer, and read
from to remove bytes from the buffer.
This stream returns a "hwm" metadata value that tells upstream consumers
what the configured high water mark of the stream is, or the maximum
preferred size of the buffer.
use GuzzleHttp\Psr7;
// When more than 1024 bytes are in the buffer, it will begin returning
// false to writes. This is an indication that writers should slow down.
$buffer = new Psr7\BufferStream(1024);CachingStream
The CachingStream is used to allow seeking over previously read bytes on
non-seekable streams. This can be useful when transferring a non-seekable
entity body fails due to needing to rewind the stream (for example, resulting
from a redirect). Data that is read from the remote stream will be buffered in
a PHP temp stream so that previously read bytes are cached first in memory,
then on disk.
use GuzzleHttp\Psr7;
$original = Psr7\Utils::streamFor(fopen('http://www.google.com', 'r'));
$stream = new Psr7\CachingStream($original);
$stream->read(1024);
echo $stream->tell();
// 1024
$stream->seek(0);
echo $stream->tell();
// 0DroppingStream
GuzzleHttp\Psr7\DroppingStream
Stream decorator that begins dropping data once the size of the underlying
stream becomes too full.
use GuzzleHttp\Psr7;
// Create an empty stream
$stream = Psr7\Utils::streamFor();
// Start dropping data when the stream has more than 10 bytes
$dropping = new Psr7\DroppingStream($stream, 10);
$dropping->write('01234567890123456789');
echo $stream; // 0123456789FnStream
GuzzleHttp\Psr7\FnStream
Compose stream implementations based on a hash of functions.
Allows for easy testing and extension of a provided stream without needing
to create a concrete class for a simple extension point.
use GuzzleHttp\Psr7;
$stream = Psr7\Utils::streamFor('hi');
$fnStream = Psr7\FnStream::decorate($stream, [
'rewind' => function () use ($stream) {
echo 'About to rewind - ';
$stream->rewind();
echo 'rewound!';
}
]);
$fnStream->rewind();
// Outputs: About to rewind - rewound!InflateStream
GuzzleHttp\Psr7\InflateStream
Uses PHP's zlib.inflate filter to inflate zlib (HTTP deflate, RFC1950) or gzipped (RFC1952) content.
This stream decorator converts the provided stream to a PHP stream resource,
then appends the zlib.inflate filter. The stream is then converted back
to a Guzzle stream resource to be used as a Guzzle stream.
LazyOpenStream
GuzzleHttp\Psr7\LazyOpenStream
Lazily reads or writes to a file that is opened only after an IO operation
take place on the stream.
use GuzzleHttp\Psr7;
$stream = new Psr7\LazyOpenStream('/path/to/file', 'r');
// The file has not yet been opened...
echo $stream->read(10);
// The file is opened and read from only when needed.LimitStream
GuzzleHttp\Psr7\LimitStream
LimitStream can be used to read a subset or slice of an existing stream object.
This can be useful for breaking a large file into smaller pieces to be sent in
chunks (e.g. Amazon S3's multipart upload API).
use GuzzleHttp\Psr7;
$original = Psr7\Utils::streamFor(fopen('/tmp/test.txt', 'r+'));
echo $original->getSize();
// >>> 1048576
// Limit the size of the body to 1024 bytes and start reading from byte 2048
$stream = new Psr7\LimitStream($original, 1024, 2048);
echo $stream->getSize();
// >>> 1024
echo $stream->tell();
// >>> 0MultipartStream
GuzzleHttp\Psr7\MultipartStream
Stream that when read returns bytes for a streaming multipart or
multipart/form-data stream.
NoSeekStream
GuzzleHttp\Psr7\NoSeekStream
NoSeekStream wraps a stream and does not allow seeking.
use GuzzleHttp\Psr7;
$original = Psr7\Utils::streamFor('foo');
$noSeek = new Psr7\NoSeekStream($original);
echo $noSeek->read(3);
// foo
var_export($noSeek->isSeekable());
// false
$noSeek->seek(0);
var_export($noSeek->read(3));
// NULLPumpStream
GuzzleHttp\Psr7\PumpStream
Provides a read only stream that pumps data from a PHP callable.
When invoking the provided callable, the PumpStream will pass the amount of
data requested to read to the callable. The callable can choose to ignore
this value and return fewer or more bytes than requested. Any extra data
returned by the provided callable is buffered internally until drained using
the read() function of the PumpStream. The provided callable MUST return
false when there is no more data to read.
Implementing stream decorators
Creating a stream decorator is very easy thanks to theGuzzleHttp\Psr7\StreamDecoratorTrait. This trait provides methods that
implement Psr\Http\Message\StreamInterface by proxying to an underlying
stream. Just use the StreamDecoratorTrait and implement your custom
methods.
For example, let's say we wanted to call a specific function each time the last
byte is read from a stream. This could be implemented by overriding theread() method.
use Psr\Http\Message\StreamInterface;
use GuzzleHttp\Psr7\StreamDecoratorTrait;
class EofCallbackStream implements StreamInterface
{
use StreamDecoratorTrait;
private $callback;
public function __construct(StreamInterface $stream, callable $cb)
{
$this->stream = $stream;
$this->callback = $cb;
}
public function read($length)
{
$result = $this->stream->read($length);
// Invoke the callback when EOF is hit.
if ($this->eof()) {
call_user_func($this->callback);
}
return $result;
}
}This decorator could be added to any existing stream and used like so:
use GuzzleHttp\Psr7;
$original = Psr7\Utils::streamFor('foo');
$eofStream = new EofCallbackStream($original, function () {
echo 'EOF!';
});
$eofStream->read(2);
$eofStream->read(1);
// echoes "EOF!"
$eofStream->seek(0);
$eofStream->read(3);
// echoes "EOF!"PHP StreamWrapper
You can use the GuzzleHttp\Psr7\StreamWrapper class if you need to use a
PSR-7 stream as a PHP stream resource.
Use the GuzzleHttp\Psr7\StreamWrapper::getResource() method to create a PHP
stream from a PSR-7 stream.
use GuzzleHttp\Psr7\StreamWrapper;
$stream = GuzzleHttp\Psr7\Utils::streamFor('hello!');
$resource = StreamWrapper::getResource($stream);
echo fread($resource, 6); // outputs hello!Static API
There are various static methods available under the GuzzleHttp\Psr7 namespace.
`GuzzleHttp\Psr7\Message::toString`
public static function toString(MessageInterface $message): string
Returns the string representation of an HTTP message.
$request = new GuzzleHttp\Psr7\Request('GET', 'http://example.com');
echo GuzzleHttp\Psr7\Message::toString($request);`GuzzleHttp\Psr7\Message::bodySummary`
public static function bodySummary(MessageInterface $message, int $truncateAt = 120): string|null
Get a short summary of the message body.
Will return null if the response is not printable.
`GuzzleHttp\Psr7\Message::rewindBody`
public static function rewindBody(MessageInterface $message): void
Attempts to rewind a message body and throws an exception on failure.
The body of the message will only be rewound if a call to tell()
returns a value other than 0.
`GuzzleHttp\Psr7\Message::parseMessage`
public static function parseMessage(string $message): array
Parses an HTTP message into an associative array.
The array contains the "start-line" key containing the start line of
the message, "headers" key containing an associative array of header
array values, and a "body" key containing the body of the message.
`GuzzleHttp\Psr7\Message::parseRequestUri`
public static function parseRequestUri(string $path, array $headers): string
Constructs a URI for an HTTP request message.
`GuzzleHttp\Psr7\Message::parseRequest`
public static function parseRequest(string $message): Request
Parses a request message string into a request object.
`GuzzleHttp\Psr7\Message::parseResponse`
public static function parseResponse(string $message): Response
Parses a response message string into a response object.
`GuzzleHttp\Psr7\Header::parse`
public static function parse(string|array $header): array
Parse an array of header values containing ";" separated data into an
array of associative arrays representing the header key value pair data
of the header. When a parameter does not contain a value, but just
contains a key, this function will inject a key with a '' string value.
`GuzzleHttp\Psr7\Header::normalize`
public static function normalize(string|array $header): array
Converts an array of header values that may contain comma separated
headers into an array of headers with no comma separated values.
`GuzzleHttp\Psr7\Query::parse`
public static function parse(string $str, int|bool $urlEncoding = true): array
Parse a query string into an associative array.
If multiple values are found for the same key, the value of that key
value pair will become an array. This function does not parse nested
PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2
will be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).
`GuzzleHttp\Psr7\Query::build`
public static function build(array $params, int|false $encoding = PHP_QUERY_RFC3986): string
Build a query string from an array of key value pairs.
This function can use the return value of parse() to build a query
string. This function does not modify the provided keys when an array is
encountered (like http_build_query() would).
`GuzzleHttp\Psr7\Utils::caselessRemove`
public static function caselessRemove(iterable<string> $keys, $keys, array $data): array
Remove the items given by the keys, case insensitively from the data.
`GuzzleHttp\Psr7\Utils::copyToStream`
public static function copyToStream(StreamInterface $source, StreamInterface $dest, int $maxLen = -1): void
Copy the contents of a stream into another stream until the given number
of bytes have been read.
`GuzzleHttp\Psr7\Utils::copyToString`
public static function copyToString(StreamInterface $stream, int $maxLen = -1): string
Copy the contents of a stream into a string until the given number of
bytes have been read.
`GuzzleHttp\Psr7\Utils::hash`
public static function hash(StreamInterface $stream, string $algo, bool $rawOutput = false): string
Calculate a hash of a stream.
This method reads the entire stream to calculate a rolling hash, based on
PHP's hash_init functions.
`GuzzleHttp\Psr7\Utils::modifyRequest`
public static function modifyRequest(RequestInterface $request, array $changes): RequestInterface
Clone and modify a request with the given changes.
This method is useful for reducing the number of clones needed to mutate
a message.
- method: (string) Changes the HTTP method.
- set_headers: (array) Sets the given headers.
- remove_headers: (array) Remove the given headers.
- body: (mixed) Sets the given body.
- uri: (UriInterface) Set the URI.
- query: (string) Set the query string value of the URI.
- version: (string) Set the protocol version.
`GuzzleHttp\Psr7\Utils::readLine`
public static function readLine(StreamInterface $stream, int $maxLength = null): string
Read a line from the stream up to the maximum allowed buffer length.
`GuzzleHttp\Psr7\Utils::streamFor`
public static function streamFor(resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource = '', array $options = []): StreamInterface
Create a new stream based on the input type.
Options is an associative array that can contain the following keys:
- metadata: Array of custom metadata.
- size: Size of the stream.
This method accepts the following $resource types:
Psr\Http\Message\StreamInterface: Returns the value as-is.string: Creates a stream object that uses the given string as the contents.resource: Creates a stream object that wraps the given PHP stream resource.Iterator: If the provided value implementsIterator, then a read-only
stream object will be created that wraps the given iterable. Each time the
stream is read from, data from the iterator will fill a buffer and will be
continuously called until the buffer is equal to the requested read size.
Subsequent read calls will first read from the buffer and then callnext
on the underlying iterator until it is exhausted.objectwith__toString(): If the object has the__toString()method,
the object will be cast to a string and then a stream will be returned that
uses the string value.NULL: Whennullis passed, an empty stream object is returned.callableWhen a callable is passed, a read-only stream object will be
created that invokes the given callable. The callable is invoked with the
number of suggested bytes to read. The callable can return any number of
bytes, but MUST returnfalsewhen there is no more data to return. The
stream object that wraps the callable will invoke the callable until the
number of requested bytes are available. Any additional bytes will be
buffered and used in subsequent reads.
$stream = GuzzleHttp\Psr7\Utils::streamFor('foo');
$stream = GuzzleHttp\Psr7\Utils::streamFor(fopen('/path/to/file', 'r'));
$generator = function ($bytes) {
for ($i = 0; $i < $bytes; $i++) {
yield ' ';
}
}
$stream = GuzzleHttp\Psr7\Utils::streamFor($generator(100));`GuzzleHttp\Psr7\Utils::tryFopen`
public static function tryFopen(string $filename, string $mode): resource
Safely opens a PHP stream resource using a filename.
When fopen fails, PHP normally raises a warning. This function adds an
error handler that checks for errors and throws an exception instead.
`GuzzleHttp\Psr7\Utils::tryGetContents`
public static function tryGetContents(resource $stream): string
Safely gets the contents of a given stream.
When stream_get_contents fails, PHP normally raises a warning. This
function adds an error handler that checks for errors and throws an
exception instead.
`GuzzleHttp\Psr7\Utils::uriFor`
public static function uriFor(string|UriInterface $uri): UriInterface
Returns a UriInterface for the given value.
This function accepts a string or UriInterface and returns a
UriInterface for the given value. If the value is already a
UriInterface, it is returned as-is.
`GuzzleHttp\Psr7\MimeType::fromFilename`
public static function fromFilename(string $filename): string|null
Determines the mimetype of a file by looking at its extension.
`GuzzleHttp\Psr7\MimeType::fromExtension`
public static function fromExtension(string $extension): string|null
Maps a file extensions to a mimetype.
Upgrading from Function API
The static API was first introduced in 1.7.0, in order to mitigate problems with functions conflicting between global and local copies of the package. The function API was removed in 2.0.0. A migration table has been provided here for your convenience:
| Original Function | Replacement Method |
|---|---|
str |
Message::toString |
uri_for |
Utils::uriFor |
stream_for |
Utils::streamFor |
parse_header |
Header::parse |
normalize_header |
Header::normalize |
modify_request |
Utils::modifyRequest |
rewind_body |
Message::rewindBody |
try_fopen |
Utils::tryFopen |
copy_to_string |
Utils::copyToString |
copy_to_stream |
Utils::copyToStream |
hash |
Utils::hash |
readline |
Utils::readLine |
parse_request |
Message::parseRequest |
parse_response |
Message::parseResponse |
parse_query |
Query::parse |
build_query |
Query::build |
mimetype_from_filename |
MimeType::fromFilename |
mimetype_from_extension |
MimeType::fromExtension |
_parse_message |
Message::parseMessage |
_parse_request_uri |
Message::parseRequestUri |
get_message_body_summary |
Message::bodySummary |
_caseless_remove |
Utils::caselessRemove |
Additional URI Methods
Aside from the standard Psr\Http\Message\UriInterface implementation in form of the GuzzleHttp\Psr7\Uri class,
this library also provides additional functionality when working with URIs as static methods.
URI Types
An instance of Psr\Http\Message\UriInterface can either be an absolute URI or a relative reference.
An absolute URI has a scheme. A relative reference is used to express a URI relative to another URI,
the base URI. Relative references can be divided into several forms according to
RFC 3986 Section 4.2:
- network-path references, e.g.
//example.com/path - absolute-path references, e.g.
/path - relative-path references, e.g.
subpath
The following methods can be used to identify the type of the URI.
`GuzzleHttp\Psr7\Uri::isAbsolute`
public static function isAbsolute(UriInterface $uri): bool
Whether the URI is absolute, i.e. it has a scheme.
`GuzzleHttp\Psr7\Uri::isNetworkPathReference`
public static function isNetworkPathReference(UriInterface $uri): bool
Whether the URI is a network-path reference. A relative reference that begins with two slash characters is
termed an network-path reference.
`GuzzleHttp\Psr7\Uri::isAbsolutePathReference`
public static function isAbsolutePathReference(UriInterface $uri): bool
Whether the URI is a absolute-path reference. A relative reference that begins with a single slash character is
termed an absolute-path reference.
`GuzzleHttp\Psr7\Uri::isRelativePathReference`
public static function isRelativePathReference(UriInterface $uri): bool
Whether the URI is a relative-path reference. A relative reference that does not begin with a slash character is
termed a relative-path reference.
`GuzzleHttp\Psr7\Uri::isSameDocumentReference`
public static function isSameDocumentReference(UriInterface $uri, UriInterface $base = null): bool
Whether the URI is a same-document reference. A same-document reference refers to a URI that is, aside from its
fragment component, identical to the base URI. When no base URI is given, only an empty URI reference
(apart from its fragment) is considered a same-document reference.
URI Components
Additional methods to work with URI components.
`GuzzleHttp\Psr7\Uri::isDefaultPort`
public static function isDefaultPort(UriInterface $uri): bool
Whether the URI has the default port of the current scheme. Psr\Http\Message\UriInterface::getPort may return null
or the standard port. This method can be used independently of the implementation.
`GuzzleHttp\Psr7\Uri::composeComponents`
public static function composeComponents($scheme, $authority, $path, $query, $fragment): string
Composes a URI reference string from its various components according to
RFC 3986 Section 5.3. Usually this method does not need to be called
manually but instead is used indirectly via Psr\Http\Message\UriInterface::__toString.
`GuzzleHttp\Psr7\Uri::fromParts`
public static function fromParts(array $parts): UriInterface
Creates a URI from a hash of parse_url components.
`GuzzleHttp\Psr7\Uri::withQueryValue`
public static function withQueryValue(UriInterface $uri, $key, $value): UriInterface
Creates a new URI with a specific query string value. Any existing query string values that exactly match the
provided key are removed and replaced with the given key value pair. A value of null will set the query string
key without a value, e.g. "key" instead of "key=value".
`GuzzleHttp\Psr7\Uri::withQueryValues`
public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface
Creates a new URI with multiple query string values. It has the same behavior as withQueryValue() but for an
associative array of key => value.
`GuzzleHttp\Psr7\Uri::withoutQueryValue`
public static function withoutQueryValue(UriInterface $uri, $key): UriInterface
Creates a new URI with a specific query string value removed. Any existing query string values that exactly match the
provided key are removed.
Cross-Origin Detection
GuzzleHttp\Psr7\UriComparator provides methods to determine if a modified URL should be considered cross-origin.
`GuzzleHttp\Psr7\UriComparator::isCrossOrigin`
public static function isCrossOrigin(UriInterface $original, UriInterface $modified): bool
Determines if a modified URL should be considered cross-origin with respect to an original URL.
Reference Resolution
GuzzleHttp\Psr7\UriResolver provides methods to resolve a URI reference in the context of a base URI according
to RFC 3986 Section 5. This is for example also what web browsers
do when resolving a link in a website based on the current request URI.
`GuzzleHttp\Psr7\UriResolver::resolve`
public static function resolve(UriInterface $base, UriInterface $rel): UriInterface
Converts the relative URI into a new URI that is resolved against the base URI.
`GuzzleHttp\Psr7\UriResolver::removeDotSegments`
public static function removeDotSegments(string $path): string
Removes dot segments from a path and returns the new path according to
RFC 3986 Section 5.2.4.
`GuzzleHttp\Psr7\UriResolver::relativize`
public static function relativize(UriInterface $base, UriInterface $target): UriInterface
Returns the target URI as a relative reference from the base URI. This method is the counterpart to resolve():
(string) $target === (string) UriResolver::resolve($base, UriResolver::relativize($base, $target))One use-case is to use the current request URI as base URI and then generate relative links in your documents
to reduce the document size or offer self-contained downloadable document archives.
$base = new Uri('http://example.com/a/b/');
echo UriResolver::relativize($base, new Uri('http://example.com/a/b/c')); // prints 'c'.
echo UriResolver::relativize($base, new Uri('http://example.com/a/x/y')); // prints '../x/y'.
echo UriResolver::relativize($base, new Uri('http://example.com/a/b/?q')); // prints '?q'.
echo UriResolver::relativize($base, new Uri('http://example.org/a/b/')); // prints '//example.org/a/b/'.Normalization and Comparison
GuzzleHttp\Psr7\UriNormalizer provides methods to normalize and compare URIs according to
RFC 3986 Section 6.
`GuzzleHttp\Psr7\UriNormalizer::normalize`
public static function normalize(UriInterface $uri, $flags = self::PRESERVING_NORMALIZATIONS): UriInterface
Returns a normalized URI. The scheme and host component are already normalized to lowercase per PSR-7 UriInterface.
This methods adds additional normalizations that can be configured with the $flags parameter which is a bitmask
of normalizations to apply. The following normalizations are available:
UriNormalizer::PRESERVING_NORMALIZATIONSDefault normalizations which only include the ones that preserve semantics.
UriNormalizer::CAPITALIZE_PERCENT_ENCODINGAll letters within a percent-encoding triplet (e.g., "%3A") are case-insensitive, and should be capitalized.
Example:
http://example.org/a%c2%b1b→http://example.org/a%C2%B1bUriNormalizer::DECODE_UNRESERVED_CHARACTERSDecodes percent-encoded octets of unreserved characters. For consistency, percent-encoded octets in the ranges of
ALPHA (%41–%5A and %61–%7A), DIGIT (%30–%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should
not be created by URI producers and, when found in a URI, should be decoded to their corresponding unreserved
characters by URI normalizers.Example:
http://example.org/%7Eusern%61me/→http://example.org/~username/UriNormalizer::CONVERT_EMPTY_PATHConverts the empty path to "/" for http and https URIs.
Example:
http://example.org→http://example.org/UriNormalizer::REMOVE_DEFAULT_HOSTRemoves the default host of the given URI scheme from the URI. Only the "file" scheme defines the default host
"localhost". All offile:/myfile,file:///myfile, andfile://localhost/myfileare equivalent according to
RFC 3986.Example:
file://localhost/myfile→file:///myfileUriNormalizer::REMOVE_DEFAULT_PORTRemoves the default port of the given URI scheme from the URI.
Example:
http://example.org:80/→http://example.org/UriNormalizer::REMOVE_DOT_SEGMENTSRemoves unnecessary dot-segments. Dot-segments in relative-path references are not removed as it would
change the semantics of the URI reference.Example:
http://example.org/../a/b/../c/./d.html→http://example.org/a/c/d.htmlUriNormalizer::REMOVE_DUPLICATE_SLASHESPaths which include two or more adjacent slashes are converted to one. Webservers usually ignore duplicate slashes
and treat those URIs equivalent. But in theory those URIs do not need to be equivalent. So this normalization
may change the semantics. Encoded slashes (%2F) are not removed.Example:
http://example.org//foo///bar.html→http://example.org/foo/bar.htmlUriNormalizer::SORT_QUERY_PARAMETERSSort query parameters with their values in alphabetical order. However, the order of parameters in a URI may be
significant (this is not defined by the standard). So this normalization is not safe and may change the semantics
of the URI.Example:
?lang=en&article=fred→?article=fred&lang=en
`GuzzleHttp\Psr7\UriNormalizer::isEquivalent`
public static function isEquivalent(UriInterface $uri1, UriInterface $uri2, $normalizations = self::PRESERVING_NORMALIZATIONS): bool
Whether two URIs can be considered equivalent. Both URIs are normalized automatically before comparison with the given$normalizations bitmask. The method also accepts relative URI references and returns true when they are equivalent.
This of course assumes they will be resolved against the same base URI. If this is not the case, determination of
equivalence or difference of relative references does not mean anything.
Version Guidance
| Version | Status | PHP Version |
|---|---|---|
| 1.x | Security fixes | >=5.4,<8.1 |
| 2.x | Latest | ^7.2.5 || ^8.0 |
Security
If you discover a security vulnerability within this package, please send an email to [email protected]. All security vulnerabilities will be promptly addressed. Please do not disclose security-related issues publicly until a fix has been announced. Please see Security Policy for more information.
License
Guzzle is made available under the MIT License (MIT). Please see License File for more information.
For Enterprise
Available as part of the Tidelift Subscription
The maintainers of Guzzle and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.
Overview (`vendor/illuminate/database/README.md`)
Illuminate Database
The Illuminate Database component is a full database toolkit for PHP, providing an expressive query builder, ActiveRecord style ORM, and schema builder. It currently supports MySQL, Postgres, SQL Server, and SQLite. It also serves as the database layer of the Laravel PHP framework.
Usage Instructions
First, create a new "Capsule" manager instance. Capsule aims to make configuring the library for usage outside of the Laravel framework as easy as possible.
use Illuminate\Database\Capsule\Manager as Capsule;
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
// Set the event dispatcher used by Eloquent models... (optional)
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
$capsule->setEventDispatcher(new Dispatcher(new Container));
// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();
// Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
$capsule->bootEloquent();
composer require "illuminate/events"required when you need to use observers with Eloquent.
Once the Capsule instance has been registered. You may use it like so:
Using The Query Builder
$users = Capsule::table('users')->where('votes', '>', 100)->get();Other core methods may be accessed directly from the Capsule in the same manner as from the DB facade:
$results = Capsule::select('select * from users where id = ?', [1]);Using The Schema Builder
Capsule::schema()->create('users', function ($table) {
$table->increments('id');
$table->string('email')->unique();
$table->timestamps();
});Using The Eloquent ORM
class User extends Illuminate\Database\Eloquent\Model {}
$users = User::where('votes', '>', 1)->get();For further documentation on using the various database facilities this library provides, consult the Laravel framework documentation.
Overview (`vendor/khanamiryan/qrcode-detector-decoder/README.md`)
QR code decoder / reader for PHP
This is a PHP library to detect and decode QR-codes.This is first and only QR code reader that works without extensions.
Ported from ZXing library
Installation
The recommended method of installing this library is via Composer.
Run the following command from your project root:
$ composer require khanamiryan/qrcode-detector-decoderUsage
require __DIR__ . "/vendor/autoload.php";
$qrcode = new QrReader('path/to_image');
$text = $qrcode->text(); //return decoded text from QR CodeRequirements
- PHP >= 5.6
- GD Library
Contributing
You can help the project by adding features, cleaning the code, adding composer and other.
- Fork it
- Create your feature branch:
git checkout -b my-new-feature - Commit your changes:
git commit -am 'Add some feature' - Push to the branch:
git push origin my-new-feature - Submit a pull request
Overview (`vendor/mrgoon/aliyun-sms-sdk/README.md`)
阿里云短信服务核心代码
- 网上一些开源项目的更新时间用的相对较老的版本,使用的request文件是2016-09-27
- 本项目更新于2017-05-25
Overview (`vendor/mrgoon/aliyun-sms/README.md`)
介绍
阿里大于关闭了新用户渠道,迁移到阿里云短信服务上,然而阿里云短信服务在5月底更新了api。
在github上找了一下,轮子都是基于2016年的接口,非常难受。
自己造了一个轮子,亲测可用。
- 安装
composer require mrgoon/aliyun-sms
基于laravel框架的使用方法
- 加载
在config/app的providers中添加Mrgoon\AliSms\ServiceProvider::class
同时,可以选择性添加aliases
控制台运行:php artisan vendor:publish
根据新增的aliyunsms.php 文件,在.env文件中添加环境变量:
ALIYUN_SMS_AK=your access key
ALIYUN_SMS_AS=your secret key
ALIYUN_SMS_SIGN_NAME=sign name- 使用
$aliSms = new AliSms();
$response = $aliSms->sendSms('phone number', 'SMS_code', ['name'=> 'value in your template']);
//dump($response);非laravel框架的使用方法
- 加载方式通过composer,不变
- 使用样例代码如下:
$config = [
'access_key' => 'your access key',
'access_secret' => 'your access secret',
'sign_name' => 'your sign name',
];
$aliSms = new Mrgoon\AliSms\AliSms();
$response = $sms->sendSms('phone number', 'tempplate code', ['name'=> 'value in your template'], $config);Overview (`vendor/nesbot/carbon/readme.md`)
Carbon
An international PHP extension for DateTime. https://carbon.nesbot.com
/* Detailed source-code truncated for AI context efficiency. */Get supported nesbot/carbon with the Tidelift Subscription
Installation
With Composer
$ composer require nesbot/carbon{
"require": {
"nesbot/carbon": "^2.16"
}
}<?php
require 'vendor/autoload.php';
use Carbon\Carbon;
printf("Now: %s", Carbon::now());Without Composer
Why are you not using composer? Download the Carbon latest release and put the contents of the ZIP archive into a directory in your project. Then require the file autoload.php to get all classes and dependencies loaded on need.
<?php
require 'path-to-Carbon-directory/autoload.php';
use Carbon\Carbon;
printf("Now: %s", Carbon::now());Docs
https://carbon.nesbot.com/docs
Security contact information
To report a security vulnerability, please use the
Tidelift security contact.
Tidelift will coordinate the fix and disclosure.
Credits
Contributors
This project exists thanks to all the people who contribute.
Translators
Thanks to people helping us to translate Carbon in so many languages
Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website.
Backers
Thank you to all our backers! 🙏
Carbon for enterprise
Available as part of the Tidelift Subscription.
The maintainers of Carbon and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.
Overview (`vendor/phpmailer/phpmailer/README.md`)
PHPMailer – A full-featured email creation and transfer class for PHP
Features
- Probably the world's most popular code for sending email from PHP!
- Used by many open-source projects: WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! and many more
- Integrated SMTP support – send without a local mail server
- Send emails with multiple To, CC, BCC and Reply-to addresses
- Multipart/alternative emails for mail clients that do not read HTML email
- Add attachments, including inline
- Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings
- SMTP authentication with LOGIN, PLAIN, CRAM-MD5, and XOAUTH2 mechanisms over SMTPS and SMTP+STARTTLS transports
- Validates email addresses automatically
- Protects against header injection attacks
- Error messages in over 50 languages!
- DKIM and S/MIME signing support
- Compatible with PHP 5.5 and later, including PHP 8.1
- Namespaced to prevent name clashes
- Much more!
Why you might need it
Many PHP developers need to send email from their code. The only PHP function that supports this directly is mail(). However, it does not provide any assistance for making use of popular features such as encryption, authentication, HTML messages, and attachments.
Formatting email correctly is surprisingly difficult. There are myriad overlapping (and conflicting) standards, requiring tight adherence to horribly complicated formatting and encoding rules – the vast majority of code that you'll find online that uses the mail() function directly is just plain wrong, if not unsafe!
The PHP mail() function usually sends via a local mail server, typically fronted by a sendmail binary on Linux, BSD, and macOS platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP client allows email sending on all platforms without needing a local mail server. Be aware though, that the mail() function should be avoided when possible; it's both faster and safer to use SMTP to localhost.
Please don't be tempted to do it yourself – if you don't use PHPMailer, there are many other excellent libraries that
you should look at before rolling your own. Try SwiftMailer
, Laminas/Mail, ZetaComponents etc.
License
This software is distributed under the LGPL 2.1 license, along with the GPL Cooperation Commitment. Please read LICENSE for information on the software availability and distribution.
Installation & loading
PHPMailer is available on Packagist (using semantic versioning), and installation via Composer is the recommended way to install PHPMailer. Just add this line to your composer.json file:
"phpmailer/phpmailer": "^6.5"or run
composer require phpmailer/phpmailerNote that the vendor folder and the vendor/autoload.php script are generated by Composer; they are not part of PHPMailer.
If you want to use the Gmail XOAUTH2 authentication class, you will also need to add a dependency on the league/oauth2-client package in your composer.json.
Alternatively, if you're not using Composer, you
can download PHPMailer as a zip file, (note that docs and examples are not included in the zip file), then copy the contents of the PHPMailer folder into one of the include_path directories specified in your PHP configuration and load each class file manually:
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'path/to/PHPMailer/src/Exception.php';
require 'path/to/PHPMailer/src/PHPMailer.php';
require 'path/to/PHPMailer/src/SMTP.php';If you're not using the SMTP class explicitly (you're probably not), you don't need a use line for the SMTP class. Even if you're not using exceptions, you do still need to load the Exception class as it is used internally.
Legacy versions
PHPMailer 5.2 (which is compatible with PHP 5.0 — 7.0) is no longer supported, even for security updates. You will find the latest version of 5.2 in the 5.2-stable branch. If you're using PHP 5.5 or later (which you should be), switch to the 6.x releases.
Upgrading from 5.2
The biggest changes are that source files are now in the src/ folder, and PHPMailer now declares the namespace PHPMailer\PHPMailer. This has several important effects – read the upgrade guide for more details.
Minimal installation
While installing the entire package manually or with Composer is simple, convenient, and reliable, you may want to include only vital files in your project. At the very least you will need src/PHPMailer.php. If you're using SMTP, you'll need src/SMTP.php, and if you're using POP-before SMTP (very unlikely!), you'll need src/POP3.php. You can skip the language folder if you're not showing errors to users and can make do with English-only errors. If you're using XOAUTH2 you will need src/OAuth.php as well as the Composer dependencies for the services you wish to authenticate with. Really, it's much easier to use Composer!
A Simple Example
/* Detailed source-code truncated for AI context efficiency. */You'll find plenty to play with in the examples folder, which covers many common scenarios including sending through gmail, building contact forms, sending to mailing lists, and more.
If you are re-using the instance (e.g. when sending to a mailing list), you may need to clear the recipient list to avoid sending duplicate messages. See the mailing list example for further guidance.
That's it. You should now be ready to use PHPMailer!
Localization
PHPMailer defaults to English, but in the language folder you'll find many translations for PHPMailer error messages that you may encounter. Their filenames contain ISO 639-1 language code for the translations, for example fr for French. To specify a language, you need to tell PHPMailer which one to use, like this:
//To load the French version
$mail->setLanguage('fr', '/optional/path/to/language/directory/');We welcome corrections and new languages – if you're looking for corrections, run the PHPMailerLangTest.php script in the tests folder and it will show any missing translations.
Documentation
Start reading at the GitHub wiki. If you're having trouble, head for the troubleshooting guide as it's frequently updated.
Examples of how to use PHPMailer for common scenarios can be found in the examples folder. If you're looking for a good starting point, we recommend you start with the Gmail example.
To reduce PHPMailer's deployed code footprint, examples are not included if you load PHPMailer via Composer or via GitHub's zip file download, so you'll need to either clone the git repository or use the above links to get to the examples directly.
Complete generated API documentation is available online.
You can generate complete API-level documentation by running phpdoc in the top-level folder, and documentation will appear in the docs folder, though you'll need to have PHPDocumentor installed. You may find the unit tests a good reference for how to do various operations such as encryption.
If the documentation doesn't cover what you need, search the many questions on Stack Overflow, and before you ask a question about "SMTP Error: Could not connect to SMTP host.", read the troubleshooting guide.
Tests
PHPMailer tests use PHPUnit 9, with a polyfill to let 9-style tests run on older PHPUnit and PHP versions.
If this isn't passing, is there something you can do to help?
Security
Please disclose any vulnerabilities found responsibly – report security issues to the maintainers privately.
See SECURITY and PHPMailer's security advisories on GitHub.
Contributing
Please submit bug reports, suggestions and pull requests to the GitHub issue tracker.
We're particularly interested in fixing edge-cases, expanding test coverage and updating translations.
If you found a mistake in the docs, or want to add something, go ahead and amend the wiki – anyone can edit it.
If you have git clones from prior to the move to the PHPMailer GitHub organisation, you'll need to update any remote URLs referencing the old GitHub location with a command like this from within your clone:
git remote set-url upstream https://github.com/PHPMailer/PHPMailer.gitPlease don't use the SourceForge or Google Code projects any more; they are obsolete and no longer maintained.
Sponsorship
Development time and resources for PHPMailer are provided by Smartmessages.net, the world's only privacy-first email marketing system.
Donations are very welcome, whether in beer 🍺, T-shirts 👕, or cold, hard cash 💰. Sponsorship through GitHub is a simple and convenient way to say "thank you" to PHPMailer's maintainers and contributors – just click the "Sponsor" button on the project page. If your company uses PHPMailer, consider taking part in Tidelift's enterprise support programme.
PHPMailer For Enterprise
Available as part of the Tidelift Subscription.
The maintainers of PHPMailer and thousands of other packages are working with Tidelift to deliver commercial
support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and
improve code health, while paying the maintainers of the exact packages you
use. Learn more.
Changelog
See changelog.
History
- PHPMailer was originally written in 2001 by Brent R. Matzelle as a SourceForge project.
- Marcus Bointon (
coolbruon SF) and Andy Prevost (codeworxtech) took over the project in 2004. - Became an Apache incubator project on Google Code in 2010, managed by Jim Jagielski.
- Marcus created his fork on GitHub in 2008.
- Jim and Marcus decide to join forces and use GitHub as the canonical and official repo for PHPMailer in 2013.
- PHPMailer moves to the PHPMailer organisation on GitHub in 2013.
What's changed since moving from SourceForge?
- Official successor to the SourceForge and Google Code projects.
- Test suite.
- Continuous integration with Github Actions.
- Composer support.
- Public development.
- Additional languages and language strings.
- CRAM-MD5 authentication support.
- Preserves full repo history of authors, commits and branches from the original SourceForge project.
Overview (`vendor/psr/container/README.md`)
Container interface
This repository holds all interfaces related to PSR-11 (Container Interface).
Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container.
The installable package and implementations are listed on Packagist.
Overview (`vendor/psr/http-client/README.md`)
HTTP Client
This repository holds all the common code related to PSR-18 (HTTP Client).
Note that this is not a HTTP Client implementation of its own. It is merely abstractions that describe the components of a HTTP Client.
The installable package and implementations are listed on Packagist.
Overview (`vendor/psr/http-factory/README.md`)
HTTP Factories
This repository holds all interfaces related to PSR-17 (HTTP Message Factories).
Please refer to the specification for a description.
You can find implementations of the specification by looking for packages providing the
psr/http-factory-implementation virtual package.
Overview (`vendor/psr/http-message/README.md`)
PSR Http Message
This repository holds all interfaces/classes/traits related to
PSR-7.
Note that this is not a HTTP message implementation of its own. It is merely an
interface that describes a HTTP message. See the specification for more details.
Usage
We'll certainly need some stuff in here.
Overview (`vendor/psr/simple-cache/README.md`)
PHP FIG Simple Cache PSR
This repository holds all interfaces related to PSR-16.
Note that this is not a cache implementation of its own. It is merely an interface that describes a cache implementation. See the specification for more details.
You can find implementations of the specification by looking for packages providing the psr/simple-cache-implementation virtual package.
Overview (`vendor/rah/danpu/README.md`)
Danpu - MySQL dump tool for PHP
Packagist | Downloads | Issues | Donate
Danpu is a dependency-free, cross-platform, portable PHP library for backing up MySQL databases. It has no hard dependencies, and is fit for restricted environments where security is key and access is limited. Danpu requires nothing more than access to your database, PDO and a directory it can write the backup to. The script is optimized and has low memory-footprint, allowing it to handle even larger databases.
Danpu supports backing up table structures, the data itself, views and triggers. Created dump files can optionally be compressed to save space, and generated SQL output is optimized for compatibility.
Requirements
Minimum:
- PHP 5.3.0 or newer
- MySQL 4.1.0 or newer
- PDO
Recommended, but optional:
- PHP 5.4.0 or newer
- MySQL 5.0.11 or newer
- zlib
Backing up views and triggers requires MySQL 5.0.11 or newer.
Install
Using Composer:
$ composer require rah/danpuUsage
To create a new backup or import one, configure a new Dump instance and pass it to one of the worker classes. To begin, first make sure you have included Composer's autoloader file in your project:
require './vendor/autoload.php';If you are already using other Composer packages, or a modern Composer-managed framework, this should be taken care of already. If not, merely add the autoloader to your base bootstrap includes. See Composer's documentation for more information.
Take a backup
Backups can be created with the Export class. The class exports the database to a SQL file, or throws exceptions on errors. The file is compressed if the target filename ends to a .gz extension.
use Rah\Danpu\Dump;
use Rah\Danpu\Export;
try {
$dump = new Dump;
$dump
->file('/path/to/target/dump/file.sql')
->dsn('mysql:dbname=database;host=localhost')
->user('username')
->pass('password')
->tmp('/tmp');
new Export($dump);
} catch (\Exception $e) {
echo 'Export failed with message: ' . $e->getMessage();
}The database is dumped in chunks, one row at the time without buffering huge amount of data to the memory. This makes the script very memory efficient, and can allow Danpu to handle databases of any size, given the system limitations of course. You physically won't be able backup rows that take more memory than can be allocated to PHP, nor write backups if there isn't enough space for the files.
Import a backup
Danpu can also import its own backups using the Import class. While the importer works with backups it has made, it doesn't accept freely formatted SQL. The importer is pretty strict about formatting, and expects exactly the same format as generated by Danpu. It expects that values in statements are escaped properly, including newlines, queries have to end to a semicolon and statements preferably should not wrap to multiple lines.
To import a backup, create a new instance of the Import class. It uncompresses any .gz files before importing.
use Rah\Danpu\Dump;
use Rah\Danpu\Import;
try {
$dump = new Dump;
$dump
->file('/path/to/imported/file.sql')
->dsn('mysql:dbname=database;host=localhost')
->user('username')
->pass('password')
->tmp('/tmp');
new Import($dump);
} catch (\Exception $e) {
echo 'Import failed with message: ' . $e->getMessage();
}Options
In addition to the mandatory connection and file location, Danpu accepts various optional configuration options. These include filtering tables and views by prefix, ignoring tables and creating dumps without row data. See the src/Rah/Danpu/Config.php for full list of options. The source file contains detailed documentation blocks, outlining each option.
Troubleshooting
Running out of memory, backup taking too long
As with any PHP script, Danpu is restricted by the safe limits you have set for PHP. When dealing with larger databases, taking a backup will take longer and require more memory. If you find yourself hitting the maximum execution time or running out of memory, its time to increase the limits enough to let the script to work.
PHP lets you to change these limits with its configuration options, which can be modified temporarily during script execution, or in global configuration files. The configuration options you will be the most interested in, are memory_limit and max_execution_time, and possibly ignore_user_abort. You can change these values in your script before running a backup with Danpu:
ini_set('memory_limit', '256M');
set_time_limit(0);
ignore_user_abort(true);This of course requires that you have access to these values and you actually have more memory to give. Keep in mind that PHP may be affected by other limitations, such as your web server.
Overview (`vendor/ralouphie/getallheaders/README.md`)
getallheaders
PHP getallheaders() polyfill. Compatible with PHP >= 5.3.
This is a simple polyfill for getallheaders().
Install
For PHP version >= 5.6:
composer require ralouphie/getallheadersFor PHP version < 5.6:
composer require ralouphie/getallheaders "^2"Overview (`vendor/smarty/smarty/README.md`)
Smarty 3 template engine
Documentation
For documentation see
www.smarty.net/docs/en/
Requirements
Smarty can be run with PHP 5.2 to PHP 7.4.
Distribution repository
Smarty 3.1.28 introduces run time template inheritance
Read the NEW_FEATURES and INHERITANCE_RELEASE_NOTES file for recent extensions to Smarty 3.1 functionality
Smarty versions 3.1.11 or later are now on GitHub and can be installed with Composer.
The "smarty/smarty" package will start at libs/.... subfolder.
To get the latest stable version of Smarty 3.1 use:
"require": {
"smarty/smarty": "~3.1"
}in your composer.json file.
To get the trunk version use:
"require": {
"smarty/smarty": "~3.1@dev"
}For a specific version use something like:
"require": {
"smarty/smarty": "3.1.19"
}PHPUnit test can be installed by corresponding composer entries like:
"require": {
"smarty/smarty-phpunit": "3.1.19"
}Similar applies for the lexer/parser generator.
"require": {
"smarty/smarty-lexer": "3.1.19"
}Or you could use:
"require": {
"smarty/smarty-dev": "3.1.19"
}Which is a wrapper to install all 3 packages.
Composer can also be used for Smarty2 versions 2.6.24 to 2.6.30.
Overview (`vendor/symfony/console/README.md`)
Console Component
The Console component eases the creation of beautiful and testable command line
interfaces.
Sponsor
The Console component for Symfony 5.4/6.0 is backed by Les-Tilleuls.coop.
Les-Tilleuls.coop is a team of 50+ Symfony experts who can help you design, develop and
fix your projects. We provide a wide range of professional services including development,
consulting, coaching, training and audits. We also are highly skilled in JS, Go and DevOps.
We are a worker cooperative!
Help Symfony by sponsoring its development!
Resources
Credits
Resources/bin/hiddeninput.exe is a third party binary provided within this
component. Find sources and license at https://github.com/Seldaek/hidden-input.
Overview (`vendor/symfony/deprecation-contracts/README.md`)
Symfony Deprecation Contracts
A generic function and convention to trigger deprecation notices.
This package provides a single global function named trigger_deprecation() that triggers silenced deprecation notices.
By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component,
the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments.
The function requires at least 3 arguments:
- the name of the Composer package that is triggering the deprecation
- the version of the package that introduced the deprecation
- the message of the deprecation
- more arguments can be provided: they will be inserted in the message using
printf()formatting
Example:
trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin');This will generate the following message:Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.
While not necessarily recommended, the deprecation notices can be completely ignored by declaring an emptyfunction trigger_deprecation() {} in your application.
Overview (`vendor/symfony/polyfill-ctype/README.md`)
Symfony Polyfill / Ctype
This component provides ctype_* functions to users who run php versions without the ctype extension.
More information can be found in the
main Polyfill README.
License
This library is released under the MIT license.
Overview (`vendor/symfony/polyfill-intl-grapheme/README.md`)
Symfony Polyfill / Intl: Grapheme
This component provides a partial, native PHP implementation of the
Grapheme functions from the
Intl extension.
grapheme_extract: Extract a sequence of grapheme
clusters from a text buffer, which must be encoded in UTF-8grapheme_stripos: Find position (in grapheme units)
of first occurrence of a case-insensitive stringgrapheme_stristr: Returns part of haystack string
from the first occurrence of case-insensitive needle to the end of haystackgrapheme_strlen: Get string length in grapheme unitsgrapheme_strpos: Find position (in grapheme units)
of first occurrence of a stringgrapheme_strripos: Find position (in grapheme units)
of last occurrence of a case-insensitive stringgrapheme_strrpos: Find position (in grapheme units)
of last occurrence of a stringgrapheme_strstr: Returns part of haystack string from
the first occurrence of needle to the end of haystackgrapheme_substr: Return part of a string
More information can be found in the
main Polyfill README.
License
This library is released under the MIT license.
Overview (`vendor/symfony/polyfill-intl-normalizer/README.md`)
Symfony Polyfill / Intl: Normalizer
This component provides a fallback implementation for theNormalizer class provided
by the Intl extension.
More information can be found in the
main Polyfill README.
License
This library is released under the MIT license.
Overview (`vendor/symfony/polyfill-mbstring/README.md`)
Symfony Polyfill / Mbstring
This component provides a partial, native PHP implementation for the
Mbstring extension.
More information can be found in the
main Polyfill README.
License
This library is released under the MIT license.
Overview (`vendor/symfony/polyfill-php73/README.md`)
Symfony Polyfill / Php73
This component provides functions added to PHP 7.3 core:
More information can be found in the
main Polyfill README.
License
This library is released under the MIT license.
Overview (`vendor/symfony/polyfill-php80/README.md`)
Symfony Polyfill / Php80
This component provides features added to PHP 8.0 core:
StringableinterfacefdivValueErrorclassUnhandledMatchErrorclassFILTER_VALIDATE_BOOLconstantget_debug_typePhpTokenclasspreg_last_error_msgstr_containsstr_starts_withstr_ends_withget_resource_id
More information can be found in the
main Polyfill README.
License
This library is released under the MIT license.
Overview (`vendor/symfony/service-contracts/README.md`)
Symfony Service Contracts
A set of abstractions extracted out of the Symfony components.
Can be used to build on semantics that the Symfony components proved useful - and
that already have battle tested implementations.
See https://github.com/symfony/contracts/blob/main/README.md for more information.
Overview (`vendor/symfony/string/README.md`)
String Component
The String component provides an object-oriented API to strings and deals
with bytes, UTF-8 code points and grapheme clusters in a unified way.
Resources
Overview (`vendor/symfony/translation-contracts/README.md`)
Symfony Translation Contracts
A set of abstractions extracted out of the Symfony components.
Can be used to build on semantics that the Symfony components proved useful - and
that already have battle tested implementations.
See https://github.com/symfony/contracts/blob/main/README.md for more information.
Overview (`vendor/symfony/translation/README.md`)
Translation Component
The Translation component provides tools to internationalize your application.
Getting Started
$ composer require symfony/translationuse Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\ArrayLoader;
$translator = new Translator('fr_FR');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', [
'Hello World!' => 'Bonjour !',
], 'fr_FR');
echo $translator->trans('Hello World!'); // outputs « Bonjour ! »Sponsor
The Translation component for Symfony 5.4/6.0 is backed by:
- Crowdin, a cloud-based localization management software helping teams to go global and stay agile.
- Lokalise, a continuous localization and translation management platform that integrates into your development workflow so you can ship localized products, faster.
Help Symfony by sponsoring its development!
Resources
Overview (`vendor/symfony/var-dumper/README.md`)
VarDumper Component
The VarDumper component provides mechanisms for walking through any arbitrary
PHP variable. It provides a better dump() function that you can use instead
of var_dump().
Resources
Overview (`vendor/voku/portable-ascii/README.md`)
🔡 Portable ASCII
Description
It is written in PHP (PHP 7+) and can work without "mbstring", "iconv" or any other extra encoding php-extension on your server.
The benefit of Portable ASCII is that it is easy to use, easy to bundle.
The project based on ...
- Sean M. Burke's work (https://metacpan.org/pod/Text::Unidecode)
- Tomaz Solc's work (https://pypi.org/project/Unidecode/)
- Portable UTF-8 work (https://github.com/voku/portable-utf8)
- Daniel St. Jules's work (https://github.com/danielstjules/Stringy)
- Johnny Broadway's work (https://github.com/jbroadway/urlify)
- and many cherry-picks from "github"-gists and "Stack Overflow"-snippets ...
Index
- Alternative
- Install
- Why Portable ASCII?
- Requirements and Recommendations
- Usage
- Class methods
- Unit Test
- License and Copyright
Alternative
If you like a more Object Oriented Way to edit strings, then you can take a look at voku/Stringy, it's a fork of "danielstjules/Stringy" but it used the "Portable ASCII"-Class and some extra methods.
// Portable ASCII
use voku\helper\ASCII;
ASCII::to_transliterate('déjà σσς iıii'); // 'deja sss iiii'
// voku/Stringy
use Stringy\Stringy as S;
$stringy = S::create('déjà σσς iıii');
$stringy->toTransliterate(); // 'deja sss iiii'Install "Portable ASCII" via "composer require"
composer require voku/portable-asciiWhy Portable ASCII?[]()
I need ASCII char handling in different classes and before I added this functions into "Portable UTF-8",
but this repo is more modular and portable, because it has no dependencies.
Requirements and Recommendations
- No extensions are required to run this library. Portable ASCII only needs PCRE library that is available by default since PHP 4.2.0 and cannot be disabled since PHP 5.3.0. "\u" modifier support in PCRE for ASCII handling is not a must.
- PHP 7.0 is the minimum requirement
- PHP 8.0 is also supported
Usage
Example: ASCII::to_ascii()
echo ASCII::to_ascii('�Düsseldorf�', 'de');
// will output
// Duesseldorf
echo ASCII::to_ascii('�Düsseldorf�', 'en');
// will output
// DusseldorfPortable ASCII | API
The API from the "ASCII"-Class is written as small static methods.
Class methods
charsArray(bool $replace_extra_symbols): array
↑
Returns an replacement array for ASCII methods.
EXAMPLE:
$array = ASCII::charsArray();
var_dump($array['ru']['б']); // 'b'
Parameters:
bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
Return:
array
charsArrayWithMultiLanguageValues(bool $replace_extra_symbols): array
↑
Returns an replacement array for ASCII methods with a mix of multiple languages.
EXAMPLE:
$array = ASCII::charsArrayWithMultiLanguageValues();
var_dump($array['b']); // ['β', 'б', 'ဗ', 'ბ', 'ب']
Parameters:
bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".
Return:
array An array of replacements.
charsArrayWithOneLanguage(string $language, bool $replace_extra_symbols, bool $asOrigReplaceArray): array
↑
Returns an replacement array for ASCII methods with one language.
For example, German will map 'ä' to 'ae', while other languages
will simply return e.g. 'a'.
EXAMPLE:
$array = ASCII::charsArrayWithOneLanguage('ru');
$tmpKey = \array_search('yo', $array['replace']);
echo $array['orig'][$tmpKey]; // 'ё'
Parameters:
string $language [optional] Language of the source string e.g.: en, de_at, or de-ch. (default is 'en') | ASCII::*_LANGUAGE_CODEbool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".bool $asOrigReplaceArray [optional] TRUE === return {orig: string[], replace: string[]} array
Return:
array An array of replacements.
charsArrayWithSingleLanguageValues(bool $replace_extra_symbols, bool $asOrigReplaceArray): array
↑
Returns an replacement array for ASCII methods with multiple languages.
EXAMPLE:
$array = ASCII::charsArrayWithSingleLanguageValues();
$tmpKey = \array_search('hnaik', $array['replace']);
echo $array['orig'][$tmpKey]; // '၌'
Parameters:
bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".bool $asOrigReplaceArray [optional] TRUE === return {orig: string[], replace: string[]} array
Return:
array An array of replacements.
clean(string $str, bool $normalize_whitespace, bool $keep_non_breaking_space, bool $normalize_msword, bool $remove_invisible_characters): string
↑
Accepts a string and removes all non-UTF-8 characters from it + extras if needed.
Parameters:
string $str The string to be sanitized.bool $normalize_whitespace [optional] Set to true, if you need to normalize the whitespace.bool $keep_non_breaking_space [optional] Set to true, to keep non-breaking-spaces, in combination with $normalize_whitespacebool $normalize_msword [optional] Set to true, if you need to normalize MS Word chars e.g.: "…" => "..."bool $remove_invisible_characters [optional] Set to false, if you not want to remove invisible characters e.g.: "\0"
Return:
string A clean UTF-8 string.
getAllLanguages(): string[]
↑
Get all languages from the constants "ASCII::.*LANGUAGE_CODE".
Parameters:
nothing
Return:
string[]
is_ascii(string $str): bool
↑
Checks if a string is 7 bit ASCII.
EXAMPLE:
ASCII::is_ascii('白'); // false
Parameters:
string $str The string to check.
Return:
bool **true** if it is ASCII **false** otherwise
normalize_msword(string $str): string
↑
Returns a string with smart quotes, ellipsis characters, and dashes from
Windows-1252 (commonly used in Word documents) replaced by their ASCII
equivalents.
EXAMPLE:
ASCII::normalize_msword('„Abcdef…”'); // '"Abcdef..."'
Parameters:
string $str The string to be normalized.
Return:
string A string with normalized characters for commonly used chars in Word documents.
normalize_whitespace(string $str, bool $keepNonBreakingSpace, bool $keepBidiUnicodeControls, bool $normalize_control_characters): string
↑
Normalize the whitespace.
EXAMPLE:
ASCII::normalize_whitespace("abc-\xc2\xa0-öäü-\xe2\x80\xaf-\xE2\x80\xAC", true); // "abc-\xc2\xa0-öäü- -"
Parameters:
string $str The string to be normalized.bool $keepNonBreakingSpace [optional] Set to true, to keep non-breaking-spaces.bool $keepBidiUnicodeControls [optional] Set to true, to keep non-printable (for the web) bidirectional text chars.bool $normalize_control_characters [optional] Set to true, to convert e.g. LINE-, PARAGRAPH-SEPARATOR with "\n" and LINE TABULATION with "\t".
Return:
string A string with normalized whitespace.
remove_invisible_characters(string $str, bool $url_encoded, string $replacement, bool $keep_basic_control_characters): string
↑
Remove invisible characters from a string.
e.g.: This prevents sandwiching null characters between ascii characters, like Java\0script.
copy&past from https://github.com/bcit-ci/CodeIgniter/blob/develop/system/core/Common.php
Parameters:
string $strbool $url_encodedstring $replacementbool $keep_basic_control_characters
Return:
string
to_ascii(string $str, string $language, bool $remove_unsupported_chars, bool $replace_extra_symbols, bool $use_transliterate, bool|null $replace_single_chars_only): string
↑
Returns an ASCII version of the string. A set of non-ASCII characters are
replaced with their closest ASCII counterparts, and the rest are removed
by default. The language or locale of the source string can be supplied
for language-specific transliteration in any of the following formats:
en, en_GB, or en-GB. For example, passing "de" results in "äöü" mapping
to "aeoeue" rather than "aou" as in other languages.
EXAMPLE:
ASCII::to_ascii('�Düsseldorf�', 'en'); // Dusseldorf
Parameters:
string $str The input string.string $language [optional] Language of the source string. (default is 'en') | ASCII::*_LANGUAGE_CODEbool $remove_unsupported_chars [optional] Whether or not to remove the unsupported characters.bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".bool $use_transliterate [optional] Use ASCII::to_transliterate() for unknown chars.bool|null $replace_single_chars_only [optional] Single char replacement is better for the performance, but some languages need to replace more then one char at the same time. | NULL === auto-setting, depended on the language
Return:
string A string that contains only ASCII characters.
to_filename(string $str, bool $use_transliterate, string $fallback_char): string
↑
Convert given string to safe filename (and keep string case).
EXAMPLE:
ASCII::to_filename('שדגשדג.png', true)); // 'shdgshdg.png'
Parameters:
string $strbool $use_transliterate ASCII::to_transliterate() is used by default - unsafe characters are simply replaced with hyphen otherwise.string $fallback_char
Return:
string A string that contains only safe characters for a filename.
to_slugify(string $str, string $separator, string $language, string[] $replacements, bool $replace_extra_symbols, bool $use_str_to_lower, bool $use_transliterate): string
↑
Converts the string into an URL slug. This includes replacing non-ASCII
characters with their closest ASCII equivalents, removing remaining
non-ASCII and non-alphanumeric characters, and replacing whitespace with
$separator. The separator defaults to a single dash, and the string
is also converted to lowercase. The language of the source string can
also be supplied for language-specific transliteration.
Parameters:
string $strstring $separator [optional] The string used to replace whitespace.string $language [optional] Language of the source string. (default is 'en') | ASCII::*_LANGUAGE_CODEarray<string, string> $replacements [optional] A map of replaceable strings.bool $replace_extra_symbols [optional] Add some more replacements e.g. "£" with " pound ".bool $use_str_to_lower [optional] Use "string to lower" for the input.bool $use_transliterate [optional] Use ASCII::to_transliterate() for unknown chars.
Return:
string A string that has been converted to an URL slug.
to_transliterate(string $str, string|null $unknown, bool $strict): string
↑
Returns an ASCII version of the string. A set of non-ASCII characters are
replaced with their closest ASCII counterparts, and the rest are removed
unless instructed otherwise.
EXAMPLE:
ASCII::to_transliterate('déjà σσς iıii'); // 'deja sss iiii'
Parameters:
string $str The input string.string|null $unknown [optional] Character use if character unknown. (default is '?') But you can also use NULL to keep the unknown chars.bool $strict [optional] Use "transliterator_transliterate()" from PHP-Intl
Return:
string A String that contains only ASCII characters.
Unit Test
- Composer is a prerequisite for running the tests.
composer install- The tests can be executed by running this command from the root directory:
./vendor/bin/phpunitSupport
For support and donations please visit Github | Issues | PayPal | Patreon.
For status updates and release announcements please visit Releases | Twitter | Patreon.
For professional support please contact me.
Thanks
- Thanks to GitHub (Microsoft) for hosting the code and a good infrastructure including Issues-Managment, etc.
- Thanks to IntelliJ as they make the best IDEs for PHP and they gave me an open source license for PhpStorm!
- Thanks to Travis CI for being the most awesome, easiest continous integration tool out there!
- Thanks to StyleCI for the simple but powerful code style check.
- Thanks to PHPStan && Psalm for really great Static analysis tools and for discover bugs in the code!
License and Copyright
Released under the MIT License - see LICENSE.txt for details.
Vendor Doctrine Inflector Docs En Index (`vendor/doctrine/inflector/docs/en/index.rst`)
Introduction
The Doctrine Inflector has methods for inflecting text. The features include pluralization,
singularization, converting between camelCase and under_score and capitalizing
words.
Installation
You can install the Inflector with composer:
.. code-block:: console
$ composer require doctrine/inflectorUsage
Using the inflector is easy, you can create a new Doctrine\Inflector\Inflector instance by using
the Doctrine\Inflector\InflectorFactory class:
.. code-block:: php
use Doctrine\Inflector\InflectorFactory;
$inflector = InflectorFactory::create()->build();By default it will create an English inflector. If you want to use another language, just pass the language
you want to create an inflector for to the createForLanguage() method:
.. code-block:: php
use Doctrine\Inflector\InflectorFactory;
use Doctrine\Inflector\Language;
$inflector = InflectorFactory::createForLanguage(Language::SPANISH)->build();The supported languages are as follows:
Language::ENGLISHLanguage::FRENCHLanguage::NORWEGIAN_BOKMALLanguage::PORTUGUESELanguage::SPANISHLanguage::TURKISH
If you want to manually construct the inflector instead of using a factory, you can do so like this:
.. code-block:: php
use Doctrine\Inflector\CachedWordInflector;
use Doctrine\Inflector\RulesetInflector;
use Doctrine\Inflector\Rules\English;
$inflector = new Inflector(
new CachedWordInflector(new RulesetInflector(
English\Rules::getSingularRuleset()
)),
new CachedWordInflector(new RulesetInflector(
English\Rules::getPluralRuleset()
))
);Adding Languages
If you are interested in adding support for your language, take a look at the other languages defined in theDoctrine\Inflector\Rules namespace and the tests located in Doctrine\Tests\Inflector\Rules. You can copy
one of the languages and update the rules for your language.
Once you have done this, send a pull request to the doctrine/inflector repository with the additions.
Custom Setup
If you want to setup custom singular and plural rules, you can configure these in the factory:
.. code-block:: php
use Doctrine\Inflector\InflectorFactory;
use Doctrine\Inflector\Rules\Pattern;
use Doctrine\Inflector\Rules\Patterns;
use Doctrine\Inflector\Rules\Ruleset;
use Doctrine\Inflector\Rules\Substitution;
use Doctrine\Inflector\Rules\Substitutions;
use Doctrine\Inflector\Rules\Transformation;
use Doctrine\Inflector\Rules\Transformations;
use Doctrine\Inflector\Rules\Word;
$inflector = InflectorFactory::create()
->withSingularRules(
new Ruleset(
new Transformations(
new Transformation(new Pattern('/^(bil)er$/i'), '\1'),
new Transformation(new Pattern('/^(inflec|contribu)tors$/i'), '\1ta')
),
new Patterns(new Pattern('singulars')),
new Substitutions(new Substitution(new Word('spins'), new Word('spinor')))
)
)
->withPluralRules(
new Ruleset(
new Transformations(
new Transformation(new Pattern('^(bil)er$'), '\1'),
new Transformation(new Pattern('^(inflec|contribu)tors$'), '\1ta')
),
new Patterns(new Pattern('noflect'), new Pattern('abtuse')),
new Substitutions(
new Substitution(new Word('amaze'), new Word('amazable')),
new Substitution(new Word('phone'), new Word('phonezes'))
)
)
)
->build();No operation inflector
The Doctrine\Inflector\NoopWordInflector may be used to configure an inflector that doesn't perform any operation for
pluralization and/or singularization. If will simply return the input as output.
This is an implementation of the Null Object design pattern <https://sourcemaking.com/design_patterns/null_object>_.
.. code-block:: php
use Doctrine\Inflector\Inflector;
use Doctrine\Inflector\NoopWordInflector;
$inflector = new Inflector(new NoopWordInflector(), new NoopWordInflector());Tableize
Converts ModelName to model_name:
.. code-block:: php
echo $inflector->tableize('ModelName'); // model_nameClassify
Converts model_name to ModelName:
.. code-block:: php
echo $inflector->classify('model_name'); // ModelNameCamelize
This method uses Classify_ and then converts the first character to lowercase:
.. code-block:: php
echo $inflector->camelize('model_name'); // modelNameCapitalize
Takes a string and capitalizes all of the words, like PHP's built-inucwords function. This extends that behavior, however, by allowing the
word delimiters to be configured, rather than only separating on
whitespace.
Here is an example:
.. code-block:: php
$string = 'top-o-the-morning to all_of_you!';
echo $inflector->capitalize($string); // Top-O-The-Morning To All_of_you!
echo $inflector->capitalize($string, '-_ '); // Top-O-The-Morning To All_Of_You!Pluralize
Returns a word in plural form.
.. code-block:: php
echo $inflector->pluralize('browser'); // browsersSingularize
Returns a word in singular form.
.. code-block:: php
echo $inflector->singularize('browsers'); // browserUrlize
Generate a URL friendly string from a string of text:
.. code-block:: php
echo $inflector->urlize('My first blog post'); // my-first-blog-postUnaccent
You can unaccent a string of text using the unaccent() method:
.. code-block:: php
echo $inflector->unaccent('año'); // anoLegacy API
The API present in Inflector 1.x is still available, but will be deprecated in a future release and dropped for 3.0.
Support for languages other than English is available in the 2.0 API only.
Acknowledgements
The language rules in this library have been adapted from several different sources, including but not limited to:
Ruby On Rails Inflector <http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html>_ICanBoogie Inflector <https://github.com/ICanBoogie/Inflector>_CakePHP Inflector <https://book.cakephp.org/3.0/en/core-libraries/inflector.html>_
--- METRICS ---
- Files Extracted: 37
- Estimated Token Budget: ~34516 tokens
- Canonical Reference: https://codewiki.google/github.com/lizhipay/acg-faka