سؤال

لذلك أنا أكتب إطارًا أريد أن أبني عليه بعض التطبيقات التي أعمل عليها (إطار العمل موجود لذا لدي بيئة للعمل بها، ونظام يسمح لي، على سبيل المثال، باستخدام إطار عمل واحد) سجل دخولك)

أريد أن أجعل هذا الإطار والتطبيقات التي يحتوي عليها تستخدم بنية موجهة نحو الموارد.

الآن، أريد إنشاء فئة توجيه URL قابلة للتوسيع بواسطة مؤلفي التطبيقات (وربما أيضًا بواسطة مستخدمي تطبيقات CMS، ولكن هذا هو المستقبل في المستقبل) وأحاول اكتشاف أفضل طريقة للقيام بذلك من خلال النظر في كيف تفعل التطبيقات الأخرى ذلك.

هل كانت مفيدة؟

المحلول

أفضّل استخدام reg ex بدلاً من إنشاء التنسيق الخاص بي نظرًا لأنه معروف جيدًا.لقد كتبت فصلًا صغيرًا أستخدمه والذي يسمح لي بدمج جداول التوجيه reg ex هذه.أستخدم شيئًا مشابهًا تم تنفيذه عن طريق الميراث ولكنه لا يحتاج إلى الميراث لذا أعدت كتابته.

أقوم بإجراء reg ex على مفتاح وأقوم بتعيين سلسلة التحكم الخاصة بي.خذ المثال أدناه.أزور /api/related/joe وتقوم فئة جهاز التوجيه الخاص بي بإنشاء كائن جديد ApiController ويدعو أسلوبه relatedDocuments(array('tags' => 'joe'));

// the 12 strips the subdirectory my app is running in
$index = urldecode(substr($_SERVER["REQUEST_URI"], 12)); 

Route::process($index, array(
    "#^api/related/(.*)$#Di"    => "ApiController/relatedDocuments/tags",

    "#^thread/(.*)/post$#Di"    => "ThreadController/post/title",
    "#^thread/(.*)/reply$#Di"   => "ThreadController/reply/title",
    "#^thread/(.*)$#Di"         => "ThreadController/thread/title",

    "#^ajax/tag/(.*)/(.*)$#Di"  => "TagController/add/id/tags",
    "#^ajax/reply/(.*)/post$#Di"=> "ThreadController/ajaxPost/id",
    "#^ajax/reply/(.*)$#Di"     => "ArticleController/newReply/id",
    "#^ajax/toggle/(.*)$#Di"    => "ApiController/toggle/toggle",

    "#^$#Di"                    => "HomeController",
));

من أجل تقليل الأخطاء والبساطة، يمكنك تقسيم الجدول الخاص بك.بهذه الطريقة يمكنك وضع جدول التوجيه في الفئة التي يتحكم فيها.بأخذ المثال أعلاه، يمكنك دمج استدعاءات سلاسل المحادثات الثلاثة في مكالمة واحدة.

Route::process($index, array(
    "#^api/related/(.*)$#Di"    => "ApiController/relatedDocuments/tags",

    "#^thread/(.*)$#Di"         => "ThreadController/route/uri",

    "#^ajax/tag/(.*)/(.*)$#Di"  => "TagController/add/id/tags",
    "#^ajax/reply/(.*)/post$#Di"=> "ThreadController/ajaxPost/id",
    "#^ajax/reply/(.*)$#Di"     => "ArticleController/newReply/id",
    "#^ajax/toggle/(.*)$#Di"    => "ApiController/toggle/toggle",

    "#^$#Di"                    => "HomeController",
));

ثم تقوم بتعريف ThreadController::route ليكون هكذا.

function route($args) {
    Route::process($args['uri'], array(
        "#^(.*)/post$#Di"    => "ThreadController/post/title",
        "#^(.*)/reply$#Di"   => "ThreadController/reply/title",
        "#^(.*)$#Di"         => "ThreadController/thread/title",
    ));
}

كما يمكنك تحديد الإعدادات الافتراضية التي تريدها لسلسلة التوجيه الخاصة بك على اليمين.فقط لا تنس توثيقها وإلا ستربك الناس.أقوم حاليًا باستدعاء الفهرس إذا لم تقم بتضمين اسم الوظيفة على اليمين. هنا هو الكود الحالي الخاص بي.قد ترغب في تغييره للتعامل مع الأخطاء بالطريقة التي تريدها و/أو الإجراءات الافتراضية.

نصائح أخرى

إطار آخر؟-- على أي حال...

تكمن الحيلة في التوجيه في تمرير كل شيء إلى وحدة تحكم التوجيه الخاصة بك.

ربما ترغب في استخدام شيء مشابه لما قمت بتوثيقه هنا:

http://www.hm2k.com/posts/Friendly-urls

يتيح لك الحل الثاني استخدام عناوين URL المشابهة لـ Zend Framework.

استخدم قائمة Regexs لمطابقة الكائن الذي يجب أن أستخدمه

على سبيل المثال

^/users/[\w-]+/bookmarks/(.+)/$
^/users/[\w-]+/bookmarks/$
^/users/[\w-]+/$

الايجابيات:لطيف وبسيط ، يتيح لي تحديد الطرق مباشرة السلبيات:يجب أن يتم طلبها، مما لا يجعل من السهل إضافة أشياء جديدة (عرضة للخطأ للغاية)

هذه هي الطريقة التي يفعل بها جانغو ذلك

أعتقد أن الكثير من الأطر تستخدم مزيجًا من mod_rewrite الخاص بـ Apache ووحدة التحكم الأمامية.باستخدام mod_rewrite، يمكنك تحويل عنوان URL مثل هذا:/people/get/3 في هذا:Index.php?controller=people&method=get&id=3.سيقوم Index.php بتنفيذ وحدة التحكم الأمامية الخاصة بك والتي تقوم بتوجيه طلب الصفحة بناءً على المعلمات المحددة.

كما قد تتوقع، هناك الكثير من الطرق للقيام بذلك.

على سبيل المثال، في إطار نحيف ، قد يكون ما يلي مثالاً لمحرك التوجيه (استنادًا إلى النمط ${OBJECT}->${REQUEST METHOD}(${PATTERM}, ${CALLBACK}) ):

$app->get("/Home", function() {
    print('Welcome to the home page');
}

$app->get('/Profile/:memberName', function($memberName) {
    print( 'I\'m viewing ' . $memberName . '\'s profile.' );
}

$app->post('/ContactUs', function() {
    print( 'This action will be fired only if a POST request will occure');
}

لذلك، المثيل الذي تمت تهيئته ($app) يحصل على طريقة لكل طريقة طلب (على سبيل المثالget وpost وput وdelete وما إلى ذلك) ويحصل على مسار باعتباره المعلمة الأولى ورد الاتصال باعتباره المعلمة الثانية.

يمكن أن يحصل المسار على الرموز المميزة - وهي "متغيرة" ستتغير في وقت التشغيل بناءً على بعض البيانات (مثل اسم العضو أو معرف المقالة أو اسم موقع المؤسسة أو أي شيء آخر - كما تعلم، تمامًا كما هو الحال في كل وحدة تحكم توجيه).

أنا شخصياً أحب هذه الطريقة ولكن لا أعتقد أنها ستكون مرنة بما يكفي لإطار عمل متقدم.

نظرًا لأنني أعمل حاليًا مع ZF وYii، لدي مثال لجهاز توجيه قمت بإنشائه كجزء من إطار عمل لشركة أعمل بها:

يعتمد محرك المسار على regex (على غرار محرك @gradbot) ولكنه يحتوي على محادثة ثنائية الاتجاه، لذلك إذا لم يتمكن عميلك من تشغيل mod_rewrite (في Apache) أو إضافة قواعد إعادة الكتابة على خادمه، فهو أو هي لا يزال بإمكانه استخدام عناوين URL التقليدية مع سلسلة الاستعلام.

يحتوي الملف على مصفوفة، كل منها، كل عنصر مشابه لهذا المثال:

$_FURLTEMPLATES['login']    =   array(
    'i' => array( // Input - how the router parse an incomming path into query string params
        'pattern' => '@Members/Login/?@i',
        'matches' => array( 'Application' => 'Members', 'Module' => 'Login' ),
    ),
    'o' => array( // Output - how the router parse a query string into a route
        '@Application=Members(&|&)Module=Login/?@' => 'Members/Login/'
    )
);

يمكنك أيضًا استخدام مجموعات أكثر تعقيدًا، مثل:

$_FURLTEMPLATES['article']  =   array(
    'i' => array(
        'pattern' => '@CMS/Articles/([\d]+)/?@i',
        'matches' => array( 'Application' => "CMS",
            'Module' => 'Articles',
            'Sector' => 'showArticle',
            'ArticleID' => '$1' ),
    ),
    'o' => array(
     '@Application=CMS(&|&)Module=Articles(&|&)Sector=showArticle(&|&)ArticleID=([\d]+)@' => 'CMS/Articles/$4'
    )
);

خلاصة القول، كما أعتقد، هي أن الاحتمالات لا حصر لها، فهي تعتمد فقط على مدى التعقيد الذي ترغب في أن يكون عليه إطار العمل الخاص بك وما ترغب في فعله به.

إذا كان المقصود، على سبيل المثال، فقط أن تكون خدمة ويب أو غلافًا بسيطًا لموقع الويب - فما عليك سوى اتباع أسلوب الكتابة الخاص بـ Slim Framework - وهو رمز سهل للغاية وجميل المظهر.

ومع ذلك، إذا كنت ترغب في تطوير مواقع معقدة باستخدامه، فأعتقد أن regex هو الحل.

حظ سعيد!:)

يجب عليك التحقق من Pux https://github.com/c9s/Pux

هنا هو الملخص

<?php
require 'vendor/autoload.php'; // use PCRE patterns you need Pux\PatternCompiler class.
use Pux\Executor;

class ProductController {
    public function listAction() {
        return 'product list';
    }
    public function itemAction($id) { 
        return "product $id";
    }
}
$mux = new Pux\Mux;
$mux->any('/product', ['ProductController','listAction']);
$mux->get('/product/:id', ['ProductController','itemAction'] , [
    'require' => [ 'id' => '\d+', ],
    'default' => [ 'id' => '1', ]
]);
$mux->post('/product/:id', ['ProductController','updateAction'] , [
    'require' => [ 'id' => '\d+', ],
    'default' => [ 'id' => '1', ]
]);
$mux->delete('/product/:id', ['ProductController','deleteAction'] , [
    'require' => [ 'id' => '\d+', ],
    'default' => [ 'id' => '1', ]
]);
$route = $mux->dispatch('/product/1');
Executor::execute($route);

يستخدم إطار عمل Zend MVC بشكل افتراضي بنية مثل

/router/controller/action/key1/value1/key2/value2

أين router هو ملف جهاز التوجيه (الذي تم تعيينه عبر mod_rewrite, controller هو من معالج إجراء وحدة التحكم الذي يتم تعريفه بواسطة فئة مشتقة من Zend_Controller_Action و action يشير إلى طريقة في وحدة التحكم، تسمى actionAction.يمكن أن يتم ترتيب أزواج المفتاح/القيمة بأي ترتيب وتكون متاحة لأسلوب الإجراء كمصفوفة ترابطية.

لقد استخدمت شيئًا مشابهًا في الماضي في الكود الخاص بي، وهو يعمل بشكل جيد حتى الآن.

حاول إلقاء نظرة على MVC نمط.
يستخدمه Zend Framework على سبيل المثال، ولكنه يستخدمه أيضًا CakePHP وCodeIgniter و...

أنا شخصياً لا أحب نموذج MVC، ولكن يتم تنفيذه في معظم الأحيان كمكون "عرض للويب".

القرار يعتمد إلى حد كبير على التفضيل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top