diff --git a/README.md b/README.md index 232feb03f..315f71c50 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,8 @@ namespaced, cleaned up, improved and other stuff. ## Documentation -A documentation created with [phpDocumentor](https://www.phpdoc.org/) can be found at https://chillerlan.github.io/php-qrcode/ (WIP). +See [the wiki](https://github.com/chillerlan/php-qrcode/wiki) for advanced documentation. +An API documentation created with [phpDocumentor](https://www.phpdoc.org/) can be found at https://chillerlan.github.io/php-qrcode/ (WIP). ### Requirements - PHP 7.4+ @@ -49,7 +50,7 @@ A documentation created with [phpDocumentor](https://www.phpdoc.org/) can be fou via terminal: `composer require chillerlan/php-qrcode` -*composer.json* (note: replace `dev-main` with a [version constraint](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints), e.g. `^3.2` - see [releases](https://github.com/chillerlan/php-qrcode/releases) for valid versions) +*composer.json* ```json { "require": { @@ -59,18 +60,19 @@ via terminal: `composer require chillerlan/php-qrcode` } ``` +Note: replace `dev-main` with a [version constraint](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints), e.g. `^3.2` - see [releases](https://github.com/chillerlan/php-qrcode/releases) for valid versions. For PHP version ... - 7.4+ use `^4.2` - 7.2+ use `^3.3` - 7.0+ use `^2.0` - 5.6+ use `1.0.9` (please let PHP 5 die!) -### Usage +### Quickstart We want to encode this URI for a mobile authenticator into a QRcode image: ```php $data = 'otpauth://totp/test?secret=B3JX4VCVJDVNXNZ5&issuer=chillerlan.net'; -//quick and simple: +// quick and simple: echo 'QR Code'; ``` @@ -79,312 +81,7 @@ echo 'QR Code'; QR codes are awesome!

-Wait, what was that? Please again, slower! - -### Advanced usage - -Ok, step by step. First you'll need a `QRCode` instance, which can be optionally invoked with a `QROptions` (or a [`SettingsContainerInterface`](https://github.com/chillerlan/php-settings-container/blob/master/src/SettingsContainerInterface.php), respectively) object as the only parameter. - -```php -$options = new QROptions([ - 'version' => 5, - 'outputType' => QRCode::OUTPUT_MARKUP_SVG, - 'eccLevel' => QRCode::ECC_L, -]); - -// invoke a fresh QRCode instance -$qrcode = new QRCode($options); - -// and dump the output -$qrcode->render($data); - -// ...with additional cache file -$qrcode->render($data, '/path/to/file.svg'); -``` - -In case you just want the raw QR code matrix, call `QRCode::getMatrix()` - this method is also called internally from `QRCode::render()`. See also [Custom output modules](#custom-qroutputinterface). - -```php -$matrix = $qrcode->getMatrix($data); - -foreach($matrix->matrix() as $y => $row){ - foreach($row as $x => $module){ - - // get a module's value - $value = $module; - - // or via the matrix's getter method - $value = $matrix->get($x, $y); - - // boolean check a module - if($matrix->check($x, $y)){ // if($module >> 8 > 0) - // do stuff, the module is dark - } - else{ - // do other stuff, the module is light - } - - } -} -``` - -Have a look [in this folder](https://github.com/chillerlan/php-qrcode/tree/main/examples) for some more usage examples. - -#### Custom module values -You can distinguish between different parts of the matrix, namely the several required patterns from the QR Code specification, and use them in different ways. -The dark value is the module value (light) shifted by 8 bits to the left: `$value = $M_TYPE << ($bool ? 8 : 0);`, where `$M_TYPE` is one of the `QRMatrix::M_*` constants. -You can check the value for a type explicitly like... -```php -// for true (dark) -($value >> 8) === $M_TYPE; - -// for false (light) -$value === $M_TYPE; -``` -...or you can perform a loose check, ignoring the module value -```php -// for true -($value >> 8) > 0; - -// for false -($value >> 8) === 0; -``` - -See also `QRMatrix::set()`, `QRMatrix::check()` and [`QRMatrix` constants](#qrmatrix-constants). - -To map the values and properly render the modules for the given `QROutputInterface`, it's necessary to overwrite the default values: -```php -$options = new QROptions; - -// for HTML, SVG and ImageMagick -$options->moduleValues = [ - // finder - 1536 => '#A71111', // dark (true) - 6 => '#FFBFBF', // light (false) - // alignment - 2560 => '#A70364', - 10 => '#FFC9C9', - // timing - 3072 => '#98005D', - 12 => '#FFB8E9', - // format - 3584 => '#003804', - 14 => '#00FB12', - // version - 4096 => '#650098', - 16 => '#E0B8FF', - // data - 1024 => '#4A6000', - 4 => '#ECF9BE', - // darkmodule - 512 => '#080063', - // separator - 8 => '#AFBFBF', - // quietzone - 18 => '#FFFFFF', -]; - -// for the image output types -$options->moduleValues = [ - 512 => [0, 0, 0], - // ... -]; - -// for string/text output -$options->moduleValues = [ - 512 => '#', - // ... -]; -``` - -#### Custom `QROutputInterface` -Instead of bloating your code you can simply create your own output interface by extending `QROutputAbstract`. Have a look at the [built-in output modules](https://github.com/chillerlan/php-qrcode/tree/main/src/Output). - -```php -class MyCustomOutput extends QROutputAbstract{ - - // inherited from QROutputAbstract - protected QRMatrix $matrix; // QRMatrix - protected int $moduleCount; // modules QRMatrix::size() - protected QROptions $options; // MyCustomOptions or QROptions - protected int $scale; // scale factor from options - protected int $length; // length of the matrix ($moduleCount * $scale) - - // ...check/set default module values (abstract method, called by the constructor) - protected function setModuleValues():void{ - // $this->moduleValues = ... - } - - // QROutputInterface::dump() - public function dump(string $file = null):string{ - $output = ''; - - for($row = 0; $row < $this->moduleCount; $row++){ - for($col = 0; $col < $this->moduleCount; $col++){ - $output .= (int)$this->matrix->check($col, $row); - } - } - - return $output; - } - -} -``` - -In case you need additional settings for your output module, just extend `QROptions`... -``` -class MyCustomOptions extends QROptions{ - protected string $myParam = 'defaultValue'; - - // ... -} -``` -...or use the [`SettingsContainerInterface`](https://github.com/chillerlan/php-settings-container/blob/main/src/SettingsContainerInterface.php), which is the more flexible approach. - -```php -trait MyCustomOptionsTrait{ - protected string $myParam = 'defaultValue'; - - // ... -} -``` -set the options: -```php -$myOptions = [ - 'version' => 5, - 'eccLevel' => QRCode::ECC_L, - 'outputType' => QRCode::OUTPUT_CUSTOM, - 'outputInterface' => MyCustomOutput::class, - // your custom settings - 'myParam' => 'whatever value', - ]; - -// extends QROptions -$myCustomOptions = new MyCustomOptions($myOptions); - -// using the SettingsContainerInterface -$myCustomOptions = new class($myOptions) extends SettingsContainerAbstract{ - use QROptionsTrait, MyCustomOptionsTrait; -}; - -``` - -You can then call `QRCode` with the custom modules... -```php -(new QRCode($myCustomOptions))->render($data); -``` -...or invoke the `QROutputInterface` manually. -```php -$qrOutputInterface = new MyCustomOutput($myCustomOptions, (new QRCode($myCustomOptions))->getMatrix($data)); - -//dump the output, which is equivalent to QRCode::render() -$qrOutputInterface->dump(); -``` - -### API - -#### `QRCode` methods -method | return | description ------- | ------ | ----------- -`__construct(QROptions $options = null)` | - | see [`SettingsContainerInterface`](https://github.com/chillerlan/php-settings-container/blob/main/src/SettingsContainerInterface.php) -`render(string $data, string $file = null)` | mixed, `QROutputInterface::dump()` | renders a QR Code for the given `$data` and `QROptions`, saves `$file` optional -`getMatrix(string $data)` | `QRMatrix` | returns a `QRMatrix` object for the given `$data` and current `QROptions` -`initDataInterface(string $data)` | `QRDataInterface` | returns a fresh `QRDataInterface` for the given `$data` -`isNumber(string $string)` | bool | checks if a string qualifies for `Number` -`isAlphaNum(string $string)` | bool | checks if a string qualifies for `AlphaNum` -`isKanji(string $string)` | bool | checks if a string qualifies for `Kanji` -`isByte(string $string)` | bool | checks if a string is non-empty - -#### `QRCode` constants -name | description ----- | ----------- -`VERSION_AUTO` | `QROptions::$version` -`MASK_PATTERN_AUTO` | `QROptions::$maskPattern` -`OUTPUT_MARKUP_SVG`, `OUTPUT_MARKUP_HTML` | `QROptions::$outputType` markup -`OUTPUT_IMAGE_PNG`, `OUTPUT_IMAGE_JPG`, `OUTPUT_IMAGE_GIF` | `QROptions::$outputType` image -`OUTPUT_STRING_JSON`, `OUTPUT_STRING_TEXT` | `QROptions::$outputType` string -`OUTPUT_IMAGICK` | `QROptions::$outputType` ImageMagick -`OUTPUT_FPDF` | `QROptions::$outputType` PDF, using [FPDF](https://github.com/setasign/fpdf) -`OUTPUT_CUSTOM` | `QROptions::$outputType`, requires `QROptions::$outputInterface` -`ECC_L`, `ECC_M`, `ECC_Q`, `ECC_H`, | ECC-Level: 7%, 15%, 25%, 30% in `QROptions::$eccLevel` -`DATA_NUMBER`, `DATA_ALPHANUM`, `DATA_BYTE`, `DATA_KANJI` | `QRDataInterface::$datamode` - -#### `QROptions` properties -property | type | default | allowed | description --------- | ---- | ------- | ------- | ----------- -`$version` | int | `QRCode::VERSION_AUTO` | 1...40 | the [QR Code version number](http://www.qrcode.com/en/about/version.html) -`$versionMin` | int | 1 | 1...40 | Minimum QR version (if `$version = QRCode::VERSION_AUTO`) -`$versionMax` | int | 40 | 1...40 | Maximum QR version (if `$version = QRCode::VERSION_AUTO`) -`$eccLevel` | int | `QRCode::ECC_L` | `QRCode::ECC_X` | Error correct level, where X = L (7%), M (15%), Q (25%), H (30%) -`$maskPattern` | int | `QRCode::MASK_PATTERN_AUTO` | 0...7 | Mask Pattern to use -`$addQuietzone` | bool | `true` | - | Add a "quiet zone" (margin) according to the QR code spec -`$quietzoneSize` | int | 4 | clamped to 0 ... `$matrixSize / 2` | Size of the quiet zone -`$dataModeOverride` | string | `null` | `Number`, `AlphaNum`, `Kanji`, `Byte` | allows overriding the data type detection -`$outputType` | string | `QRCode::OUTPUT_IMAGE_PNG` | `QRCode::OUTPUT_*` | built-in output type -`$outputInterface` | string | `null` | * | FQCN of the custom `QROutputInterface` if `QROptions::$outputType` is set to `QRCode::OUTPUT_CUSTOM` -`$cachefile` | string | `null` | * | optional cache file path -`$eol` | string | `PHP_EOL` | * | newline string (HTML, SVG, TEXT) -`$scale` | int | 5 | * | size of a QR code pixel (SVG, IMAGE_*), HTML -> via CSS -`$cssClass` | string | `null` | * | a common css class -`$svgOpacity` | float | 1.0 | 0...1 | -`$svgDefs` | string | * | * | anything between [``](https://developer.mozilla.org/docs/Web/SVG/Element/defs) -`$svgViewBoxSize` | int | `null` | * | a positive integer which defines width/height of the [viewBox attribute](https://css-tricks.com/scale-svg/#article-header-id-3) -`$textDark` | string | '🔴' | * | string substitute for dark -`$textLight` | string | '⭕' | * | string substitute for light -`$markupDark` | string | '#000' | * | markup substitute for dark (CSS value) -`$markupLight` | string | '#fff' | * | markup substitute for light (CSS value) -`$imageBase64` | bool | `true` | - | whether to return the image data as base64 or raw like from `file_get_contents()` -`$imageTransparent` | bool | `true` | - | toggle transparency (no jpeg support) -`$imageTransparencyBG` | array | `[255, 255, 255]` | `[R, G, B]` | the RGB values for the transparent color, see [`imagecolortransparent()`](http://php.net/manual/function.imagecolortransparent.php) -`$pngCompression` | int | -1 | -1 ... 9 | `imagepng()` compression level, -1 = auto -`$jpegQuality` | int | 85 | 0 - 100 | `imagejpeg()` quality -`$imagickFormat` | string | 'png' | * | ImageMagick output type, see `Imagick::setType()` -`$imagickBG` | string | `null` | * | ImageMagick background color, see `ImagickPixel::__construct()` -`$moduleValues` | array | `null` | * | Module values map, see [Custom output modules](#custom-qroutputinterface) and `QROutputInterface::DEFAULT_MODULE_VALUES` - -#### `QRMatrix` methods -method | return | description ------- | ------ | ----------- -`__construct(int $version, int $eclevel)` | - | - -`init(int $maskPattern, bool $test = null)` | `QRMatrix` | -`matrix()` | array | the internal matrix representation as a 2 dimensional array -`version()` | int | the current QR Code version -`eccLevel()` | int | current ECC level -`maskPattern()` | int | the used mask pattern -`size()` | int | the absoulute size of the matrix, including quiet zone (if set). `$version * 4 + 17 + 2 * $quietzone` -`get(int $x, int $y)` | int | returns the value of the module -`set(int $x, int $y, bool $value, int $M_TYPE)` | `QRMatrix` | sets the `$M_TYPE` value for the module -`check(int $x, int $y)` | bool | checks whether a module is true (dark) or false (light) - -#### `QRMatrix` constants -name | light (false) | dark (true) | description ----- | ------------- | ----------- | ----------- -`M_NULL` | 0 | - | module not set (should never appear. if so, there's an error) -`M_DARKMODULE` | - | 512 | once per matrix at `$xy = [8, 4 * $version + 9]` -`M_DATA` | 4 | 1024 | the actual encoded data -`M_FINDER` | 6 | 1536 | the 7x7 finder patterns -`M_SEPARATOR` | 8 | - | separator lines around the finder patterns -`M_ALIGNMENT` | 10 | 2560 | the 5x5 alignment patterns -`M_TIMING` | 12 | 3072 | the timing pattern lines -`M_FORMAT` | 14 | 3584 | format information pattern -`M_VERSION` | 16 | 4096 | version information pattern -`M_QUIETZONE` | 18 | - | margin around the QR Code -`M_LOGO` | 20 | - | space for a logo image (not used yet) -`M_TEST` | 255 | 65280 | test value - - -### Notes -The QR encoder, especially the subroutines for mask pattern testing, can cause high CPU load on increased matrix size. -You can avoid a part of this load by choosing a fast output module, like `OUTPUT_IMAGE_*` and setting the mask pattern manually (which may result in unreadable QR Codes). -Oh hey and don't forget to sanitize any user input! - -### Disclaimer! -I don't take responsibility for molten CPUs, misled applications, failed log-ins etc.. Use at your own risk! - -#### Trademark Notice - -The word "QR Code" is registered trademark of *DENSO WAVE INCORPORATED*
-http://www.denso-wave.com/qrcode/faqpatent-e.html +Wait, what was that? Please again, slower! See [Advanced usage](https://github.com/chillerlan/php-qrcode/wiki/Advanced-usage) on the wiki. ### Framework Integration - Drupal [Google Authenticator Login `ga_login`](https://www.drupal.org/project/ga_login) @@ -394,10 +91,17 @@ http://www.denso-wave.com/qrcode/faqpatent-e.html - [Cachet](https://github.com/CachetHQ/Cachet) - other uses: [dependents](https://github.com/chillerlan/php-qrcode/network/dependents) / [packages](https://github.com/chillerlan/php-qrcode/network/dependents?dependent_type=PACKAGE) - +### Shameless advertising Hi, please check out my other projects that are way cooler than qrcodes! - [php-oauth-core](https://github.com/chillerlan/php-oauth-core) - an OAuth 1/2 client library along with a bunch of [providers](https://github.com/chillerlan/php-oauth-providers) - [php-httpinterface](https://github.com/chillerlan/php-httpinterface) - a PSR-7/15/17/18 implemetation - [php-database](https://github.com/chillerlan/php-database) - a database client & querybuilder for MySQL, Postgres, SQLite, MSSQL, Firebird +### Disclaimer! +I don't take responsibility for molten CPUs, misled applications, failed log-ins etc.. Use at your own risk! + +#### Trademark Notice + +The word "QR Code" is registered trademark of *DENSO WAVE INCORPORATED*
+http://www.denso-wave.com/qrcode/faqpatent-e.html