PHP – Bitkorn Blog https://blog.bitkorn.de Developer Zeugz Wed, 18 Jan 2023 06:47:08 +0000 de-DE hourly 1 https://wordpress.org/?v=6.3.1 PHP Kompatibilität Check https://blog.bitkorn.de/php-kompatibilitaet-check/ Fri, 13 Jan 2023 06:46:39 +0000 https://blog.bitkorn.de/?p=1198 PHPCompatibility

PHPCSStandards/composer-installer

…mit composer global installieren.

Damit das globale Composer Zeug komfortabel in der Bash funktioniert, Folgendes in die ~/.profile

# composer global packages
if [ -d "$HOME/.config/composer/vendor/bin" ] ; then
    export PATH="$HOME/.config/composer/vendor/bin:$PATH"
fi

Konfiguration

PHP_CodeSniffer/wiki/Configuration-Options
…im Terminal z.B. (severity=5 macht ne riesige Ausgabe – mit lauter „nice to have“ Zeug):

phpcs --config-set severity 6

…steht dann in ~/.config/composer/vendor/squizlabs/php_codesniffer/CodeSniffer.conf
…wo man die Werte auch manuell ändern kann.

run

Dann kann man beliebige Projekte auf Kompatibilität prüfen:

phpcs -p /var/www/html/myPhpProject/

…oder, die Ausgabe in eine Datei schreiben, falls sie zu lang ist:

phpcs -p /var/www/html/myPhpProject/ > ~/Downloads/myPhpProjectSniffer8-1
]]>
filter_input_array() UUIDs https://blog.bitkorn.de/filter_input_array-uuids/ Sun, 07 Nov 2021 07:13:38 +0000 https://blog.bitkorn.de/?p=1060 Code sagt mehr als tausend Worte:

<?php
/**
 * Use a callback function to filter UUIDs from POST with filter_input_array()
 * c0fc2876-2551-426b-8cc1-69730d22774a
 * 2c91ff35-7089-4383-91e3-0976a7bf06a9
 * ddc25d51-d2a7-4b32-9ca8-3cf70d89dffb
 */
require '../../vendor/autoload.php';

use Laminas\Validator\Uuid;

$uuid = new Uuid();
function filterUuid(string $value): string
{
    global $uuid;
    return $uuid->isValid($value) ? $value : '';
}

class MyStaticFilter
{
    protected static Uuid $uuid;

    public static function filterUuid(string $value): string
    {
        if (!isset(self::$uuid)) {
            self::$uuid = new Uuid();
        }
        return self::$uuid->isValid($value) ? $value : '';
    }
}

class MyFilter
{
    protected Uuid $uuid;

    public function filterUuid(string $value): string
    {
        if (!isset($this->uuid)) {
            $this->uuid = new Uuid();
        }
        return $this->uuid->isValid($value) ? $value : '';
    }
}

$myFilter = new MyFilter();

$call = (int)filter_input(INPUT_POST, 'callback', FILTER_SANITIZE_NUMBER_INT);
switch ($call) {
    case 1:
        $uuids = filter_input_array(INPUT_POST, ['anuuid' => [
            'filter'  => FILTER_CALLBACK,
            'flags'   => FILTER_REQUIRE_ARRAY,
            'options' => 'filterUuid',
        ]]);
        break;
    case 2:
        $uuids = filter_input_array(INPUT_POST, ['anuuid' => [
            'filter'  => FILTER_CALLBACK,
            'flags'   => FILTER_REQUIRE_ARRAY,
            'options' => ['MyStaticFilter', 'filterUuid'],
        ]]);
        break;
    case 3:
        $uuids = filter_input_array(INPUT_POST, ['anuuid' => [
            'filter'  => FILTER_CALLBACK,
            'flags'   => FILTER_REQUIRE_ARRAY,
            'options' => [$myFilter, 'filterUuid'],
        ]]);
        break;
    default:

}

$uuids = $uuids['anuuid'] ?? [];
?>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="utf-8">
    <title>filter uuid</title>
    <link href="../../../w3.css" media="screen" rel="stylesheet" type="text/css">
<body>
<div class="w3-container">
    <form action="filter-uuid.php" method="post" style="width: 400px">
        <label class="w3-block">1. UUID <input type="text" class="w3-input" name="anuuid[]" value="<?php echo $uuids[0] ?? '' ?>"></label>
        <label class="w3-block">2. UUID <input type="text" class="w3-input" name="anuuid[]" value="<?php echo $uuids[1] ?? '' ?>"></label>
        <label class="w3-block">4. UUID <input type="text" class="w3-input" name="anuuid[]" value="<?php echo $uuids[2] ?? '' ?>"></label>
        <select class="w3-select" name="callback">
            <option value="1" <?php echo $call == 1 ? 'selected="selected"' : '' ?>>function</option>
            <option value="2" <?php echo $call == 2 ? 'selected="selected"' : '' ?>>static</option>
            <option value="3" <?php echo $call == 3 ? 'selected="selected"' : '' ?>>object</option>
        </select>
        <button type="submit" class="w3-button w3-blue-gray">ok</button>
    </form>
</div>
<div class="w3-container">
    <pre><?= print_r($uuids, true) ?></pre>
</div>
</body>

https://www.php.net/manual/de/function.filter-input-array

https://www.php.net/manual/en/filter.filters.misc.php

https://www.php.net/manual/de/language.types.callable.php

]]>
ViewHelper im Service benutzen https://blog.bitkorn.de/viewhelper-im-service-benutzen/ Fri, 23 Jul 2021 09:13:59 +0000 https://blog.bitkorn.de/?p=1004 Zuerst etwas config:

'view_helpers'        => [
    'aliases'    => [
    ],
    'factories'  => [
        FooterHtml::class => FooterHtmlFactory::class,
    ],

In einer Factory den ViewHelperManager/HelperPluginManager holen und ausführen:

/** @var HelperPluginManager $pluginManager */
$pluginManager = $container->get('ViewHelperManager');
/** @var FooterHtml $footerHtml */
$footerHtml = $pluginManager->get(FooterHtml::class);
$some->setUserdataFooterHtml($footerHtml());

Und der ViewHelper:

class FooterHtml extends AbstractViewHelper
{
    const TEMPLATE = 'lerpDocumentTcpdf/footerHtml';

    protected string $brandColor;

    public function setBrandColor(string $brandColor): void
    {
        $this->brandColor = $brandColor;
    }

    /**
     * @return string
     */
    public function __invoke(): string
    {
        $viewModel = new ViewModel();
        $viewModel->setTemplate(self::TEMPLATE);
        $viewModel->setVariable('colorBrand', $this->brandColor);
        return $this->getView()->render($viewModel);
    }
}
]]>
Custome Post Type template https://blog.bitkorn.de/custome-post-type-template/ Tue, 28 Apr 2020 08:20:34 +0000 http://blog.bitkorn.de/?p=756 Erstelle ich ein Template „single-block_part.php“, kann ich dem Template mitteilen, in welchen Post Typen es verfügbar sein soll.

Dazu müssen zwei Dinge in die obersten Kommentare:

<?php
/**
Template Name: Part Block
Template Post Type: post, page, block_part
 *
 * ...
 *
 */

get_header(); ?>

Die Dinge hinter Template Post Type: geben an, in welchen Post Typen dieses Template zur Auswahl steht.
Für den Post Type „block_part“ wird dieses Template automatisch genommen, weil das der Dateiname (single-block_part.php) vor gibt. Wenn wir ihn hier trotzdem angeben, kann man bei Posts diesen Typs das Template auch auswählen.

]]>
install SSL Zertifikate in Linux https://blog.bitkorn.de/install-ssl-zertifikate/ Tue, 24 Mar 2020 11:32:07 +0000 http://blog.bitkorn.de/?p=746 Sicherheit => SSL/TLS-Zertifikate ein Cert aussuchen und bei „CA-Zertifikat (*-ca.crt)“ das cert kopieren (für die *.crt Datei).]]> benutze Ubuntu 🙂

cd /usr/local/share/ca-certificates/
sudo mkdir mycerts
# kopiere die *.crt Datei da rein, oder auch ohne extra Ordner
# chmod 755 für den Ordner, 644 für die Datei
sudo update-ca-certificates

Um z.B. das Email Server cert aus einem Plesk zu holen:
In
Tools & Einstellungen => Sicherheit => SSL/TLS-Zertifikate
ein Cert aussuchen und bei „CA-Zertifikat (*-ca.crt)“ das cert kopieren (für die *.crt Datei).

]]>
ZF3 Pdo_Pgsql LastGeneratedValue https://blog.bitkorn.de/zf3-pdo_pgsql-lastgeneratedvalue/ Sat, 28 Dec 2019 15:31:02 +0000 http://blog.bitkorn.de/?p=702 Nur mit Angabe der Sequence funktioniert es:

$lastId = $this->getAdapter()->getDriver()->getConnection()->getLastGeneratedValue('public.seq_some_name');

stackoverflow

]]>
PHPStorm Xdebug (2 und 3) https://blog.bitkorn.de/phpstorm-xdebug/ Thu, 28 Nov 2019 11:51:00 +0000 http://blog.bitkorn.de/?p=671 PhpStorm IDE & Xdebug 2

Wie ermögliche ich einfaches Debuggen mit Xdebug und PhpStorm?

Zuerst legt man eine eigene php.ini (yourname.user.ini) in /etc/php/ an. Diese muss in allen installierten PHP Versionen verlinkt (z.B. /etc/php/7.4/apache2/conf.d/yourname.user.ini) sein. Bsw. für PHP 7.4 in der Konsole einen symbolischen Link auf unsere eigene php.ini machen:

sudo ln -s /etc/php/yourname.user.ini /etc/php/7.4/apache2/conf.d/yourname.user.ini

Xdebug Teil der yourname.user.ini:

[Xdebug]
zend_extension=xdebug.so
xdebug.remote_enable=true
xdebug.remote_autostart=true
xdebug.remote_port=9000
xdebug.idekey=PHPSTORM

Dann Xdebug installieren und den Server neu starten:

sudo apt install php-xdebug
sudo systemctl restart apache2

Jetzt ist Xdebug und PHP bereit um gemeinsam mit PhpStorm zu debuggen 🙂

PhpStorm Settings

In PhpStorm unter Settings => Languages & Frameworks => PHP => Debug sind die Einstellungen für das Debuggen. Außer den Einstellungen, an denen ich nichts ändern musste, gibt es eine Möglichkeit die Xdebug Server Konfiguration zu validieren …also, ob alles OK ist zum Debuggen mit PhpStorm.

PhpStorm debugging

In PhpStorm den Hörer (zwei rechts neben dem Käfer) klicken! Dank der Xdebug Einstellung xdebug.remote_autostart=1 kann man jeden PHP Request debuggen.

Xdebug 3.x

Auf der Xdebug Seite gibt es einen Upgrade Guide.

Xdebug: Step Debugging

Die PhpStorm Version muss mindestens 2020.3 sein.

Xdebug Teil meiner yourname.user.ini:

[Xdebug]
# zend_extension=xdebug.so # steht in der 20-xdebug.ini
# xdebug.mode=debug # xdebug 3.x - muss direkt in die 20-xdebug.ini | php.ini
xdebug.client_host=localhost # xdebug 3.x
xdebug.client_port=9003 # xdebug 3.x
xdebug.start_with_request=yes # xdebug 3.x
# xdebug.idekey=PHPSTORM # muss direkt in die 20-xdebug.ini | php.ini
# xdebug.discover_client_host=1 # muss direkt in die 20-xdebug.ini | php.ini

Eine Leerzeile am Ende, sonst: PHP: syntax error, unexpected TC_STRING in

Der xdebug.client_port (9003) muss auch in PhpStorm unter Settings => Languages & Frameworks => PHP => Debug gesetzt sein.

In PhpStorm unter Settings => Languages & Frameworks => PHP => Debug – und dort oben im Punkt eins „validate“ klicken. Da muss der richtige Pfad gesetzt sein (Laminas /public).

Ob der IDE Key gesetzt ist – mit phpinfo() gucken.

PhpStorm – Configure Xdebug

Das Browser Plugin XDebug muss den richtigen key (xdebug.idekey=PHPSTORM) konfiguriert haben.

Xdebug Log:
In die xdebug.ini:

xdebug.log="/home/allapow/xdebug.log"

…das File muss existieren und beschreibbar sein.

Die komplette xdebug.ini:

zend_extension=xdebug.so
xdebug.mode=debug
xdebug.idekey=PHPSTORM
xdebug.log="/home/allapow/xdebug.log"
# xdebug.show_error_trace = 1
xdebug.discover_client_host=1 # important

WICHTIG als boolean Wert funktioniert „yes“ | „true“ nicht – stattdessen muss „1“ benutzt werden (siehe Code Beispiele).

CLI

Um CLI Programme zu debuggen, muss eine Linux Umgebungsvariable gesetzt sein:

export XDEBUG_SESSION=1

…siehe Xdebug Doku.

Wirklich funktionieren tut es mit (xdebug 2):

export XDEBUG_CONFIG="remote_enable=1 remote_mode=req remote_host=127.0.0.1 remote_port=9000 remote_connect_back=0"

…siehe PhpStorm Hilfe.

In PHPStorm muss zusätzlich noch – wie immer beim Debuggen – der Käfer-Hörer geklickt werden.

]]>
EventManager and Listener class https://blog.bitkorn.de/eventmanager-and-listener-class/ Sat, 13 Jul 2019 11:36:12 +0000 http://blog.bitkorn.de/?p=629 Ein Listener:

namespace Lcamo\CamoTransfer\Event;

use Zend\EventManager\AbstractListenerAggregate;
use Zend\EventManager\EventInterface;
use Zend\EventManager\EventManagerInterface;
use Zend\Log\Logger;

class CamoListener extends AbstractListenerAggregate
{
    protected $listeners = [];

    /**
     * @var Logger
     */
    protected $logger;

    /**
     * @param Logger $logger
     */
    public function setLogger(Logger $logger): void
    {
        $this->logger = $logger;
    }

    /**
     * Attach one or more listeners
     *
     * Implementors may add an optional $priority argument; the EventManager
     * implementation will pass this to the aggregate.
     *
     * @param EventManagerInterface $events
     * @param int $priority
     * @return void
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $this->listeners[] = $events->attach('before_login', array($this, 'beforeLogin'));
    }

    public function beforeLogin(EventInterface $event)
    {
        $params = $event->getParams();
        $this->logger->info(print_r($params, true));
    }
}

Factory des Listeners (hier bekommt der Listener den EventManager vom UserService injiziert:

namespace Lcamo\CamoTransfer\Factory;

use Bitkorn\User\Service\UserService;
use Interop\Container\ContainerInterface;
use Lcamo\CamoTransfer\Event\CamoListener;
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
use Zend\ServiceManager\Exception\ServiceNotFoundException;
use Zend\ServiceManager\Factory\FactoryInterface;

class CamoListenerFactory implements FactoryInterface
{

    /**
     * Create an object
     *
     * @param ContainerInterface $container
     * @param string $requestedName
     * @param null|array $options
     * @return object
     * @throws ServiceNotFoundException if unable to resolve the service.
     * @throws ServiceNotCreatedException if an exception is raised when
     *     creating a service.
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        /** @var UserService $userService */
        $userService = $container->get(UserService::class);
        $eventManager = $userService->getEvents();
        $listener = new CamoListener();
        $listener->setLogger($container->get('logger'));
        $listener->attach($eventManager);
        return $listener;
    }
}

Den Listener in der /config/application.config.php eintragen:

use Lcamo\CamoTransfer\Event\CamoListener;

return [
    // Retrieve list of modules used in this application.
    'modules' => require __DIR__ . '/modules.config.php',
    'listeners' => [
        CamoListener::class
    ],
    // These are various options for the listeners attached to the ModuleManager
    'module_listener_options' => [
        // This should be an array of paths in which modules reside.
        // If a string key is provided, the listener will consider that a module
        // namespace, the value of that key the specific path to that module's
        // Module class.
        'module_paths' => [
            './module',
            './vendor',
        ],

        // An array of paths from which to glob configuration files after
        // modules are loaded. These effectively override configuration
        // provided by modules themselves. Paths may use GLOB_BRACE notation.
        'config_glob_paths' => [
            realpath(__DIR__) . '/autoload/{{,*.}global,{,*.}local}.php',
        ],
        // ...
];

Und der UserService, der den EventManager hält und das Event triggert:

namespace Bitkorn\User\Service;

use Zend\EventManager\EventManager;

class UserService
{

    /**
     * @var EventManager
     */
    protected $events;

    /**
     * @return EventManager
     */
    public function getEvents(): EventManager
    {
        return $this->events;
    }

    /**
     *
     * @param string $login
     * @param string $password
     * @return bool
     */
    public function loginWithLoginAndPassword(string $login, string $password): bool
    {
        $this->events->trigger('before_login', $this, ['login' => $login, 'passwd' => $password]);

        /**
         * ...some other stuff
         */
        return true;
    }

    /**
     * ...some other stuff
     */
}

U.a. Dank an Samsonasik.

]]>
createDriver expects a „driver“ key to be present inside the parameters https://blog.bitkorn.de/createdriver-expects-a-driver-key-to-be-present-inside-the-parameters/ Sat, 25 May 2019 09:34:13 +0000 http://blog.bitkorn.de/?p=602 Ist man im Development Mode braucht es einen default Datenbank Adapter in /config/autoload/db.local-development.php.

    'db' => array(
        // for primary db adapter that called
        // by $sm->get('Zend\Db\Adapter\Adapter')
        // required in development mode
        'username' => $dbParams['username'],
        'password' => $dbParams['password'],
        'driver' => 'Pdo_Pgsql',
        'dsn' => 'pgsql:dbname=' . $dbParams['database'] . ';host=' . $dbParams['hostname'],
        'adapters' => array(
            'dbDefault' => array(
                'username' => $dbParams['username'],
                'password' => $dbParams['password'],
                'driver' => 'Pdo_Pgsql',
                'dsn' => 'pgsql:dbname=' . $dbParams['database'] . ';host=' . $dbParams['hostname']
            ),
        ),
    ),

zend-developer-tools/issues/224#issuecomment-246174677

Bei der Zend Skeleton Application ist man zu Begin im Development Mode
Development Mode ausschalten:

vendor/bin/zf-development-mode disable

oder einschalten:

vendor/bin/zf-development-mode enable

Im Development Mode hat man die Developer Toolbar.

]]>
Redis in Ubuntu 18.04 für PHP https://blog.bitkorn.de/redis-in-ubuntu-18-04-fuer-php/ Sat, 29 Dec 2018 09:59:09 +0000 http://blog.t-brieskorn.de/?p=533 ) Die Ausgabe sollte pong sein. Mit STRG+C kann man die Redis Konsole verlassen. Starten und Stoppen des Redis Server mit Hausmitteln: Die config Datei für Redis liegt in /etc/redis/. Nach Änderungen in dieser Datei den Redis Server neu starten: Redis-PHP installieren: github.com/phpredis/phpredis …Datentyp […]]]> Redis Server installieren

sudo apt install redis-server

Redis Server testen:

redis-cli

…gibt uns eine Redis Konsole (127.0.0.1:6379>)

ping

Die Ausgabe sollte pong sein.
Mit STRG+C kann man die Redis Konsole verlassen.

Starten und Stoppen des Redis Server mit Hausmitteln:

sudo systemctl enable redis-server.service

Die config Datei für Redis liegt in /etc/redis/. Nach Änderungen in dieser Datei den Redis Server neu starten:

sudo systemctl restart redis-server.service

Redis-PHP installieren:

sudo apt install php-redis
sudo systemctl restart apache2

github.com/phpredis/phpredis

…Datentyp Hash:
github.com/phpredis/phpredis#hashes

]]>