Tutorial: Controller schreiben

Am Ende dieses Artikels erfahren Sie, wie Sie Controller implementieren und verwenden

Das Ergebnis dieses Tutorials auf github finden Sie hier

Dieses Tutorial ist eine natürliche Fortsetzung des Schreibens von Modellen mit Fluent. Sie können entweder zuerst dieses Tutorial aufrufen und später wiederkommen oder ein Rebell sein, es überspringen und weiterlesen

1. Erstellen Sie ein neues Projekt

Wir werden das Ergebnis des oben genannten Tutorials als Vorlage verwenden, um unser neues Projekt zu erstellen:

vapour new projectName --template = vapourberlin / my-first-model --branch = vapour-2

2. Generieren Sie ein Xcode-Projekt

Bevor wir ein Xcode-Projekt generieren, müssten wir den Paketnamen in Package.swift ändern:

PackageDescription importieren
let package = Package (
  Name: "Projektname", // geändert
  Produkte: [
    .library (Name: "App", Ziele: ["App"]),
    .executable (Name: "Run", Ziele: ["Run"])
  ],
  Abhängigkeiten:
    .package (URL: "https://github.com/vapor/vapor.git", .upToNextMajor (von: "2.1.0")),
    .package (URL: "https://github.com/vapor/leaf-provider.git", .upToNextMajor (von: "1.1.0")),
    .package (URL: "https://github.com/vapor/fluent-provider.git", .upToNextMajor (von: "1.3.0"))
  ],
  Ziele: [
    .target (Name: "App", Abhängigkeiten: ["Vapor", "LeafProvider", "FluentProvider"],
      ausschließen: [
        "Config",
        "Öffentlichkeit",
        "Ressourcen",
      ]
    ),
    .target (Name: "Ausführen", Abhängigkeiten: ["App"]),
    .testTarget (Name: "AppTests", Abhängigkeiten: ["App", "Testing"])
  ]
)

Jetzt im Terminal im Stammverzeichnis projectName / execute:

dampf xcode -y

Das Abrufen der Abhängigkeit kann etwas dauern, aber wenn Sie fertig sind, sollten Sie eine Projektstruktur wie die folgende haben:

Projektname/
├── Package.swift
├── Quellen /
│ ├── App /
│ │ ├── Modelle /
│ │ │ │ User.swift
│ │ ├── Routen /
│ │ │ │ Routes.swift
│ │ └── Einrichtung /
│ │ ├── Config + Setup.swift
│ │ │ Droplet + Setup.swift
│ └── Run /
├── Tests /
├── Konfig /
├── Öffentlich /
├── Abhängigkeiten /
└── Produkte /

3. Warum brauchen wir Controller?

Wenn Sie in Routes.swift nachsehen, sollten Sie zwei Funktionen (Routen) sehen, von denen die erste eine Liste von Benutzern zurückgibt und die zweite einen neuen Benutzer erstellt. Stellen Sie sich vor, Sie möchten jetzt die Möglichkeit implementieren, kurze Textausschnitte zu erstellen und diese auch aufzulisten. Sie müssten wahrscheinlich eine ähnliche Route erstellen ("Snippet"), um alle Snippets als Liste abzurufen, und möglicherweise einen Beitrag ("Snippet"), um neue Snippets zu erstellen. Wenn Sie das in Routes.swift tun würden, wäre das in Ordnung, solange Ihr Projekt mit nur 4 - 6 Routen superklein ist. Sobald Ihr Projekt größer wird, wird auch die Routes.swift-Datei größer und Sie verlieren den Überblick. Es ist auch keine gute Praxis, eine Datei für mehrere Aufgaben zu haben . Das Erstellen eines Benutzers ist etwas anderes als das Erstellen eines Snippets.

4. Erstellen Sie Ihren ersten Controller

Wir wollen also alles, was mit dem Benutzer zu tun hat, in einen eigenen Controller integrieren. Ein UserController. Erstellen Sie das folgende Verzeichnis und die folgende Datei:

Projektname/
├── Package.swift
├── Quellen /
│ ├── App /
│ │ ├── Controller / // hinzugefügt
│. │ │ UserController.swift // hinzugefügt
│ │ ├── Modelle /
│ │ │ │ User.swift
│ │ ├── Routen /
│ │ │ │ Routes.swift
│ │ └── Einrichtung /
│ │ ├── Config + Setup.swift
│ │ │ Droplet + Setup.swift
│ └── Run /
├── Tests /
├── Konfig /
├── Öffentlich /
├── Abhängigkeiten /
└── Produkte /
HINWEIS: Ich habe das Terminal verwendet. Führen Sie in projectName / mkdir Sources / App / Controllers / aus und berühren Sie Sources / App / Controllers / UserController.swift

Möglicherweise müssen Sie Ihr Xcode-Projekt mit vapor xcode -y neu generieren, damit Xcode Ihr neues Verzeichnis sieht.

Wir möchten, dass unsere get ("user") -Funktionalität in unserem UserController enthalten ist. Schreiben Sie dazu den folgenden Code:

letzte Klasse UserController {
  
  func list (_ req: Request) wirft -> ResponseRepresentable {
    let list = versuche User.all ()
    return try self.view.make ("userview", ["userlist": list.makeNode (in: nil)])
  }
}

Lassen Sie mich kurz erklären. Wir definieren eine neue Funktion, die sie so aufruft, wie wir wollen. Es ist sinnvoll, sie als Liste aufzurufen, da wir uns in einem Benutzer-Controller befinden und diese Funktion eine Liste von Benutzern zurückgeben soll. Funktionen, die Anfragen bearbeiten sollen, sehen immer so aus:

func myFunc (_ req: Request) wirft -> ResponseRepresentable {
  ...
}

Wie verknüpfen wir nun eine Route wie get ("user") in unserer Routes.swift, die von dieser Funktion verarbeitet werden soll? Es ist so super einfach, in Ihrem Routes.swift machen Sie einfach:

Vapor importieren
Erweiterung Droplet {
  func setupRoutes () wirft {
    let userController = UserController () // hinzugefügt
    get ("user", handler: userController.list) // hinzugefügt
    post ("user") {req in
      ...
    }
  }
}
HINWEIS: Wir haben die frühere Route get ("user") hier gelöscht, da sie nicht mehr benötigt wird

Wir initiieren unseren Benutzercontroller und definieren, dass get ("user") von der Funktionsliste des Benutzercontrollers behandelt wird. Jetzt, wo wir Leaf verwenden, müssen wir noch etwas tun. Bevor wir die Controller-Funktion verwendeten, hatten wir („user“) und riefen self.view.make (…) auf, wobei self auf Droplet verwies. Wenn wir nun in unserer Listenfunktion in unser UserController.swift schauen, rufen wir immer noch self.view.make (…) auf, aber da wir uns in der UserController-Klasse befinden, verweist das self auf die Klasse, die nicht das view.make (…) hat. ) Funktion. Alles, was wir tun müssen, ist, das Droplet beim Initiieren an unsere Klasse zu übergeben, es in einer Variablen zu speichern und view.make (…) aufzurufen. In unserem UserController.swift fügen Sie hinzu:

letzte Klasse UserController {
  Tropfen lassen: Tröpfchen
  init (drop: Droplet) {
    self.drop = drop
  }
  func list (_ req: Request) wirft -> ResponseRepresentable {
    let list = versuche User.all ()
    return try drop.view.make ("userview", ["userlist": list.makeNode (in: nil)])
  }
}

Jetzt passieren wir in unserer Routes.swift das Droplet, wenn wir unseren Controller starten:

Vapor importieren
Erweiterung Droplet {
  func setupRoutes () wirft {
    let userController = UserController (drop: self)
    get ("user", handler: userController.list)
    post ("user") {
      ...
    }
  }
}

Wenn du jetzt cmd + r oder die / user-Route startest und startest, funktioniert es einfach!

Hinweis: Stellen Sie sicher, dass neben Ihrer Schaltfläche die Option Als Schema ausführen ausgewählt ist, bevor Sie die App ausführen

Lassen Sie uns der Vollständigkeit halber auch den Post ("Benutzer") auf unseren Controller verschieben
In unserer Routes.swift:

Vapor importieren
Erweiterung Droplet {
  func setupRoutes () wirft {
    let userController = UserController (drop: self)
    get ("user", handler: userController.list)
    post ("user", Handler: userController.create)
  }
}

Und schließlich in unserem UserController.swift:

letzte Klasse UserController {
  Tropfen lassen: Tröpfchen
  init (drop: Droplet) {
    self.drop = drop
  }
  func list (_ req: Request) wirft -> ResponseRepresentable {
    ...
  }
  func create (_ req: Request) wirft -> ResponseRepresentable {
    Wache let username = req.data ["Benutzername"] ?. string else {
      Antwort zurückgeben (Status: .badRequest)
    }
    let user = User (Benutzername: Benutzername)
    versuche user.save ()
    Antwort zurückgeben (Weiterleitung: "/ user")
  }
}

Und das ist es! Sie haben Ihren ersten Controller erfolgreich implementiert ! Whoop!

Vielen Dank fürs Lesen! Wenn Sie Fragen oder Verbesserungen haben - schreiben Sie einen Kommentar! I würde es lieben von dir zu hören!

Twitter / Github / Instagram