يحتوي هذا المستودع على إطار قليل قادر على القيام بـ Restapi بسهولة مع PHP
PDOUtilsRepository التنظيف من أجل استخدام PDOUtilsApiException.phpRest::handleRequest لإعادة HTTP 409 عند رفع الاستثناءRest::existFileSingletonController->getAllRest::scalePicturedbIgnoreController->getByFieldsRest::uploadFileRest::$uploadDirRest::getUploadDir()Rest::configureUploadDir()Rest::createDirectoryRecursive()Guards المضافةRole المضافةKeyValue والهيكل KeyValueListService Repository المحدثةCredentialsdeleteByField()getByField() المحدثة ، فإنها تُرجع الآن Model[] بدلاً من Model للبدء ، سيتعين عليك إنشاء مجلد (قمت بتسميته /rest ) ووضع مجلد ApiRest في الداخل. سيكون الملف الرئيسي هو api.php : سيقوم بإنشاء RestApi ، والاتصال بـ DB والاستماع إلى الطلبات.
فيما يلي المحتوى الافتراضي في هذا الملف:
<?php
require_once __DIR__ . " /ApiRest/RestAPI.php " ;
header ( ' Content-Type: application/json ' );
header ( ' Access-Control-Allow-Headers: Content-Type, enctype, token ' );
header ( ' Access-Control-Allow-Origin: * ' );
header ( ' Access-Control-Allow-Methods: GET, POST, PUT, DELETE ' );
$ restAPI = new RestAPI ( " localhost " , " myDB " , " root " , "" );
// You can add an argument to improve the security of your session like this :
//$restAPI = new RestAPI("localhost", "myDB", "root", "", "m*;rO)P7^)3'k[F'S~h0Lx7{zN%`6S");
Rest:: configureUploadDir ( " rest-upload " );
echo $ restAPI -> handleRequest (); الآن Restapi جاهز للاستخدام. يمكنك التحقق من ذلك مع Postman والضغط على عنوان URL مع طريقة GET : http://your-domain/your-path/rest/api.php/user .
إنه لأمر رائع ، ولكن كيف يتعامل Restapi مع ذلك؟
api.php (هنا هي كلمة user )user موجودًاuser/include.php موجودUserControllerprocessUrl في دليل user ، ستجد مثالاً لإضافة مسارات إلى راحة API لكائن User . يجب أن تكون كل ملفات متعلقة بكائن / فئة / جدول معين في نفس المجلد واتبع نفس القواعد مثل المستخدم:
/modelname/include.phpModelName.controller.phpModelName.model.phpModelName.repository.phpModelName.service.php وحدات التحكم هي الطبقة الأولى التي يطلق عليها Restapi. يجب تسميتها مثل هذا: modelClassName + "Controller" . بشكل افتراضي ، يتم إنشاء مسارات الأطروحات افتراضيًا:
api.php/modelClassNameapi.php/modelClassName/$idapi.php/modelClassNameapi.php/modelClassNameapi.php/modelClassName/$idبشكل افتراضي ، يرتبط كل مسار تم إنشاؤه بمسجل الحارس. إذا كنت ترغب في إزالة الحارس ، فسيتعين عليك تجاوز Apiroute بإعلانه في وحدة التحكم الخاصة بك.
يمكنك إضافة مرشح على وظيفة getall عن طريق إضافة قيم الحصول على عنوان URL. مثال :
api.php/modelClassName?lastname=Doe
فيما يلي مثال على فئة UserController:
<?php
// FILE rest/user/User.controller.php
require_once __DIR__ . " /../ApiRest/Rest.php " ;
require_once __DIR__ . " /../ApiRest/Controller.php " ;
class UserController extends Controller {
public function __construct ( string $ modelName ) {
parent :: __construct ( $ modelName );
$ this -> createApiRoute (Rest:: PUT , ' login ' , " login " );
$ this -> createApiRoute (Rest:: POST , ' picture ' , " uploadPicture " , [ new LoginGuard ()]);
}
/* PUT */
public static function login ( array $ params , stdClass $ body ): string {
$ user = User:: fromJSON ( $ body );
return static :: $ service -> login ( $ user );
}
public static function uploadPicture (): string {
$ fileName = " htmlInputName " ;
$ newName = " profilePicture.png " ;
Rest:: uploadFile ( $ fileName , $ newName );
return "" ;
}
} عند استدعاء وظيفة createApiRoute() ، تتوافق المعلمة الثانية مع مسار الطلب. في هذه السلسلة ، يمكنك إضافة معلمات ديناميكية مثل 'customPath/$param1/$param2/anything' . بعد ذلك ، عندما يتم استدعاء الوظيفة المرتبطة ، ستجد قيمًا لـ $param1 و $param2 على متغير $params :
var_dump ( $ params );
// print :
// array(
// "param1" => "value1",
// "param2" => "value2",
//)يمكنك تجاوز مسار مع آخر دون إزالته ، إذا لم يكن لديهم نفس القدر من المعلمات. على سبيل المثال ، سيتم الحفاظ على طرق الأطروحات:
$ this -> createApiRoute (Rest:: GET , ' $id ' , " getById " );
$ this -> createApiRoute (Rest:: GET , ' current ' , " getCurrent " );إذا أمكن ، سيتم تشغيل المسار "الحالي". إذا لم يكن الأمر كذلك ، فسيتم تشغيل مسار "$ ID".
الخدمات هي الطبقة التالية التي تسمى وحدات التحكم: فهي بين فصول التحكم وفئات المستودعات. يتم استخدام الخدمات للحصول على بيانات من فئات Repository وجعل المعالجة البيانات.
يمكن لدروس Service أيضًا استدعاء خدمات الآخرين لتجاوز البيانات وجعل عملية خاصة.
بشكل افتراضي ، يتم إنشاء الوظائف المرتبطة بمسارات وحدة التحكم:
getAll()getByID(string $id)create()update()delete(string $id)فيما يلي مثال على فئة userverse:
<?php
// FILE rest/user/User.service.php
require_once __DIR__ . " /../ApiRest/Service.php " ;
class UserService extends Service {
public function login ( User $ user ): string {
return $ this -> repository -> login ( $ user );
}
function initialize () { }
} إذا كنت ترغب في استخدام Service أخرى في فئة Theses ، فيجب عليك إعلانها وتهيئة فئة Service في وظيفة initialize مثل هذه:
<?php
class UserService extends Service {
/** @var $bookService BookService */
public $ bookService ;
public function login ( User $ user ): string {
return $ this -> repository -> login ( $ user );
}
function initialize () {
$ this -> bookService = BookService:: getInstance ( " Book " );
}
}المستودعات هي الطبقة النهائية التي تسمى الخدمات. أنها تحتوي على استعلامات SQL والحصول على كائن النماذج من قاعدة البيانات.
مثل الخدمات ، تتوفر وظائف الأطروحات الافتراضية:
getAll()getByID(string $id)create()update()delete(string $id)فيما يلي مثال على فئة Userrepository:
<?php
// FILE rest/user/User.repository.php
require_once __DIR__ . " /../ApiRest/Repository.php " ;
class UserRepository extends Repository {
public function __construct () {
parent :: __construct ( " user " , ' User ' );
}
public function login ( User $ user ): string {
$ fields = new KeyValueList ([
new KeyValue ( " name " , $ user -> name ),
new KeyValue ( " password " , $ user -> password )
]);
$ matchedUsers = $ this -> getByFields ( $ fields );
if ( count ( $ matchedUsers ) != 1 )
throw new Exception ( " UserRepository->login() : $ matchedUsers have a size of " . count ( $ matchedUsers ) . " instead of 1 ! " );
$ loggedUser = $ matchedUsers [ 0 ];
if ( $ loggedUser )
return Rest:: IDToToken ( $ loggedUser -> id );
else
return "" ;
}
}إذا كنت ترغب في استخدام استعلامات SQL مخصصة ، فيمكنك استخدام فئة Pdoutils لتنفيذها. هنا مثال:
$ query = " < CUSTOM_SELECT_QUERY > " ;
$ PDOStatement = PDOUtils:: executeQuery ( $ query );
return static :: getByPDOStatement ( $ PDOStatement ); هناك بعض الوظائف التي يمكنك استخدامها من PDOUtils :
executeQuery(query)executeQueryWithParameter(query, keyValue)executeQueryWithParameters(query, KeyValueList)النماذج هي الفئات التي تمثل خطًا في قاعدة البيانات.
عندما يتم استرداد البيانات من قاعدة البيانات ، لن يكون المنطقيون متساويين في true / false ولكن إلى '1' / '0' . لاستعادة منطقنا المسروقين ، يمكنك استدعاء الوظيفة preserveBooleans() لتحويل حقول منطقية.
للاحتفال بحقل مثل حقل منطقي ، ما عليك سوى استدعاء هذه الوظيفة داخل المنشئ: addBoolean("booleanField1", "booleanField2", ...)
على نفس الطريقة ، يمكنك وضع علامة على الحقل باسم Jsonignore من خلال استدعاء الوظيفة addIgnore("ignoredField1", ...) . ثم ، لتحويل مثيلات الطراز إلى JSON استدعاء وظيفة encode() !
هناك وظيفة أخرى: addDbIgnore("field1", ...) تستخدم لتحديد الحقول التي لا يتم تخزينها في قاعدة البيانات.
يمكن استرداد فئات النماذج من JSON باستخدام هذه الوظيفة الثابتة: Model::fromJSON(stdClass $data) .
يتم استخدام الحراس لتقييد الوصول إلى البيانات اعتمادًا على دور المستخدم. يتم إنشاء ثلاثة حراس افتراضيًا:
AdminGuardModeratorGuardLoginGuard إنهم يمتدون جميعًا فئة Guard Abstract ، وينفذون authorizeAccess(): bool . يمكنك إنشاء الحارس الخاص بك أيضًا باتباع نفس القواعد ، ثم إضافة سطر جديد في ملف include.php في دليل Guard .
يتم استدعاء الحراس في فصول وحدات التحكم ، عندما تعلن الطريق. لاحظ أن المسار يمكن أن يحتوي على 0 أو 1 أو عدة حراس.
يمكن إثارة الاستثناء عندما تكون هناك مشكلة يتم طباعتها في موقع الويب الأمامي. للقيام بذلك ، يجب عليك رمي ApiException وسيستجيب الخادم بخطأ HTTP 409 .
يمتد فئة ApiException فئة Exception ، لكنها لا تستخدم المعلمات من الفئة الفائقة.
يتم صنع هذه الفئة بطريقة لاستخدام أداة Frondend التدويل بسهولة: إنها تحتوي على معلمة key يمكن أن تكون مفتاح الترجمة في ملف JSON ، ومعلمة parameters التي تحتوي على البيانات المراد نقلها. على سبيل المثال ، إليك ملف Apiexception وملف تدويل JSON المرتبط به:
throw new ApiException ( " api-error.error1 " , [ " name " => ' John ' ]);{
"api-error" : {
"error1" : {
"title" : " Hey ! " ,
"text" : " Hello {{name}} "
}
}
} عند استخدام Apiexception ، سيتم تخزين هذه البيانات في خاصية error لعنصر HttpErrorResponse JavaScript.
أضف قدرة فرض نوع حقل كل طراز على خلاف ذلك ، لا توجد تحسينات مستقبلية مخططة الآن. لا يعني أنه لن يتم تحديث الحزمة!