Ähnlich wie mit Dockerumgebungen, kann man in Python Entwicklungsumgebungen kapseln bzw. isolieren. Damit hat man alle Abhängigkeiten innerhalb der Umgebung und kann flexibel zu globalen Pythoninstallation auch andere Paketversionen verwenden.
Außerdem lassen sich auf diese Weise eventuelle Versionskonflikte vermeiden und kann seine Systemumgebung schützen, weil diese unberührt bleibt.
Um eine solche Umgebung zu initialisieren folgendes:
Bash
python3-mvenvface_scrapper
Bash
Im Anschluss aktiviert man diese Umgebung und signalisiert damit, dass alle Aktionen wie Installationen von Abhängigkeiten etc. innerhalb der Umgebung passieren sollen.
Bash
sourceface_scrapper/bin/activate
Bash
Wichtig: Wenn die Umgebung aktiviert ist, sollte man auch eine Veränderung der Prompt im Bash sehen! Bsp.: zsh:
Um sich aus der Umgebung auszuloggen folgt einfach ein
Ich habe dazu eine Videoserie von Stefan Frömken zusammengestellt. Stefan ist ein Urgestein der Typo3-Community und wer könnte besser über dieses Thema referieren.
Grundgerüst
Composer
Für die Initialisierung mit Composer wird die Extension b13/make benutzt. Der Ablauf ähnelt dem Initialisierungsprozess mit NPM. Zu beachten ist hier, ob mit DDEV entwickelt wird oder nicht! Die Entwicklung der Extension wird im src/extensions – Verzeichnis empfohlen. In der Composer.json – Datei im Projektroot empfiehlt sich ein Wildcard anzugeben. Damit muss man nicht für jede weitere Extension einen neuen Eintrag machen.
Über das Backend Verwaltungswerkzeuge > Wartung > Analyze Database Structure kann man die Tabellen anlegen oder Änderungen an der DB ausführen. Am besten man legt vorher noch das TCA an, damit auch dynamisch Spalten aus dem TCA gleich mit in der Tabelle angelegt werden. (bspw. crdate oder deleted etc.)
TCA (Table Configuration Array)
Für die Definition der Felder ist die TCA-Dokumentation unabdingbar. Im Extensionordner legt man nun im Ordner EXT:sales/Configuration/TCA die Dateien tx_sales_campaign.php und tx_sales_objects.php an. Also für jede Tabelle eine eigene TCA.
PHP
<?php/** * TCA for the sales table and its fields in the backend */return['ctrl'=>['title'=>'Verkaufskampagnen','label'=>'titel','tstamp'=>'tstamp','crdate'=>'crdate','delete'=>'deleted','sortby'=>'sorting','default_sortby'=>'titel','versioningWS'=>true,'rootLevel'=>0,//'iconfile' => 'EXT:styleguide/Resources/Public/Icons/tx_styleguide.svg','origUid'=>'t3_origuid','languageField'=>'sys_language_uid','transOrigPointerField'=>'l10n_parent','transOrigDiffSourceField'=>'l10n_diffsource','translationSource'=>'l10n_source','searchFields'=>'titel,beschreibung','security'=>['ignorePageTypeRestriction'=>true,],'enablecolumns'=>['disabled'=>'hidden','starttime'=>'starttime','endtime'=>'endtime',],],'columns'=>['titel'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.titel','config'=>['type'=>'input',],],'beschreibung'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.beschreibung','config'=>['type'=>'text','cols'=>40,'rows'=>5,'eval'=>'trim',],],'endtime'=>['exclude'=>false,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.anzeigen_bis','config'=>['type'=>'input','renderType'=>'inputDateTime','eval'=>'datetime,int',// 'datetime' für die Benutzeroberfläche, 'int' für Speicherung als Timestamp'default'=>0,// Standardwert ist 0],],'starttime'=>['exclude'=>false,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.anzeigen_von','config'=>['type'=>'input','renderType'=>'inputDateTime','eval'=>'datetime,int',// 'datetime' für die Benutzeroberfläche, 'int' für Speicherung als Timestamp'default'=>0,// Standardwert ist 0],],/* Show delete field */'deleted'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.campaign.deleted','config'=>['type'=>'check','renderType'=>'checkboxToggle','items'=>[[0=>'',1=>'','invertStateDisplay'=>true]],],],'hidden'=>['exclude'=>false,'label'=>'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.enabled','config'=>['type'=>'check','renderType'=>'checkboxToggle','items'=>[[0=>'',1=>'','invertStateDisplay'=>true]],]],],'types'=>[['showitem'=>'titel, beschreibung, hidden, starttime, endtime, deleted',],],];
PHP
PHP
<?php/** * TCA for the sales table and its fields in the backend */return['ctrl'=>['title'=>'Verkaufsobjekte','label'=>'bearbeitungsnummer','label_alt'=>'titel','label_alt_force'=>true,'tstamp'=>'tstamp','crdate'=>'crdate','delete'=>'deleted','sortby'=>'sorting','default_sortby'=>'bearbeitungsnummer','versioningWS'=>true,'rootLevel'=>0,//'iconfile' => 'EXT:styleguide/Resources/Public/Icons/tx_styleguide.svg','origUid'=>'t3_origuid','languageField'=>'sys_language_uid','transOrigPointerField'=>'l10n_parent','transOrigDiffSourceField'=>'l10n_diffsource','translationSource'=>'l10n_source','searchFields'=>'titel,bearbeitungsnummer,beschreibung','security'=>['ignorePageTypeRestriction'=>true,],'enablecolumns'=>['disabled'=>'hidden'],],'columns'=>['bearbeitungsnummer'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.bearbeitungsnummer','config'=>['type'=>'input',],],'tx_sales_campaign_uid'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.kampagne','config'=>['type'=>'select','renderType'=>'selectSingle','foreign_table'=>'tx_sales_campaign',// Tabelle für die Kampagnen'maxitems'=>1,// Da es eine 1:n Beziehung ist],],'titel'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.titel','config'=>['type'=>'input',],],'beschreibung'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.beschreibung','config'=>['type'=>'text','cols'=>40,'rows'=>5,'eval'=>'trim',],],'preis'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.preis','config'=>['type'=>'number','size'=>10,'format'=>'decimal','eval'=>'double,required',// 'double' für Gleitkommazahlen, 'required' für Pflichtfeld'placeholder'=>'z.B. 99.99',// Hinweistext im Eingabefeld],],'preisart'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.preisart','config'=>['type'=>'select','renderType'=>'selectSingle','items'=>[['Mindestangebot','Mindestangebot'],['Festpreis','Festpreis'],['Verhandlungsbasis','Verhandlungsbasis']],'default'=>'Festpreis',// Optional: Standardwert festlegen],],'bilder'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.bilder','config'=>['type'=>'inline','foreign_table'=>'sys_file_reference','foreign_field'=>'uid_foreign','foreign_sortby'=>'sorting_foreign','foreign_table_field'=>'tablenames','foreign_match_fields'=>['fieldname'=>'bilder',],'foreign_label'=>'uid_local','foreign_selector'=>'uid_local','overrideChildTca'=>['columns'=>['uid_local'=>['config'=>['appearance'=>['elementBrowserType'=>'file','elementBrowserAllowed'=>'jpg,jpeg,png,gif',],],],],],'filter'=>[['userFunc'=>\TYPO3\CMS\Core\Imaging\IconFactory::class.'->getFilePickerFilter','parameters'=>['allowedFileExtensions'=>'jpg,jpeg,png,gif',],],],'maxitems'=>5,// Maximale Anzahl der hochladbaren Bilder'appearance'=>['collapseAll'=>true,'showSynchronizationLink'=>true,'showAllLocalizationLink'=>true,],],],'uploads'=>['exclude'=>true,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.uploads','config'=>['type'=>'inline','foreign_table'=>'sys_file_reference','foreign_field'=>'uid_foreign','foreign_sortby'=>'sorting_foreign','foreign_table_field'=>'tablenames','foreign_match_fields'=>['fieldname'=>'uploads',],'foreign_label'=>'uid_local','foreign_selector'=>'uid_local','overrideChildTca'=>['columns'=>['uid_local'=>['config'=>['appearance'=>['elementBrowserType'=>'file','elementBrowserAllowed'=>'pdf',],],],],],'filter'=>[['userFunc'=>\TYPO3\CMS\Core\Imaging\IconFactory::class.'->getFilePickerFilter','parameters'=>['allowedFileExtensions'=>'pdf',],],],'maxitems'=>5,// Maximale Anzahl der hochladbaren PDFs'appearance'=>['collapseAll'=>true,'showSynchronizationLink'=>true,'showAllLocalizationLink'=>true,],],],'endtime'=>['exclude'=>false,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.anzeigen_bis','config'=>['type'=>'input','renderType'=>'inputDateTime','eval'=>'datetime,int',// 'datetime' für die Benutzeroberfläche, 'int' für Speicherung als Timestamp'default'=>0,// Standardwert ist 0],],'starttime'=>['exclude'=>false,'label'=>'LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.anzeigen_von','config'=>['type'=>'input','renderType'=>'inputDateTime','eval'=>'datetime,int',// 'datetime' für die Benutzeroberfläche, 'int' für Speicherung als Timestamp'default'=>0,// Standardwert ist 0],],'hidden'=>['exclude'=>false,'label'=>'LLL:EXT:core/Resources/Private/Language/locallang_general.xlf:LGL.enabled','config'=>['type'=>'check','renderType'=>'checkboxToggle','items'=>[[0=>'',1=>'','invertStateDisplay'=>true]],]],],'types'=>[['showitem'=>'bearbeitungsnummer, tx_sales_campaign_uid, titel, beschreibung, preis, preisart, bilder, uploads, hidden, starttime, endtime',],],];
PHP
Systemordner
Wenn über die Extension Datensätze angelegt werden sollen. Dann ist es am besten dafür einen gesonderten Systemordner anzulegen, in dem die Datensätze gespeichert werden sollen.
Über das Listenmodul kann man dann in dem Systemordner neue Datensätze anlegen.
Übersetzungen
Übersetzungen für Plugin, Felder etc. werden in folgendem Ordner angelegt EXT:Resources/Private/Language. Für Deutsch bspw: de.locallang_db.xlf. Wie auf die Sprachen referenziert wird, sieht man im TCA. (bspw: LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.object.anzeigen_von)
XML
<?xml version="1.0" encoding="utf-8" standalone="yes"?><xliffversion="1.0"><filesource-language="en"datatype="plaintext"original="messages"date="2024-10-25T13:36:39Z"product-name="sales"><header/><body><!-- Kampagnen --><trans-unitid="tx_sales_sale.campaign.titel"><source>Title</source><target>Titel</target></trans-unit><trans-unitid="tx_sales_sale.campaign.beschreibung"><source>Description</source><target>Beschreibung</target></trans-unit><trans-unitid="tx_sales_sale.campaign.zuordnung"><source>Assignment</source><target>Zuordnung</target></trans-unit><trans-unitid="tx_sales_sale.campaign.anzeigen_von"><source>Publishing date</source><target>Veröffentlichungsdatum</target></trans-unit><trans-unitid="tx_sales_sale.campaign.anzeigen_bis"><source>Expiry date</source><target>Ablaufdatum</target></trans-unit><!-- Verkäufe --><trans-unitid="tx_sales_sale.object.bearbeitungsnummer"><source>processing number</source><target>Bearbeitungsnummer</target></trans-unit><trans-unitid="tx_sales_sale.object.titel"><source>Title</source><target>Titel</target></trans-unit><trans-unitid="tx_sales_sale.object.preis"><source>Price (in Euro)</source><target>Preis (in Euro)</target></trans-unit><trans-unitid="tx_sales_sale.object.preisart"><source>Pricetype</source><target>Preisart</target></trans-unit><trans-unitid="tx_sales_sale.object.beschreibung"><source>Description</source><target>Beschreibung</target></trans-unit><trans-unitid="tx_sales_sale.object.kampagne"><source>Campaign</source><target>Kampagne</target></trans-unit><trans-unitid="tx_sales_sale.object.bilder"><source>Images</source><target>Bilder</target></trans-unit><trans-unitid="tx_sales_sale.object.uploads"><source>Documents</source><target>Dokumente</target></trans-unit><!-- Plugin --><trans-unitid="tx_sales_sale.pluginlabel"><source>List sales</source><target>Verkäufe auflisten</target></trans-unit><trans-unitid="tx_sales_sale.plugindescription"><source>List sales of campaings of the organisation</source><target>Füge dieses Plugin hinzu, um Verkäufe von Kampagnen der Organisation aufzulisten</target></trans-unit></body></file></xliff>
XML
Feldspezifische Berechtigungen im Backend (anlegen, ändern, etc.)
Um Felder nur speziellen Benutzergruppen editierbar, anlegbar zur Verfügung zu stellen, muss im TCA an dem entsprechenden Feld exclude aus true gesetzt sein. Damit ist es per Default erstmal nicht verfügbar. Dann muss es in der Benutzergruppe in den Zugriffsrechten unter Erlaubte Ausschlussfelder explizit freigegeben werden.
Plugin für Backend
Im Pluginmanager verfügbar machen
Als erstes legt man unter EXT:sales/Configuration/TCA/Overrides eine Datei tt_content.php an. In dieser wird das Plugin registriert.
PHP
<?phpuse TYPO3\CMS\Extbase\Utility\ExtensionUtility;ExtensionUtility::registerPlugin('Sales','list','LLL:EXT:sales/Resources/Private/Language/locallang_db.xlf:tx_sales_sale.pluginlabel','tx-sales-svgicon'// Has to be defined in EXT:Configuration/Icons.php);
PHP
Damit sollte das Plugin dann schon auswählbar sein. (Cache löschen nicht vergessen!)
Typoscript des Plugins verfügbar machen
Um später Typoscript aus der Extension im Backend verfügbar zu machen legen wir ebenfalls in dem Verzeichnis eine sys_template.php mit folgendem Inhalt an. Damit ist sämtlicher TypoScript-Code im Verzeichnis Configuration/TypoScript verfügbar. Das Template wird dann im Backend unter Template > Rootseite wählen > Gesamtes Typoscript bearbeiten > Erweiterte Optionen eingebunden. In dem Typoscript wird bspw. festgelegt, wo die HTML-Templates für die Views liegen.
PHP
<?phpuse TYPO3\CMS\Core\Utility\ExtensionManagementUtility;/** * Make the extension configuration accessible for TYPO3 Template */ExtensionManagementUtility::addStaticFile('sales','Configuration/TypoScript','TS template for sales');
PHP
Content Element Wizard
Der Content Element Wizard beinhaltet bspw. die Pluginübersicht.
Wenn man das Plugin auch schon direkt im Content Element Wizard auswählen können soll, muss noch folgendes TypoScript ergänzt werden. (EXT:sales/Configuration/TSConfig/Page/ContentElementWizard.tsconfig)
Plaintext
# Configuration for Content Element Wizardmod.wizards { newContentElement.wizardItems { plugins { elements { tenders_list { iconIdentifier = tx-tenders-svgicon title = LLL:EXT:tenders/Resources/Private/Language/locallang_db.xlf:tx_tenders_tender.pluginlabel description = LLL:EXT:tenders/Resources/Private/Language/locallang_db.xlf:tx_tenders_tender.plugindescription tt_content_defValues { CType = list list_type = tenders_list header = LLL:EXT:tenders/Resources/Private/Language/locallang_db.xlf:tx_tenders_tender.pluginlabel } } } } }}# Add CType Previewmod.web_layout.tt_content.preview.list.sales_list = EXT:sales/Resources/Private/Templates/PluginPreview/Show.html
Plaintext
In Zeile 22 wird noch die Ansicht des ContentTypes in der Seite selbst mit einem Template verfeinert. So sieht man schon in der Übersicht, aus welchem Ordner sich die Extension bedient. Das Template EXT:sales/Resources/Private/Templates/PluginPreview/Show.html sieht wie folgt aus.
Das Icon im SVG-Format legt man unter EXT:Resources/Public/Icons ab. (bspw. sales.svg). Unter EXT:Configuration legt man eine Icons.php an, in der man den Icon-Identifier bescheibt.
PHP
<?phpdeclare(strict_types=1);use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;return[// Icon identifier'tx-sales-svgicon'=>[// Icon provider class'provider'=>SvgIconProvider::class,// The source SVG for the SvgIconProvider'source'=>'EXT:sales/Resources/Public/Icons/sales.svg',]];
PHP
Frontendanbindung
Extbase für das Datenhandling
Alle Klassen für das Plugin kommen ins Verzeichnis EXT:sales/Classes. Einstiegspunkt ist der Controller. Der EXT:sales/Classes/Controller/SaleController.php sieht wie folgt aus.
PHP
<?phpdeclare(strict_types=1);namespace OeKonzept\Sales\Controller;useInvalidArgumentException;use OeKonzept\Sales\Domain\Model\Sale;use OeKonzept\Sales\Domain\Repository\SaleRepository;use Psr\Http\Message\ResponseInterface;use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;classSaleControllerextendsActionController{/** * @var\OeKonzept\Sales\Domain\Repository\SaleRepository */protected$saleObjectRepository;publicfunctioninjectSaleRepository(SaleRepository$salesObjectRepository){$this->saleObjectRepository=$salesObjectRepository;}/** * Action to list all sales objects * * @returnResponseInterface * @throwsInvalidArgumentException */publicfunctionlistAction(){$salesObjects=$this->saleObjectRepository->findSalesWithCampaigns();$this->view->assign('sales',$salesObjects);return$this->responseFactory->createResponse()->withHeader('Content-Type','text/html; charset=utf-8')->withBody($this->streamFactory->createStream($this->view->render()));}/** * Action to show a single sales object * * @paramSale $salesObject * @returnResponseInterface * @throwsInvalidArgumentException */publicfunctionshowAction(Sale$sale){$this->view->assign('sale',$sale);return$this->responseFactory->createResponse()->withHeader('Content-Type','text/html; charset=utf-8')->withBody($this->streamFactory->createStream($this->view->render()));}}
PHP
Der Controller bekommt seine Daten aus dem Repository. Das Repo ist zuständig für die Datenbeschaffung und der Controller ist damit von der Datenquelle entkoppelt. Das EXT:sales/Classes/Domain/SaleRepository.php kann recht leer sein, da es die Grundfunktionalitäten vom Extbase Repository erbt.
Damit Extbase die einzelnen Datensätze in ein Model packen kann, erstellt man ein Domain Model dafür. (EXT:sales/Classes/Domain/Model/Sale.php)
PHP
<?phpnamespace OeKonzept\Sales\Domain\Model;use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;classSaleextendsAbstractEntity{protectedstring$bearbeitungsnummer='';protectedstring$titel='';protectedfloat$preis=0.0;protectedstring$preisart='';protectedstring$beschreibung='';protected\TYPO3\CMS\Extbase\Domain\Model\FileReference$bilder;protected\TYPO3\CMS\Extbase\Domain\Model\FileReference$uploads;protectedint$tx_sales_campaign_uid=0;/** * Get the value of bearbeitungsnummer */publicfunctiongetBearbeitungsnummer():string{return$this->bearbeitungsnummer;}/** * Set the value of bearbeitungsnummer */publicfunctionsetBearbeitungsnummer(string$bearbeitungsnummer):self{$this->bearbeitungsnummer=$bearbeitungsnummer;return$this;}/** * Get the value of titel */publicfunctiongetTitel():string{return$this->titel;}/** * Set the value of titel */publicfunctionsetTitel(string$titel):self{$this->titel=$titel;return$this;}/** * Get the value of preis */publicfunctiongetPreis():float{return$this->preis;}/** * Set the value of preis */publicfunctionsetPreis(float$preis):self{$this->preis=$preis;return$this;}/** * Get the value of preisart */publicfunctiongetPreisart():string{return$this->preisart;}/** * Set the value of preisart */publicfunctionsetPreisart(string$preisart):self{$this->preisart=$preisart;return$this;}/** * Get the value of beschreibung */publicfunctiongetBeschreibung():string{return$this->beschreibung;}/** * Set the value of beschreibung */publicfunctionsetBeschreibung(string$beschreibung):self{$this->beschreibung=$beschreibung;return$this;}/** * Get the value of bilder */publicfunctiongetBilder():\TYPO3\CMS\Extbase\Domain\Model\FileReference{return$this->bilder;}/** * Set the value of bilder */publicfunctionsetBilder(\TYPO3\CMS\Extbase\Domain\Model\FileReference$bilder):self{$this->bilder=$bilder;return$this;}/** * Get the value of uploads */publicfunctiongetUploads():\TYPO3\CMS\Extbase\Domain\Model\FileReference{return$this->uploads;}/** * Set the value of uploads */publicfunctionsetUploads(\TYPO3\CMS\Extbase\Domain\Model\FileReference$uploads):self{$this->uploads=$uploads;return$this;}/** * Get the value of tx_sales_campaign_uid */publicfunctiongetTxSalesCampaignUid():int{return$this->tx_sales_campaign_uid;}/** * Set the value of tx_sales_campaign_uid */publicfunctionsetTxSalesCampaignUid(int$tx_sales_campaign_uid):self{$this->tx_sales_campaign_uid=$tx_sales_campaign_uid;return$this;}}
PHP
Extbase wird mit der entsprechenden Tabelle, welche die Daten für das Model enthält in EXT:sales/Configuration/Extbase/Persistance/Classes.php verbunden.
PHP
<?php/** * Mapping of classes to tables */declare(strict_types=1);return[\OeKonzept\Sales\Domain\Model\Sale::class=>['tableName'=>'tx_sales_object',]];
PHP
Der Controller für das Plugin muss konfiguriert werden in der EXT:sales/ext_localconf.php.
Delete „gradle-2.13-all.zip“ folder and everything in this directory: C:\Users\Somnath Sarkar.gradle\wrapper\dists\gradle-2.13all\7hsc6vr6mi3i6i5m7q9hj4ci1q\
Download the gradle zip manually
Paste the gradle zip folder in C:\Users\Somnath Sarkar.gradle\wrapper\dists\gradle-2.13-all\7hsc6vr6mi3i6i5m7q9hj4ci1q\
Wenn das Problem auftritt, muss in den Project Setting das Build System von „New Build System“ auf „Legacy Build System“ umgestellt werden:
Xcode 10: A valid provisioning profile for this executable was not found
Xcode 10: A valid provisioning profile for this executable was not found
Since yesterday I’ve been getting the following error when trying run an app on my device: „A valid provisioning profile for this executable was not found.“. This is after updating to Xcode 10. Bui…
Problem: Server welche sich hinter einem NAT befinden, sind mit der eigenen IP-Adresse nach außen nicht erreichbar. Entsprechend können über die Server-IP keine FTP-Operationen ausgeführt werden. Die Lösung liegt darin, über die öffentliche Serveradresse zu kommunizieren. Das heißt, dem PHP zu sagen, dass es nicht die Adresse nutzen soll welche der Server versucht zu vermitteln, sondern die mit der sich ursprünglich verbunden wurde. Das erreicht man über folgende FTP-Option:
Um dir ein optimales Erlebnis zu bieten, verwenden wir Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wenn du diesen Technologien zustimmst, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn du deine Zustimmung nicht erteilst oder zurückziehst, können bestimmte Merkmale und Funktionen beeinträchtigt werden.
Funktional
Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt.Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.