Rumah > Artikel > pembangunan bahagian belakang > Panduan Terbaik untuk Perkhidmatan Generik Pionia.
Rangka kerja Pionia ialah rangka kerja PHP Rest yang mengubah cara kami membangunkan platform Rest. Tidak seperti semua rangka kerja sedia ada, ia memberikan keseluruhan proses rupa baharu, menjadikan pembangunan API lebih mudah dan kurang membosankan. Ini kerana ia berjalan pada corak yang berbeza dan agak 'baru' dipanggil cahaya bulan.
Sebenarnya, cahaya bulan bukanlah seni bina/corak baharu, kebanyakan institusi/syarikat/pemaju telah menggunakannya tetapi tidak dinamakan. Tetapi hari ini, kita tidak bercakap tentang cahaya bulan, anda boleh membaca tentangnya dalam artikel saya yang lain di sini dan juga meninggalkan komen anda.
Untuk bootstrap projek Pionia baharu, anda perlu menjalankan perintah berikut dengan mengandaikan anda sudah menyediakan komposer.
Jom buat apl_todo.
composer create-project pionia/pionia-app todo_app
Anda juga boleh menjalankan projek yang sama menggunakan arahan pionia seperti di bawah:
php pionia serve
Untuk melihat anda log semasa ia berlaku dalam masa nyata, buka terminal kedua dan jalankan arahan berikut:
tail -f server.log
Perkhidmatan dalam rangka kerja Pionia adalah intipati, mungkin satu-satunya bahagian yang anda akan luangkan sebahagian besar masa anda semasa membangunkan API anda. Semua perkhidmatan biasa di Pionia melanjutkan PioniaRequestBaseRestService. Perkhidmatan biasa di Pionia mungkin kelihatan seperti ini.
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"); } }
Selepas membina perkhidmatan anda, anda perlu mendaftarkannya dalam suis yang akan mengendalikannya mulai sekarang. Jika anda tidak mengetahui suis dalam Pionia, anda boleh membaca tentangnya di sini dalam dokumen. Jadi, pergi ke folder suis kami, mungkin dalam MainAppSwitch.php jika anda belum mencipta satu lagi, dan daftarkan perkhidmatan di atas seperti di bawah dalam kaedah registerServices
/** * Register your services here. * * @return array */ public function registerServices(): array { return [ 'user' => new UserService(), 'todo' => new TodoService() ]; }
Ini adalah cara anda mendapatkan perkhidmatan anda untuk ditemui secara automatik oleh kernel mulai sekarang. Dalam tetapan biasa, anda akan menambah penghala dan pengawal untuk memetakan perkhidmatan ini, tetapi Pionia menghampiri perkara secara berbeza. Ingat, anda boleh mendaftarkan perkhidmatan yang sama dalam berbilang suis. Beginilah cara kami mencapai konsep versi API kerana setiap suis dikendalikan oleh titik akhir APInya. Secara lalai, MainAppSwitch boleh diakses pada /api/v1/.
Dalam permintaan anda, anda boleh menunjukkan perkhidmatan ini dengan menghantar yang berikut.
// POST http://localhost:8000/api/v1/ { "SERVICE": "user", "ACTION": "login", "username": "pionia", "password": "pionia1234" }
Jika anda perasan, ACTION ialah nama pada tindakan/kaedah yang kami buat dalam PERKHIDMATAN/perkhidmatan/kelas kami yang mana kami telah membaptiskan pengguna nama itu semasa pendaftaran.
Beginilah cara perkhidmatan biasa berfungsi di Pionia.
Di bawah ialah perkhidmatan lengkap yang melaksanakan CRUD di Piona. Ia berdasarkan jadual ringkas berikut yang dipanggil todos dalam pangkalan data MySQL yang dipanggil 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;
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); } }
Dan memandangkan TodoService kami sudah didaftarkan, itu sahaja yang perlu kami lakukan, tiada menambah laluan tambahan, tiada menambah pengawal, cuma mula menekan tindakan dalam permintaan anda dan anda harus mendapat respons seragam daripada semua tindakan di atas.
Walau bagaimanapun perkara ini tidak banyak dilakukan, dan satu-satunya perkara yang perlu dilakukan dalam Pionia(perkhidmatan bangunan), semua tindakan di atas dalam TodoService kami boleh ditinggalkan dan kami masih mendapat fungsi yang sama, Di sinilah kami Perkhidmatan Generik masuk!
Jika logik anda tidak lebih daripada mencipta, memadam, menamakan muka surat, menyenaraikan, mengemas kini, memadam atau mendapatkan semula maka Perkhidmatan Generik mungkin sahaja yang anda perlukan.
Pionia menyediakan kedua-dua perkhidmatan generik dan campuran untuk digunakan. Mixin boleh disatukan untuk menyediakan keseluruhan Perkhidmatan Generik baharu anda.
Bancuhan yang disediakan termasuk ListMixin, CreateMixin, DeleteMixin, UpdateMixin, RandomMixin dan RetrieveMixin. Di bawah hud, malah perkhidmatan Generik hanya menggabungkan Mixin ini sambil melanjutkan GenericService.
Perkhidmatan Generik yang disediakan termasuk RetrieveCreateUpdateService, RetrieveListCreateService, RetrieveListCreateUpdateDeleteService, RetrieveListDeleteService, RetrieveListRandomService, RetrieveListUpdateDeleteService, RetrieveListCreateDeleteService, RetrieveListServiceDeleteService, RetrieveListDeleteService.
Jika Generik di atas tidak menggabungkan mixin mengikut cara yang anda mahukan, anda boleh melanjutkan GenericService dan memanggil semua mixin yang anda mahu gunakan sekali gus mencipta perkhidmatan generik tersuai anda.
Ingat, untuk menggunakan mixin, anda mesti memanjangkan PioniaGenericsBaseGenericService bukan BaseRestService biasa yang kami lanjutkan sebelum ini. Selain itu, ingat bahawa mixin hanyalah ciri PHP dan harus digunakan dengan cara itu.Untuk memfaktorkan semula TodoService kami, kami memerlukan perkhidmatan generik yang terakhir disebut, UniversalGenericService kerana ia menggunakan semua campuran yang ditetapkan.
Mari kita mulakan dengan menukar kelas yang kita lanjutkan. Faktorkan semula ini seperti di bawah
use Pionia\Generics\UniversalGenericService; // ... rest of the imports class TodoService extends UniversalGenericService { // ... rest of your actions }
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 }
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 }
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 }
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 }
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.
{ "SERVICE": "todo", "ACTION": "list", "limit": 3, "offset": 0 }
{ "SERVICE": "todo", "ACTION": "list", "PAGINATION": { "limit": 3, "offset": 0, } }
{ "SERVICE": "todo", "ACTION": "list", "SEARCH": { "limit": 3, "offset": 0 } }
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']; }
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']; }
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']; }
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!
Atas ialah kandungan terperinci Panduan Terbaik untuk Perkhidmatan Generik Pionia.. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!