Der ultimative Leitfaden für generische Pionia-Dienste.

王林
Freigeben: 2024-07-16 20:46:49
Original
552 Leute haben es durchsucht

The Ultimate Guide to Pionia Generic Services.

Das Pionia-Framework ist ein PHP-Rest-Framework, das die Art und Weise verändert, wie wir früher Rest-Plattformen entwickelt haben. Im Gegensatz zu allen bestehenden Frameworks verleiht es dem gesamten Prozess ein völlig neues Aussehen, wodurch die Entwicklung von APIs viel einfacher und weniger langweilig wird. Dies liegt daran, dass es nach einem anderen und eher „neuen“ Muster namens Mondlicht läuft.

Mondlicht ist per se keine neue Architektur/ein neues Muster, die meisten Institutionen/Unternehmen/Entwickler haben es verwendet, aber nur unbenannt. Aber heute reden wir nicht über Mondlicht, Sie können in meinem anderen Artikel hier darüber lesen und sogar Ihre Kommentare hinterlassen.

Um ein neues Pionia-Projekt zu booten, müssen Sie den folgenden Befehl ausführen, vorausgesetzt, Sie haben Composer bereits eingerichtet.

Lass uns eine todo_app erstellen.

composer create-project pionia/pionia-app todo_app
Nach dem Login kopieren

Sie können dasselbe Projekt auch mit dem pionia-Befehl wie unten ausführen:

php pionia serve
Nach dem Login kopieren

Um Ihre Protokolle in Echtzeit zu verfolgen, öffnen Sie ein zweites Terminal und führen Sie den folgenden Befehl aus:

tail -f server.log
Nach dem Login kopieren

Hintergrundinformationen zu Dienstleistungen.

Dienste im Pionia-Framework sind das Herzstück, wahrscheinlich der einzige Teil, den Sie die meiste Zeit mit der Entwicklung Ihrer APIs verbringen werden. Alle normalen Dienste in Pionia erweitern den PioniaRequestBaseRestService. Ein normaler Gottesdienst in Pionia könnte so aussehen.

namespace application\services;


use Exception;
use Pionia\Request\BaseRestService;
use Pionia\Response\BaseResponse;
use Porm\Porm;

class UserService extends BaseRestService
{
    /**
     * @throws Exception
     */
    protected function login(array $data): BaseResponse
    {
        // password and username are required, without them we won't proceed even
        $this->requires(["username", "password"]);

        $username = $data["username"];
        $password = password_hash($data['password'], PASSWORD_DEFAULT);

        $user = Porm::from('user')->get(['username' => $username, 'password' => $password]);
        //You can do more here, maybe generate a JWT token or add more checks
        // for example if the user is an active or not
        if ($user) {
            return BaseResponse::JsonResponse(0, "Login successful", $user);
        }
        throw new Exception("User with the given username and password not found");
    }

}
Nach dem Login kopieren

Nachdem Sie Ihren Dienst erstellt haben, müssen Sie ihn bei dem Switch registrieren, der ihn von nun an verwalten soll. Wenn Sie die Schalter in Pionia nicht kennen, können Sie sie hier in den Dokumenten nachlesen. Gehen Sie also zu unserem Switch-Ordner, wahrscheinlich in der MainAppSwitch.php, falls Sie noch keinen anderen erstellt haben, und registrieren Sie den oben genannten Dienst wie unten in der Methode „registerServices“

     /**
     * Register your services here.
     *
     * @return array
     */
    public function registerServices(): array
    {
        return [
            'user' => new UserService(),
            'todo' => new TodoService()
        ];
    }
Nach dem Login kopieren

Auf diese Weise wird Ihr Dienst von nun an automatisch vom Kernel erkannt. In typischen Einstellungen hätten Sie einen Router und einen Controller hinzugefügt, um diesen Dienst zuzuordnen, aber Pionia geht die Sache anders an. Denken Sie daran, dass Sie denselben Dienst in mehreren Switches registrieren können. Auf diese Weise erreichen wir das Konzept der API-Versionierung, da jeder Wechsel von seinem API-Endpunkt gehandhabt wird. Standardmäßig kann auf MainAppSwitch unter /api/v1/ zugegriffen werden.

In Ihren Anfragen können Sie auf diesen Service hinweisen, indem Sie Folgendes senden.

// POST http://localhost:8000/api/v1/
{
    "SERVICE": "user",
    "ACTION": "login",
    "username": "pionia",
    "password": "pionia1234"
}
Nach dem Login kopieren

Wie Sie bemerken, ist ACTION der Name der Aktion/Methode, die wir in unserem SERVICE/Service/Klasse erstellt haben und die wir bei der Registrierung auf den Namen Benutzer getauft haben.

So funktionieren normale Dienste in Pionia.

Unten finden Sie einen kompletten Service, der CRUD in Piona durchführt. Es basiert auf der folgenden einfachen Tabelle namens todos in einer MySQL-Datenbank namens todo_db.

create table todo_db.todos
(
    id          int auto_increment primary key,
    title       varchar(200)                        not null,
    description text                                null,
    created_at  timestamp default CURRENT_TIMESTAMP null
) engine = InnoDB;
Nach dem Login kopieren
use Exception;
use Pionia\Request\BaseRestService;
use Pionia\Request\PaginationCore;
use Pionia\Response\BaseResponse;
use Porm\exceptions\BaseDatabaseException;
use Porm\Porm;

class TodoService extends BaseRestService
{
    /**
     * Returns all todos
     * @throws Exception
     */
    public function list(): BaseResponse
    {
        $result = Porm::table('todos')
            ->using('db')
            ->columns(['id', 'title', 'description', 'created_at'])
            ->all();

        return BaseResponse::JsonResponse(0, null, $result);
    }

    /**
     * Returns a single todo
     * @throws Exception
     */
    public function details(array $data): BaseResponse
    {
        $this->requires(['id']);
        $id = $data['id'];

        $result = Porm::table('todos')
            ->using('db')
            ->columns(['id', 'title', 'description', 'created_at'])
            ->get(['id' => $id]);

        return BaseResponse::JsonResponse(0, null, $result);
    }

    /**
     * Creates a new todo
     * @throws Exception
     */
    public function create(array $data): BaseResponse
    {
        $this->requires(['title', 'description']);
        $title = $data['title'];
        $description = $data['description'];

        $result = Porm::table('todos')
            ->save(['title' => $title, 'description' => $description]);

        return BaseResponse::JsonResponse(0, 'Todo created successfully', $result);
    }

    /**
     * Updates a todo
     * @throws Exception
     */
    public function update(array $data): BaseResponse
    {
        $this->requires(['id']);

        $id = $data['id'];

        $todo = Porm::table('todos')
            ->get($id); // similar to `get(['id' => $id])`

        // if the todo is not found, we throw an exception
        if (!$todo) {
            throw new BaseDatabaseException('Todo not found');
        }

        $description = $data['description'] ?? $todo->description;
        $title = $data['title'] ?? $todo->title;

        // we update in a transaction as below
        $result= null;
        Porm::table('todos')
            ->inTransaction(function () use ($description, $title, $id, &$result) {
                Porm::table('todos')
                    ->update(['description' => $description, 'title' => $title], $id);

                $result = Porm::table('todos')
                    ->get($id);
            });

        return BaseResponse::JsonResponse(0, "Todo $id updated successfully", $result);
    }

    /**
     * Deletes a todo
     * @throws Exception
     */
    public function delete(array $data): BaseResponse
    {
        $this->requires(['id']);
        $id = $data['id'];

        $todo = Porm::table('todos')
            ->get($id);

        if (!$todo) {
            throw new BaseDatabaseException('Todo not found');
        }

        $deleted = false;
        Porm::table('todos')
            ->inTransaction(function () use ($id, &$deleted) {
                Porm::table('todos')
                    ->delete($id);
                $deleted = true;
            });
        if (!$deleted) {
            throw new BaseDatabaseException('Todo not deleted');
        }
        return BaseResponse::JsonResponse(0, "Todo $id deleted successfully");
    }

    /**
     * Returns a random todo object if the size is not defined or 1,
     * else returns an array of random todos
     * @throws Exception
     */
    public function random($data): BaseResponse
    {
        $size = $data['size'] ?? 1;

        $result = Porm::table('todos')
            ->random($size);

        return BaseResponse::JsonResponse(0, null, $result);
    }

    /**
     * Returns a paginated list of todos
     * @throws Exception
     */
    public function paginatedList(array $data): BaseResponse
    {
        $offset = $data['offset'] ?? 0;
        $limit = $data['limit'] ?? 3;

        $paginator = new PaginationCore($data, 'todos', $limit, $offset, 'db');
        $result = $paginator->paginate();

        return BaseResponse::JsonResponse(0, null, $result);
    }
}
Nach dem Login kopieren

Und da unser TodoService bereits registriert ist, ist das alles, was wir tun müssen, keine zusätzlichen Routen, keine Controller hinzuzufügen. Beginnen Sie einfach mit der Ausführung der Aktionen in Ihren Anfragen und Sie sollten einheitliche Antworten auf alle oben genannten Aktionen erhalten.

Obwohl dies nicht viel zu tun ist und das einzige, was in Pionia (Gebäudedienstleistungen) zu tun ist, können alle oben genannten Aktionen in unserem TodoService weggelassen werden und wir erhalten immer noch die gleiche Funktionalität. Hier ist unsere Allgemeine Dienstleistungen kommen ins Spiel!

Todo Service, der generische Weg.

Wenn Ihre Logik nicht aus mehr besteht als Erstellen, Löschen, Paginieren, Auflisten, Aktualisieren, Löschen oder Abrufen, dann sind generische Dienste möglicherweise alles, was Sie brauchen.

Pionia bietet sowohl generische Dienste als auch Mixins zur Nutzung an. Mixins können zusammengestellt werden, um Ihren gesamten neuen generischen Service bereitzustellen.

Zu den bereitgestellten Mixins gehören ListMixin, CreateMixin, DeleteMixin, UpdateMixin, RandomMixin und RetrieveMixin. Unter der Haube kombinieren sogar generische Dienste diese Mixins und erweitern gleichzeitig GenericService.

Zu den bereitgestellten generischen Diensten gehören RetrieveCreateUpdateService, RetrieveListCreateService, RetrieveListCreateUpdateDeleteService, RetrieveListDeleteService, RetrieveListRandomService, RetrieveListUpdateDeleteService, RetrieveListUpdateService und UniversalGenericService.

Wenn die oben genannten Generics die Mixins nicht in der von Ihnen gewünschten Weise kombinieren, können Sie GenericService erweitern und alle Mixins aufrufen, die Sie verwenden möchten, und so Ihren benutzerdefinierten generischen Service erstellen.

Denken Sie daran, dass Sie zur Verwendung von Mixins PioniaGenericsBaseGenericService erweitern müssen, nicht den normalen BaseRestService, den wir zuvor erweitert haben. Denken Sie auch daran, dass Mixins nur PHP-Eigenschaften sind und auch so verwendet werden sollten.

Um unseren TodoService umzugestalten, benötigen wir den zuletzt genannten generischen Dienst, UniversalGenericService, da er alle definierten Mixins verwendet.

Beginnen wir mit der Änderung der Klasse, die wir erweitern. Refaktorieren Sie dies wie folgt

use Pionia\Generics\UniversalGenericService;
// ... rest of the imports

class TodoService extends UniversalGenericService
{
// ... rest of your actions
}
Nach dem Login kopieren

Before we do anything, let's first define the table we want to target in the database. We use the $table property for this. This is a compulsory feature and must be defined for all generic views.

use Pionia\Generics\UniversalGenericService;
// ... rest of the imports

class TodoService extends UniversalGenericService
{
   public string $table = "todo";
// ... rest of your actions
}
Nach dem Login kopieren

Secondly, from our list action, we are defining columns we want to return, however, we are defining all. If you want to return a certain range of columns only, we define the $listColumns(which defaults to all) and pass the columns we want to return. Let's just still pass all though it is the default behavior of the service.

use Pionia\Generics\UniversalGenericService;
// ... rest of the imports

class TodoService extends UniversalGenericService
{
    public string $table = "todo";
    public ?array $listColumns = ['id', 'title', 'description', 'created_at'];

// ... rest of your actions
}
Nach dem Login kopieren

At this point, we can delete the list action from our service. That's complete!

Our second target action is now details. This one can be replaced by defining the $pk_field which defaults to id. Since our primary key field for our todo table is also id, we don't need to define it, we just need to delete it too! Remember, this one also uses the defined $listColumns for columns to return from the DB.
The RetrieveMixin also defines another sister action to this called retrieve, so in your request, you can use ACTION as details or retrieve, the two will perform the same thing.
Since we already have all we need, we can drop the details action too!

Our third action is create. For this, we must define the $createColumns to define those columns we shall be looking for from the request(required) to create a record. Let's add the property now.

use Pionia\Generics\UniversalGenericService;
// ... rest of the imports

class TodoService extends UniversalGenericService
{
    public string $table = "todo";
    public ?array $listColumns = ['id', 'title', 'description', 'created_at'];
    public ?array $createColumns = ['title', 'description'];

// ... rest of your actions
}
Nach dem Login kopieren

After adding, go ahead and delete it too!

Our fourth action is update. For this, we require the $pk_field and can also optionally define the $updateColumns. If undefined, the responsible mixin checks if any of the properties were defined in the request, and will update only those.
Let's add the $updateColumns and give it the only properties we intend to update.

use Pionia\Generics\UniversalGenericService;
// ... rest of the imports

class TodoService extends UniversalGenericService
{
    public string $table = "todo";
    public ?array $listColumns = ['id', 'title', 'description', 'created_at'];
    public ?array $createColumns = ['title', 'description'];
    public ?array $updateColumns = ['title', 'description'];

// ... rest of your actions
}
Nach dem Login kopieren

We can now drop the update action too!

For our fifth action, delete, we only need the $pk_field which is by default id, so we shall be checking if id was passed in the request, and then we delete the associated record. So, just delete it, we already have all we need!

Now to our sixth action, random, this also uses the $listColumns to determine the columns to fetch from the DB per record. We already have out property defined, so, just drop it too!

For our seventh action, paginatedList, we can drop it, and in any request, we target our list action, but we define any of the following pairs of keys in our request.

  1. limit and offset on the request object level.
{
   "SERVICE": "todo",
   "ACTION": "list",
   "limit": 3,
   "offset": 0
}
Nach dem Login kopieren
  1. PAGINATION or pagination object on the request with limit and offset keys.
{
   "SERVICE": "todo",
   "ACTION": "list",
   "PAGINATION": {
      "limit": 3,
      "offset": 0,
   }
}
Nach dem Login kopieren
  1. SEARCH or search object on the request object with limit and offset keys.
{
   "SERVICE": "todo",
   "ACTION": "list",
   "SEARCH": {
      "limit": 3,
      "offset": 0
   }
}
Nach dem Login kopieren

Note: Both the limit and offset keys must be defined for pagination to kick in.

And just like that, our service now has been reduced to the following.

use Pionia\Generics\UniversalGenericService;

class TodoService extends UniversalGenericService
{
    public string $table = "todo";
    public ?array $listColumns = ['id', 'title', 'description', 'created_at'];
    public ?array $createColumns = ['title', 'description'];
    public ?array $updateColumns = ['title', 'description'];
}
Nach dem Login kopieren

Let's do a little more cleanup. As we had mentioned earlier, if we are listing all columns from our table, then we don't need to define the $listColumns property, let's remove that too.

use Pionia\Generics\UniversalGenericService;

class TodoService extends UniversalGenericService
{
    public string $table = "todo";
    public ?array $createColumns = ['title', 'description'];
    public ?array $updateColumns = ['title', 'description'];
}
Nach dem Login kopieren

Also, since our update can also discover the columns to update from the request data, let's remove the $updateColumns too!

And we are left with the following as our new TodoService but still exposing the actions of list(all and paginated), create, update, delete, retrieve or details and random

use Pionia\Generics\UniversalGenericService;

class TodoService extends UniversalGenericService
{
    public string $table = "todo";
    public ?array $createColumns = ['title', 'description'];
}
Nach dem Login kopieren

You can also override how we get a single record and multiple records. You might not need it, but sometimes you may need to add where clauses and other conditions as you see fit. For that, you can read about it in this section in the docs.

Also, you may want to add your other actions in the same generic service, this is fully supported and will work as if you're in normal services, however, make sure none of those actions share the names with the provided mixin actions or otherwise you stand a chance of overriding the provided actions.

This also drives to the last point, what if you intend to override the default action? that's also okay! You can also look into it under this section of the docs.

Welcome to Pionia Framework, where we believe in both developer and program performance, writing precise and maintainable codebase with simplicity both at the front end and the back end!

Let me hear what you say about the Pionia Framework specifically about generic services. Happy coding!

Das obige ist der detaillierte Inhalt vonDer ultimative Leitfaden für generische Pionia-Dienste.. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!