(...) wenn ich jetzt z.b. ein kleines grafisches Programm,schrieben will (...)

So lange du mit einfachen Grundbausteinen (Listen, Kontrollstrukturen, OOP) noch nicht vertraut bist, wäre es besser, sich erst einmal darauf zu fokussieren, statt bereits mit fortgeschritteneren Themen agieren zu wollen.

Mit einsteigerfreundlichen Modulen wie turtle oder Processing.py gelangt man ebenso zu visuellen Erfolgserlebnissen.

(...) woher weiß ich dann das ich erst was importieren muss (...)

Plane im Voraus. Du musst erst erfassen, was dein Programm tun/können soll und im Anschluss kannst du schauen, welcher Teilschritte es dafür zu lösen bedarf. Ich habe erst gestern mehr in diesem Beitrag dazu geschrieben.

Wenn du dabei merkst, dass du z.B. eine Netzwerkverbindung herstellen musst, wäre es gut, nach einem Modul zu suchen, welches dich dabei unterstützt, da du so etwas kaum selbst von neu aufbauen möchtest. Erste Anlaufstellen wären die Dokumentation (in der alle Module der Standardbibliothek aufgelistet werden) oder ein Package-Repository wie PyPi, welches externe Bibliotheken führt.

Für genauere Informationen zu einem Modul (was es beinhaltet, wie man es nutzen kann, etc.) solltest du immer in die entsprechende Dokumentation schauen. Bei externen Bibliotheken auf PyPi solltest du dir die jeweilige Moduldetailseite durchlesen, denn sie beinhaltet auch Links zu den offiziellen Manuals o.ä. oder manchmal sogar Kurzanleitungen).

...zur Antwort

JetBrains IntelliJ ist in erster Linie eine Java-IDE. Den Support für Python müsstest du dir erst einmal einrichten. Empfehlenswerter wäre es allerdings, sich stattdessen JetBrains PyCharm zu holen, denn das ist eine direkt auf Python-fokussierte IDE.

Die Paketverwaltung wird in deren Dokumentation beschrieben. Über diesen Weg kannst du dir auch den Discord-Wrapper für Python von PyPi herunterladen und ihn anschließend in deinem Projekt einbinden.

...zur Antwort

Ich verstehe nicht, wieso der Tutor sich dafür ein extra Skript schreibt. Die Funktionalität liefert IntelliJ bereits von sich aus. Du brauchst lediglich eine entsprechende Run Configuration anlegen. Ein komplettes Tutorial, wie man ein Java-Programm in IntelliJ anlegt, dazu eine JAR deployt und sie ausführt, findest du ebenso in der JetBrains-Dokumentation (siehe Create your first Java application).

Bezüglich der Fehlermeldung: Entweder kann das System die Datei nicht finden oder hat keine Leserechte.

  • Schau dir die JAR-Datei (bzw. ihre Eigenschaften) über den Windows Dateiexplorer an.
  • Probiere es mit Verschieben (in einen anderen Ordner) und/oder Umbenennen der Datei. Der Pfad im Skript müsste dementsprechend natürlich angepasst werden.
java -jar "c:\users\path\to\your\jar\file.jar"

PS.: Batchskripte (.bat) sind für Windows OS, Shellskripte (.sh) sind für Unixsysteme.

PPS.: An deiner Rechtschreibung solltest du dringend arbeiten, denn die ist eklatant schlecht. Bestenfalls, bevor du weiter Programmieren lernst, denn gerade dort werden Tippfehler u.ä. nicht verziehen.

...zur Antwort

Der erste Schritt wäre stets, das Problem zu erfassen, welches folgend gelöst werden soll. Ob es hierbei nun darum geht, ein komplettes Programm zu entwickeln oder nur um die Entwicklung einer einzigen Funktion in einem Programm, ist an der Stelle egal. Beschreibe also zuerst, in Kurzform (Stichpunkte / wenige Sätze), was du überhaupt erreichen möchtest. Dabei kann man zusätzliche Informationen, wie den aktuellen Zustand mit hineinnehmen, wenn man es als hilfreich empfindet.

Solltest du dabei mit dir unbekannten Themen konfrontiert sein, müsstest du dich in diese erst hineinarbeiten. Wolltest du beispielsweise einen Konverter entwickeln, der Dezimalzahlen in eine Form des Binärsystems umwandelt, müsstet du erst wissen, wie diese Zahlensysteme überhaupt funktionieren und wie der mathematische Weg zur Umwandlung aussieht.

Der zweite Schritt wäre eine Ausarbeitung und der Beginn einer Aufteilung. Vor allem wenn es um ein komplexes Problem geht, welches in seiner Rohform noch zu abstrakt ist, als dass man es direkt lösen könnte, muss man schauen, dass man es zergliedern kann. So oft, bis man konkrete, fassbare Teilaufgaben vor sich hat, mit denen zusammengenommen sich das Gesamtziel erreichen lässt.

Ein sehr einfaches, bildhaftes Beispiel dafür wäre die Ausgabe eines beliebig großen Vierecks mit einem beliebigen Zeichen in der Konsole. So ein Viereck besteht aus mehreren Reihen und Spalten. Insofern kann man erst schauen, wie man eine Reihe ausgibt und noch davor, wie man überhaupt eine Spalte zeichnet.

void printColumn(char symbol) {
  System.out.print(symbol);
}

void printRow(char symbol, int width) {
  for (int x = 0; x < width; ++x) {
    printColumn(symbol);
  }

  System.out.println();
}

void printRectangle(char symbol, int width, int height) {
  for (int y = 0; y < height; ++y) {
    printRow(symbol, width);
  }
}

Es setzt in diesem Beispiel natürlich auch etwas voraus, dass zumindest ein paar Implementationen (siehe print, println) aus der Standard-API bereits bekannt sind, damit man nicht wirklich alles versucht, neu zu erfinden. Bei bestimmten Herausforderungen sollte man daher ebenso eine kurze Recherche in Erwägung ziehen, ob es nicht schon fertige Lösungen gibt. Mathematische Funktionen (log, pow, sin, ...) oder String-Operationen (reverse, substring, ...) sind typische Beispiele.

Die Umstellung in ein recht striktweises Denken ist zugegeben nicht immer einfach. Für Programmiereinsteiger ist es vor allem ungewohnt, da der Mensch an sich sprachlich Operationen meist zusammenfasst. Eine Aktion wie laufen ist für uns alle verständlich. Für den Computer ist es eine komplexe Operation, die erst in die einzelnen Muskelbewegungen heruntergebrochen werden müsste.

Ein paar Tipps, die ich bei der Entwicklung von Funktionen/Algorithmen geben könnte, wären diese:

  • Suche in der Beschreibung des Problems nach Verben, die notwendige Operationen (also Funktionen) darstellen könnten.
  • Überlege dir, was der IST-/Anfangs- und der SOLL-/End-Zustand ist.
  • Halte dich möglichst strikt an die Regel, dass jede Funktion nur einem Zweck dient, nicht mehreren.
  • Scheue nicht davor zurück, Hilfsfunktionen zu formulieren, wenn eine Operation leicht beschreibbar, aber für sich gesehen dennoch komplex ausfällt. Ein typisches Beispiel wäre eine mathematische Prüfung, ob sich ein Punkt in einem Rechteck befindet. So etwas lässt sich gut auslagern und später an anderer Stelle wiederverwenden.
  • Lege dir einen Programmablaufplan an (alternativ ein Struktogramm o.ä. Skizzen - hauptsache es gibt nur einfache Bauteile wie if-else, Deklaration/Definition, Anweisung); Operationen, die noch zu abstrakt/komplex sind, werden in weiteren (eigenen) Diagrammen/Skizzen behandelt.
  • Wenn du die Möglichkeit hast, dir Operationen durch Nachstellung bildlich zu machen, dann nutze das (Beispiel: Arrayoperationen wie Tauschen, Sortieren kann man sich mit Karten nachlegen).
  • Löse Probleme nie direkt mit Programmcode. Beginne mit einer Übersetzung in Java-Code erst, sobald der Ablauf des Algorithmus bereits (z.B. als Diagramm) feststeht und getestet werden konnte (nimm dir 1-2 konkrete Anwendungsfälle und versuche mit ihnen deinen Plan einmal durchzuspielen, so fallen frühzeitig Logikfehler auf).
  • Stelle (Performance-)optimierungen hintenan.
  • Vergib für alle Elemente (Variablen, Funktionen, etc.) immer eindeutige, aussagekräftige Namen.

Dazu gibt es eine große Bandbreite an möglichen Aufgaben, an denen sich das Vorgehen üben lässt. Zum Beispiel:

  • Berechnung des Produkts zweier Faktoren, ohne den Multiplikationsoperator zu nutzen
  • Konversion von Zahlen in unterschiedliche Zahlensysteme (Dezimal-/Oktal-/Hexadezimal-/Binärsystem)
  • Addition und Subtraktion beliebiger Brüche
  • Berechnung des größten/kleinsten gemeinsamen Teilers zweier Zahlen
  • Berechnung der Quersumme einer dreistelligen Zahl
  • Berechnung und Ausgabe der ersten zehn Ziffern der Fibonacci-Reihenfolge
  • Die Lösung von Problemen gezielt mit Rekursion (Test ob ein Wort einem Palindrom entspricht, Rückwärtsausgabe einer Zeichenfolge, Berechnung der Werte für ein Pascal'sches Dreieck)
  • Viele mathematische Rätsel findest du auf Projekt Euler
  • Zahlen-raten (eine Zahl zwischen 0 und 1000 wird berechnet, in Folge soll versucht werden, mit möglichst wenigen Arbeitsschritten diese Zahl zu erraten)
  • Eigenimplementation von bekannten String-Methoden (z.B. indexOf, replace und replaceAll für einfache Zeichenfolgen, substring)
  • Die Implementation von Sortierverfahren (Bubblesort, Selectionsort, Insertionsort, Quicksort) - schau für die jeweiligen Beschreibungen auf Wikipedia
  • Überlege dir Methoden, wie man in einer Liste beliebiger Zahlen eine bestimmte Zahl suchen könnte
  • Entwicklung eigener Datenstrukturen (ohne dafür die List-Implementationen der Standard-API zu nutzen): Stack (mit peek, pop und push), doppelt verkettete Liste (mit add, insert, remove), eine Queue (mit add, remove), AVL-Baum (mit add, insert, remove), Graph (mit add, insert, remove)
  • Binäre Suche für einen binären Baum
  • Traversionsverfahren für einen binären Baum (pre-order, in-order, post-order)
  • Suche nach dem kürzesten Weg von einem Knoten eines Graph zu einem anderen (die Kanten, die die Knoten verbinden, geben die Entfernung zwischen zwei verbundenen Knoten vor)
  • Minispiele oder Simulationen wie Conway's Game Of Life, Türme von Hanoi oder Snake (für die grafische Darstellung kannst du Processing nutzen)

Bei der Entwicklung von komplexen Programmen kommt es oft vor, dass man keinen allgemeinen Hauptprogrammablauf hat und stattdessen ein Bündel verschiedener Anwendungsfälle/Funktionen (vgl. mit MSPaint: Der Nutzer kann das Programm öffnen und verschiedene Aktionen in beliebiger Reihenfolge starten). Zudem ist man meist damit konfrontiert, neben der eigentlichen Anwendungslogik noch eine grafische Oberfläche zu haben, die interaktiv sein muss.

Es ist bei so einem Projekt sinnvoll, in der Analysephase das Programm als eigenständiges System auszuarbeiten, welches sich an objektorientierte Konzepte orientiert.

  • Man muss die Anwendungsfälle finden, die in dem System auftreten können (ein use-case-diagram kann hierbei helfen: Erst schaut man, wer das Programm nutzen soll und dann, welche Interessen diese Personengruppe hat bzw. was für Aktionen sie nutzen wird)
  • Anhand einer textuellen Beschreibung des Systems (Was tut es? Wer agiert damit?) kann man einmal wieder herausfinden, welcher Objekte es braucht und wie sie miteinander agieren. Ich habe das in diesem Beitrag einmal an dem Spiel Pac-Man ansatzweise gezeigt. Letztendlich lässt sich damit ein Objektdiagramm und anschließend ein Klassendiagramm kreieren (Stichwort: UML)

In der Projektstrukturierung wiederum sollte es klare Aufteilungen geben. Funktionsbündel kann man als eigene Module definieren (Beispiel MSPaint: Es gibt ein Modul zur Speicherung von Bildformaten, ein Modul für Zeichenoperationen, usw.). Die Anwendungslogik sollte generell von der Formulierung der grafischen Oberfläche getrennt sein. Architekturmuster wie MVC, MVP oder MVVM sind dabei ziemlich hilfreich. Generell macht es Sinn, sich zu diesem Thema (Architektur- und Entwurfsmuster) genauer zu belesen.

Hilfreich könnte zudem eine testgesteuerte Entwicklung (test-driven-development/TDD) sein, da sie dich unter anderem stärker dazu drängt, modular zu denken. Recherchiere zu dem Thema einfach einmal.

...zur Antwort

Deiner Beschreibung zufolge ist das Weiterkommen nichts, was über den Feldzustand ermittelt wird. Stattdessen wird bei jedem Feld neu ausgewürfelt.

Das heißt, du brauchst an sich nur eine Zufallszahl zwischen 0 (inklusiv) und 2 (exklusiv) ermitteln. Ob man nun weiterkommt, bemisst sich daran, ob die ausgewürfelte Zahl größer als 0 ist oder nicht.

Statt eines mathematischen Vergleichs könnte man ebenso die nextBoolean-Methode des Random-Objekts nutzen.

...zur Antwort

Du kannst in der Konfiguration des Webservers bestimmen, welche Ciphersuites für die TLS-Verbindung erlaubt werden sollen. Beachte dabei, dass die Auswahl an verfügbaren Suites von der installierten OpenSSL-Version auf dem OS abhängt.

  • Eine Übersicht zu den als derzeit sicher eingestuften Suites findest du auf ciphersuite.info.
  • Als Hilfsmittel für die Konfiguration kannst du den SSL Configuration Generator von Mozilla nutzen. Schau andernfalls (oder nichtsdestotrotz) auch in die jeweilige Dokumentation des von dir genutzten Webservers (Beispiel Apache).
...zur Antwort

Trimming ist bei Anwendungen, die mit Reflection oder COM-Marshalling arbeiten, problematisch, denn während des Analyseprozesses kann nur schwer beurteilt werden, was denn raus darf oder nicht. Windows Forms ist an der Stelle besonders betroffen, denn es baut unter Haube wesentlich auf COM-Marshalling. Eine mögliche Lösung an der Stelle ist die Nutzung von COM-Wrappern (siehe z.B. WinFormsComInterop).

Zusätzlich solltest du den Microsoft-Artikel Prepare libraries for trimming durcharbeiten.

Eine Garantie dafür, dass du es schaffst, gibt es aber nicht. Seitens des .NET-Teams (lies hier) gibt es jedenfalls noch keinen offiziellen Support. Einen Überblick über den aktuellen Entwicklungsstatus liefert dieses Epic: #4649 Make WinForms trim compatible.

Noch ein paar andere Optionen, die du ausprobieren/angehen könntest:

  • Deploye die App im Release-Modus.
  • Gehe diese Liste an Features durch. Sicherlich kannst du einige von ihnen ausschließen.
  • Schau, ob es im Projekt Dateien gibt, die explizit exkludiert werden können und markiere sie entsprechend.
  • Komprimiere Mediendateien (u.ä. externe Ressourcen), die du möglicherweise nutzt.
  • Mit einem Packer/Kompressor kannst du deine Executable nochmals komprimieren (siehe bspw. NeoLite oder UPX).
  • Etwas, was man fallbedingt einfach einmal testen müsste: Eine Aufteilung in Assemblies und dazu ein partielles Trimming.
...zur Antwort

Die input-Funktion ist ausschließlich für die Texteingabe (und z.T. -ausgabe) in der Konsole gedacht. Wenn du mit einer grafischen Oberfläche (mit Buttons, etc.) arbeiten möchtest, solltest du auch an der Stelle mit entsprechenden Komponenten arbeiten.

Seitens tkinter gibt es für Nutzereingaben das Entry-Widget.

Beispiel:

import tkinter as tk

def show_input():
  output_field.configure(text = input_field.get())

root = tk.Tk()
input_field = tk.Entry(root)
input_field.pack()
output_field = tk.Label(root, text="")
output_field.pack()

tk.Button(root, text="Show text", command=show_input).pack()
root.mainloop()

In diesem Beispiel wird bei Buttonklick das Eingabefeld ausgelesen und dessen Text in einem Label ausgegeben.

Alternativ kann man das Label auch an eine StringVar binden:

text = tk.StringVar()
output_field = tk.Label(root, textvariable=text)

// change:
text.set(input_field.get())

Bei Änderung dessen Wertes wird aktualisiert sich das Label automatisch.

Auch andere GUI-Toolkits (kivy, PyQt, u.ä.) verfügen über eigene Komponenten für Ein- und Ausgabe.

...zur Antwort
(...) Ich habe als letztes Projekt (...) mit QTpy erstellt (...)

Du meinst sicherlich QtPy. Qt ist kein Akronym. 😉

Kennt jemand gute Möglichkeiten / Websites, mit denen ich weiter Üben könnte?

Für kleine Aufgaben / Herausforderungen kannst du auf Edabit, EntwicklerHeld, Excercism oder Projekt Euler schauen. Es gibt dort einen Mix aus Übungen für Anfänger und Intermediate-Level. Als Inspirationsquelle für eigene kleine Projekte kann man die Seiten ebenso nutzen.

Sofern du dich schon mit OOP beschäftigt hast, wäre es gut, sich dahingehend zu vertiefen. Spiele (z.B. Klassiker wie Pac-Man, Schiffe versenken, Snake, Tetris; Text-Adventures, Kartenspiele wie Uno oder Brettspiele wie Go, Pachisi, Schach) stellen dafür angemessene Herausforderungen dar und lassen sich leicht mit weiteren Features erweitern (bspw. einer Zughistorie, einem Multiplayermodus via Netzwerk, neuen Spielmodi, einem Chat zur Kommunikation unter Spielern, einer Gegner-KI, ...). Du kannst hierfür sowohl auf Bibliotheken wie Processing.py oder PyGame, als auch erneut QtPy zurückgreifen.

Schau dir in dem Zusammenhang Datenstrukturen (Bäume, Queues, Stacks), verschiedene Sortier- und Suchalgorithmen (z.B. Alpha-Beta-Pruning, Traversion) und Design Patterns (sowie MVC, MVVM) an. Löse dich allerdings von Schritt-für-Schritt-Tutorials (sofern du solche bisher genutzt haben solltest) und versuche eigene Lösungsansätze (natürlich unter Anwendung der OOP) zu finden.

Andernfalls lohnt sich eine Fokussierung auf ein bestimmtes (Python-spezifisches) Thema, wobei natürlich die Frage im Raum steht, was du mit Python denn nun machen möchtest. Optionen gibt es ja genug:

  • AI/ML (s. Keras)
  • Datentracking und -analyse (s. Anaconda, Pandas, SciPy)
  • IoT / Entwicklung von Software für Mikrocontroller (z.B. für Raspberry Pi OS)
  • Entwicklung von Webanwendungen (mit Django/Flask/Pyramid/o.ä.)
  • Spieleentwicklung (mit Panda3D/PyGame/Ursina/Wasabi2D/o.ä.)

Eine Anlaufstelle für verschiedene Lerntracks und Einstiegstutorials (für diverse Themen aus den oben gelisteten Themenfeldern) bietet RealPython. Ansonsten solltest du spezifisch recherchieren: Es gibt zahlreiche Bücher, Online-Dokumentationen zu den jeweiligen Tools und Webartikel (s. bspw. PlanetPython, PyBites, PythonCentral), in denen neue Features, u.ä. vorgestellt werden.

...zur Antwort

Überlege dir zuerst, welche tatsächlichen Vorteile für dich entstehen bzw. welche Features denn nun fehlen würden, die bestehende Ticketsysteme nicht bieten. Schau dabei auch, ob deine Anforderungen nicht via Nachkonfiguration oder mittels Erweiterungen eines existierenden Systems erfüllbar sind. In der Regel sind solche Anwendungen ziemlich anpassbar und verfügen über eine API zur Automatisierung.

Für das Anlegen von Tickets aus der App heraus, kannst du dir beispielsweise auch ein einfaches Formular anlegen, welches notwendige Daten (Titel, Beschreibung, ...) an ein bestehendes System schickt.

Meines Erachtens dürfte es kaum Gründe geben, das Rad an der Stelle neu erfinden zu müssen. Zumal du an der Stelle ein zweites Softwareprojekt starten würdest und den Fokus vom wesentlichen Projekt nimmst. Das wird dich definitiv hemmen, egal ob du das Projekt nun als einfach oder schwer einschätzt.

Ein zusätzlicher Vorteil, den dir Plattformen wie Atlassian, DevOps oder GitHub bieten können, ist ein komplettes Board rund um deine Software drumherum, welches neben dem Ticketsystem noch weitere Aspekte (Repository, Wiki, Release-Pipelines) verknüpfen kann.

...zur Antwort

Der Umbruch auf eine neue Zeile entspricht bereits dem Standardverhalten von Tabellen.

<table><!-- table 1 --></table>
<table><!-- table 2 --></table>

Wenn das nicht klappt, wurde dieses Verhalten von dir wohl überschrieben. Schau in dem Fall also, welche Styles auf die Tabellen und den Containern wirken.

...zur Antwort

Syntaxfehler gibt es keine. Ob die Dateistruktur des Projekts sowie die Programmlogik stimmt, kannst du innerhalb von Eclipse prüfen. Bei Konfigurationsproblemen (bzgl. Ausführung des Programms) schau in die Eclipse-Dokumentation (Launching a Java program).

Bezüglich der Form wäre es besser, sich an den üblichen Java-Konventionen auszurichten:

  • Bezeichner für Packages, Variablen (das inkludiert auch Parameter) und Methoden beginnen mit einem Kleinbuchstaben
  • Bezeichner für Klassen beginnen mit einem Großbuchstaben
  • Da Methoden etwas tun, wäre es besser, sie mit einem Verb oder einer Imperativform (z.B. baueTreppe) zu bezeichnen
...zur Antwort

1) Du änderst in deinem Code die StarterGui, statt der PlayerGui. Ersteres ist ein Replikat von Letzterem, wird aber erst sichtbar, wenn der Spieler zurückgesetzt wird. Ändere also stattdessen den Knoten in der PlayerGui.

2) Da du eine Sekunde je Intervall warten möchtest, wäre es besser, task.wait zu nutzen. Die von dir genutzte wait-Funktion gilt als veraltet und agiert ungenauer.

3) Noch ein wichtiger Rat: Vergib immer eindeutige und aussagekräftige Namen für deine Variablen, Funktionen, etc.. Mit c, q, u.ä. kann niemand etwas anfangen. Du machst es dir ebenso nur schwer, da du dich doch ebenso stets einlesen musst - wofür stand nun gerade d, für was gerade o? Verwechslungen führen schnell zu Fehlern und nach Pausenzeiten ist es aufwendiger, sich wieder einzulesen.

...zur Antwort

Die Meldung weist auf einen Syntaxfehler hin. Der könnte beispielsweise durch eine falsche Klammersetzung oder eine falsche Parameterübergabe verursacht werden.

Reduziere deine Formel auf eine funktionierende Minimalform und nimm dann schrittweise die entfernten Terme wieder hinzu. So dürfte es einfacher fallen, die Fehlerstelle zu finden.

...zur Antwort

Auf NPM kannst du Packages wie mysql2 finden, mit denen du (in diesem Fall) mit einer MySQL-Datenbank kommunizieren kannst. Für deine Datenbank brauchst du lediglich die Verbindungsdaten (Host, Datenbankname, Nutzername, Passwort).

...zur Antwort

Die Codes sind nicht identisch.

1) Der Starttag des urlset-Elements ist unvollständig. Es fehlt die schließende Klammer (>).

2) Es gibt mehrere ungeschlossene br-Elemente, bei denen eh hinterfragt werden müsste, was die in dem XML-Konstrukt bewirken sollen.

Berücksichtige, dass XML nicht gleich HTML ist. In HTML gibt es einen vordefinierten Satz bekannter Elemente, mit denen die Struktur einer Webseite beschrieben werden soll. Dort ist br bekannt. In XML ist es das nicht.

Für den Aufbau deiner Sitemap-XML solltest du dich an dem üblichen Schema orientieren. Es wird auf https://www.sitemaps.org/protocol.html beschrieben.

3) Es gibt mehrere öffnende url-Tags, die keinen schließenden Partner haben.

...zur Antwort

Für die Speicherung von Nutzereinstellungen kannst du PlayerPrefs nutzen.

Beispiel:

PlayerPrefs.SetInt("Some setting", 123);
PlayerPrefs.Save();

// somewhere else:
int defaultValue = 0;
int someSetting = PlayerPrefs.GetInt("Some setting", defaultValue);

Bezüglich der Kommunikation zwischen zwei Skripts ist die Zuweisung einer Referenz über den Inspektor eine einfache Methode.

Angenommen, du hast ein Skript A und ein Skript B. Skript A soll auf Skript B zugreifen. Dafür legst du in Skript A ein Feld mit dem Typ von Skript B an.

public ScriptB scriptB;

Im Editor wird daraufhin auf der Skriptkomponente ein Feld erscheinen, dem du via Drag & Drop das Skript / das GameObject mit dem Skript zuweisen kannst.

...zur Antwort
Sind diese PHP Methoden nützlich?

Hallo smarte Leute!

Bin PHP Neuling und habe mir dazu die ein oder andere hilfreiche Methode zusammengestellt und eine Standard DB Verbindung für eine MySQL Datenbank erstellt um diese möglicherweise auch für andere Projekte zu nutzen.

Sind diese Methoden hilfreich bzw. kann man diese verbessern?

Mfg, CodeMaster

Standartmethoden:

<?php
  
  function getContentSite($defaultSite) {


    if(isset($_GET['site']))
    {
      include_once($_GET['site'] . ".php");
    }
    else
    {
      include_once($defaultSite . ".php");
    }
  }


  function getFormAction()
  {
    if(isset($_GET["site"]))
    {
      return htmlspecialchars($_SERVER["PHP_SELF"]) . "?site=" . $_GET["site"];
    }


    return htmlspecialchars($_SERVER["PHP_SELF"]);
  }


  function getFormParam($name, $defaultVal = "") 
  {
    if(isset($_POST[$name]))
    {
      return $_POST[$name];
    }


    return $defaultVal;
  }


  function isFormValueChecked($key, $val)
  {
    return ($key == $val ? "checked"  : "");
  }


  function isFormValueSelected($key, $val)
  {
    return ($key == $val ? "selected"  : "");
  }


 ?>

Datenbankverbindung:

<?php


include_once("dbHelpers.inc.php");


$server = '';
$schema = '';
$user = '';
$password = '';


try{
    $con = new PDO('mysql:host='.$server.';dbname='.$schema.';charset=utf8',$user,$password);
    $con->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
} catch(Exception $e){
    printException($e);
}

Datenbankabfragen:

<?php


function makeStatement($query, $array = null){
    try{
        global $con;
        $stmt = $con->prepare($query);
        $stmt->execute($array);
        return $stmt;
    } catch(Exception $e) {
        printException($e);
    }
}
function printException($e)  {
    echo 'Error '.$e->getCode().$e->getMessage();
}


function makeTable($query, $arrV = null)
{
    try{
        $stmt = makeStatement($query, $arrV);
        echo '<table class="table">';
        $meta = array();
        echo '<tr>';
        for($i = 0; $i < $stmt -> columnCount(); $i++)
        {
            $meta[] = $stmt->getColumnMeta($i);
            echo '<th>'.$meta[$i]['name'].'</th>';
        }
        echo '</tr>';
 
        while($row = $stmt->fetch(PDO::FETCH_NUM)){
            echo '<tr>';
            foreach($row as $r){
                echo '<td>'.$r.'</td>';
            }
            echo '</tr>';
        }
        echo '</table>';
    }
    catch(Exception $e){
        printException($e);
    }
}

...zur Frage

Bei den Funktionen, die direkt Werte verarbeiten, die von außen kommen, wäre ich restriktiver. Für getContentSite sollte z.B. sichergestellt sein, dass wirklich nur die beabsichtigten PHP-Seiten aufgerufen werden können. Sammel die am besten in einem speziellen Ordner, in dem niemals andere PHP-Dateien abgelegt werden.

Da die Funktion versucht, die Datei direkt einzubinden, würde ich sie etwas anders benennen.

function includeContentSite($defaultSite) {
  if (!isset($_GET['site'])) {
    require_once($defaultSite . ".php");
    return;
  }

  $site = basename($_GET['site']);
  include_once('path/to/content/sites/folder' . $site . '.php');
}

Noch viel besser wäre allerdings ein Routingsystem, welches den Seitenname nicht an eine Datei, sondern eine Funktion knüpft. Zunächst werden alle Anfragen auf einen Dispatcher (index.php o.ä.) umgeleitet. Dort werden alle erwarteten URLs mit ihren zugehörigen Handlern verknüpft und gespeichert. Wenn die Request-URL auf einen bestimmten registrierten Eintrag passt, wird der dazugehörige Handler ausgeführt. Eine einfache Umsetzung wird in diesem Artikel gezeigt, andernfalls gibt es fertige (und ausgereiftere) Implementationen in diversen PHP-Frameworks (Laravel, Symfony, Yii, etc.).

Genauso solltest du restriktiver in getFormAction handeln. Schau erst, ob site einen validen, beabsichtigten Wert beinhaltet, bevor du ihn an eine Adresse hängst. Insofern könnte man sich da auch gleich eine Hilfsfunktion schreiben:

function getContentSiteName($defaultSite) {
  if (!isset($_GET['site'])) {
    return $defaultSite;
  }

  $site = basename($_GET['site']);
  $sitePath = 'path/to/content/sites/folder' . $site . '.php';

  if (file_exists($sitePath)) {
    return $site;
  }

  return $defaultSite;
}

function getFormAction() {
  $siteName = getContentSiteName('');

  if (!$siteName) {
    return $_SERVER['PHP_SELF'];
  }

  return '?site=' . $siteName;
}

Wenn es einen Querystring gibt, genügt diese relative Adresse. Andernfalls wird der aktuelle Dateiname ausgegeben, damit das action-Attribut, in welches der Wert später hineingeschrieben wird, nicht leer ist.

Hinsichtlich der Funktionen isFormValueChecked und isFormValueSelected kann ich nicht so viel sagen, da sich mir der Kontext nicht erschließt, in dem sie später eingesetzt werden.

Bei der Angabe des Connectionstrings würde sich, aufgrund der vielen Stringkonkatenationen eine Interpolation mal mehr lohnen:

$con = new PDO("mysql:host={$server};dbname={$schema};charset=utf8", $user, $password);

Und insgesamt könnte man alle Datenbankoperationen gut in einer Klasse kapseln:

class DatabaseHandler {
  public function __construct() {
    /* create PDO connection here ... */
    $this->connection = $connection;
  }

  public function makeStatement($query, $params = null) {
    try {
      $stmt = $this->connection->prepare($query);
      $stmt->execute($params);
      return $stmt;
    }
    catch(Exception $ex) {
      $this->printException($ex);
      return null;
    }
  }

  /* etc. */
}

// usage example:
$dbHandler = new DatabaseHandler();
$result = $dbHandler->makeStatement('select something from somewhere');
$otherResult = $dbHandler->makeStatement('select somethingElse from somewhereElse');

Auf eine globale Variable $con kann man somit verzichten. Die Rolle übernimmt das connection-Feld, welches nur in dem Kontext bekannt ist, in welchem es auch benötigt wird. Wenn du eine der Funktionen aufrufen möchtest, legst du dir eine Instanz der Klasse an und rufst über diese die jeweilige Funktion auf.

Achte im Übrigen darauf, konsistent bei der Werterückgabe zu sein. Wenn eine Funktion in einem ihrer Programmzweige einen Wert zurückgibt, dann sollte sie das letztendlich auch in allen anderen möglichen Programmzweigen tun.

Im obigen Fall (makeStatement) gibt es dahingehend zwei Möglichkeiten. Entweder du gibst bei Misserfolg null (oder zumindest einen anderen falsy Wert) zurück oder du verzichtest auf das try-catch und lässt eine Exception stattdessen nach oben eskalieren, um sie dann dort entsprechend zu behandeln.

Wenn du die erste Option wählst, könnte ein Aufrufer wie makeTable demzufolge so vorgehen:

public function makeTable($query, $arrV = null) {
  $stmt = $this->makeStatement($query, $arrV);

  if ($stmt) {
    /* print table ... */
  }
  else {
    /* fallback? */
}

Andernfalls bleibt es bei einem try-catch-Konstrukt.

Zu guter Letzt wäre es noch gut, die Namen einiger Bezeichner nochmals zu überdenken. Beispielsweise sollte $r doch eine Spalte repräsentieren und daher besser $column heißen. Bei $arrV oder $array wiederum ist von außen unklar, wozu sie dienen sollen. Ihr Zweck wird erst ersichtlich, wenn man sich den konkreten Code der jeweiligen Funktionen anschaut.

...zur Antwort

Das gesamte Konzept hinter Klassen/Objekte dient dazu, Probleme (bzw. Systeme) aus der tatsächlichen Welt besser/einfacher abbilden zu können. Es hilft dir zudem, dein Programm logisch zu strukturieren.

Ein gutes Beispiel wäre die Programmierung von Pac-Man. Es gibt ein Spielfeld, es gibt die Spielfigur, es gibt sammelbare Punkte und die Geister. Das sind alles Objekte in einem System, die (miteinander) agieren. Für jeden Objekttyp (Spielfigur, Geist, Punkt, ...) kann eine Klasse definiert werden, die die Eigenschaften (Felder) und Verhaltensweisen (Methoden) eines solchen Objekts beschreibt.

Z.b kann man Variablen auch mit einem Klassennamen deklarieren, statt mit einem einfachen Datentypen wie int oder String.

Java unterscheidet zwischen primitiven und komplexen Datentypen.

Primitive Datentypen verweisen auf einen einfachen, konstanten Wert. Zum Beispiel eine Zahl (s. int, float, double, ...).

Komplexe Datentypen hingegen können sich mehrere Eigenschaften merken und Methoden besitzen. Das heißt, sie benötigen mehr Speicherplatz und es wird eine Klasse benötigt, die ihren Aufbau beschreibt. Variablen komplexen Datentyps (z.B. String, Scanner, ...) verweisen somit auch immer auf ein Objekt.

Auch die Erzeugung eines neuen Objekts mit new bereitet mir Schwierigkeiten.

Du musst an sich nur wissen, welche Informationen ein Objekt braucht, um erstellt zu werden. Das lässt sich anhand des Konstruktors ablesen, der von der zugehörigen Klasse definiert wird. Bei Klassen aus der Standardbibliothek oder Klassen aus externen Bibliotheken u.ä. kannst du in der Regel in der jeweiligen Dokumentation nachschlagen, welche Konstruktoren eine bestimmte Klasse bietet.

Beim Erstellen des Objekts schreibst du nach dem new-Operator den Konstruktoraufruf. Der Konstruktor hat stets den selben Namen wie die Klasse.

Beispiel 1:

class Car {}

// main:
Car car = new Car();

Da in der Klasse kein expliziter Konstruktor definiert wird, wird der Standardkonstruktor verwendet, der parameterlos ist.

Beispiel 2:

class Car {
  public Car() {
  }
}

// main:
Car car = new Car();

Im Gegensatz zu Beispiel 1 wird explizit ein Konstruktor definiert (d.h. der Standardkonstruktor wird somit auch überschrieben). Der ist aber ebenfalls parameterlos, daher unterscheidet sich sein Aufruf nicht zu dem von oben.

Beispiel 3:

class Car {
  public Car(String color) {
  }
}

// main:
Car car = new Car("red");

Diesmal fordert der explizit definierte Konstruktor einen Parameter vom Typ String. Ohne diese Angabe kann kein Car-Objekt angelegt werden.

Beispiel 4:

class Car {
  public Car() {
  }

  public Car(String color) {
  }

  public Car(int maxVelocity) {
  }
}

// main:
Car car1 = new Car();
Car car2 = new Car("red");
Car car3 = new Car(250);

Die Klasse besitzt mehrere Konstruktoren. Somit kann man auch mit unterschiedlichen Daten Objekte der Klasse erzeugen.

...zur Antwort
Fehler bei password verify php?

Ich habe ein Testprogramm geschrieben, in dem man ein Passwort eingibt, dass dann gehasht in einer Datenbank gespeichert wird. Wenn ich mit dem Passwort vergleiche kommt aber nicht true sondern false raus. Das ganze habe ich in WebFTP gemacht.

Als Ausgabe bekomme ich:

123456789 $2y$10$4TMgUO3xGJMCy5iZnd6Be.TBRkIO2Z55GGwgQ5oeToD.ryJZAvvte Richtig In Datenbank übertragen $2y$10$4TMgUO3xGJMCy5iZnd6Be.TBRkIO2Z55GGwgQ5oeToD.ryJZAvvte Falsch Richtig übertragen

Bedeutet das gehashte Passwort wurde richtig gespeichert, aber passwort verify hat beim zweiten mal false zurück gegeben.

Hier ist der php Teil dazu:

<?php
if (isset($_POST["start"])) {
    $password = $_POST["password"];
    $email = $_POST["email"];
    echo $password . " ";
    $passwordHash = password_hash($password, PASSWORD_DEFAULT);
    echo $passwordHash . " ";
    if (password_verify($password, $passwordHash)){
        echo "Richtig ";
    }else{
        echo "Falsch ";
    }
    require_once "data.php"; //Hier wird die Datenbankverbindung gespeichert
    $statement = $pdo->prepare("INSERT INTO tab (email, password) VALUES (?, ?)");
    $statement->execute(array($email, $passwordHash));
    if ($statement){
        echo "In Datenbank übertragen ";
        $sql = "SELECT * FROM tab WHERE email='$email'";
        $user = $pdo->query($sql)->fetch();
        $passwordTest = $user["password"];
        echo $passwordTest . " ";
        if (password_verify($password, $passwordTest)){
            echo "Richtig ";
        }else{
            echo "Falsch ";
            if ($passwordHash == $passwordTest){
                echo "Richtig übertragen ";
            }else{
                echo "Falsch übertragen ";
            }
        }
        die();
    }else{
        die("Es ist etwas schief gelaufen");
    }
}
?>
...zur Frage

Vorweg: Ich kann dein Problem nicht reproduzieren.

Ein häufiger Grund, wenn ein Vergleich mittels password_verify fehlschlägt, liegt allerdings in intern unterschiedlich genutzten Zeichenkodierungen. Stelle daher sicher, dass du für die Datenkommunikation überall eine einheitliche Kodierung verwendest.

1) Gib dem Browser in dem HTML-Dokument, welches das Formular beinhaltet, eine Zeichenkodierung vor:

<meta charset="utf-8">

2) Deine Datenbank/-tabelle sollte die Daten in utf8mb4-Kodierung (= UTF-8) speichern.

3) Gib in deinem Connectionstring eine eindeutige Kodierung vor:

$connectionString = 'mysql:host=...;dbname=...;port=...;charset=utf8mb4';
...zur Antwort