رابط المسار، وخيارات الأمر، وأعمدة النموذج: إن لصقتها في Markdown مرة واحدة، فستتقادم. أما المرجع الحي فيقرأ تلك الحقيقة من تطبيقك في كل مرة تُصيَّر فيها الصفحة، فلا يمكن أن يبتعد عنها. اكتب الوسم مع اسم ما يصفه، في سطر مستقل:
<Route name="orders.store" />
<Artisan command="orders:prune" />
<Model name="Order" />
<Event name="OrderShipped" />| المكوّن | ما يعرضه |
|---|---|
<Route name="..." /> |
الطريقة (method)، والرابط (URI)، وأسماء الـ middleware، وحقول الـ form request الذي يحدّده الإجراء في توقيعه وأسماء قواعده |
<Artisan command="..." /> |
الوصف، وطريقة الاستخدام، والوسائط، والخيارات، مع القيم الافتراضية التي يعلنها توقيعه |
<Model name="..." /> |
الجدول، والأعمدة مع النوع وقابلية القيمة الفارغة (nullable) والتحويل (cast) وقابلية التعبئة (fillable)، والعلاقات |
<Event name="..." /> |
خصائص الحمولة (payload) العامة مع أنواعها، والمستمعون (متزامنون أو في طابور)، وهل يُبث الحدث |
غيّر اسم المسار، وسيفشل php artisan larecipe:validate في كل صفحة لا تزال تسمّي الاسم القديم. والتوثيق يعمل بالكامل من دون المراجع الحية، فاعتمدها صفحةً بعد صفحة.
هذا المرجع حي، يُقرأ من تطبيق هذا الموقع عند كل تصيير: المسار الذي يقف خلف نموذج النشرة البريدية في أسفل كل صفحة.
POST /newsletter/subscribe| Method | POST |
|---|---|
| URI | /newsletter/subscribe |
| Middleware | web, throttle |
اكتب مرجعًا
- Route: اسم المسار، لا رابطه أبدًا. والمسار الذي لا اسم له لا يمكن الإشارة إليه، وتسميته تغيير من سطر واحد يجعل التوثيق أكثر أمانًا.
- Artisan: اسم الأمر، كما تكتبه بعد
php artisan. - Model: اسم صنف في نطاق أسماء مسموح به (
OrderتعنيApp\Models\Orderافتراضيًا)، أو اسم صنف كامل داخل أحدها. - Event: اسم صنف في نطاق أسماء للأحداث (
OrderShippedتعنيApp\Events\OrderShippedافتراضيًا)، أو أي صنف حدث كامل الاسم له مستمعون مسجّلون.
اكتب جملة حول كل مرجع. يعرض المكوّن الحقائق، وكلماتك تقول متى تهمّ ولماذا. ويحصل الوكلاء على الحقائق نفسها: فنسخة Markdown الخاصة بالصفحة تُصيّر كل مرجع سطرًا بخط عريض تليه جداوله.
لا يوجد <Config> ولا <Env>، وذلك عن قصد. فقيم الإعدادات والبيئة هي حيث تعيش الأسرار. ولتذكر إعدادًا، اكتب اسمه في كود مضمّن (services.stripe.secret) وقل ما الذي يتحكّم فيه.
حين ينكسر المرجع
المسار أو الأمر أو النموذج الذي لم يعد موجودًا يتوقف عن التصيير. تعرض الصفحة مكانه إشعارًا بسيطًا، مثل "The route orders.store is not defined in this app."، وتعرض نسخة Markdown الجملة نفسها تحذيرًا، ويبلّغ larecipe:validate عن خطأ references.missing مع رقم السطر. وهكذا فإن تغيير اسم مسار من دون تحديث التوثيق يُفشل التحقق، في جلسة وكيلك وفي CI. وتطلب مهارة larecipe-update-docs من الوكلاء إصلاح هذه المراجع مع تغيير الكود.
اختر ما يجوز وصفه
ثلاثة إعدادات في config/larecipe.php تحدّد المسارات والأصناف التي يجوز للصفحة أن تشير إليها:
'references' => [
'routes' => [
'allow' => null, // route names or URIs (with *); null: your app's own routes
],
'models' => [
'allow' => ['App\\Models\\*'], // namespaces (with *) or exact classes
],
'events' => [
'namespaces' => ['App\\Events'], // where short event names are looked up
],
],لا يصف <Model> إلا الأصناف الواردة في references.models.allow، فلا تستطيع الصفحة أبدًا أن توجّه المحلِّل إلى صنف عشوائي.
تفاصيل
مرجعان آخران، حيّان من هذا الموقع
الأمر الذي يشغّله وكيل البرمجة قبل أن يجري الـ push:
larecipe:affectedList the docs pages a change affects and the ones it left stale
php artisan larecipe:affected [--base [BASE]] [--head [HEAD]] [--uncommitted] [--set [SET]] [--docs-version [DOCS-VERSION]] [--locale [LOCALE]] [--format [FORMAT]] [--fail-on-stale] [--no-drift]| Option | Description | Default |
|---|---|---|
--base=BASE | Compare with this branch or commit (from where the branch left it) | |
--head=HEAD | The end of the range | HEAD |
--uncommitted | Include staged, unstaged and untracked changes | |
--set=SET | Only this doc set | |
--docs-version=DOCS-VERSION | A version id, or "all" (default: each set's default version) | |
--locale=LOCALE | Check this locale's translations against their source pages | |
--format=FORMAT | text, json, github or markdown | text |
--fail-on-stale | Exit with 1 when the change leaves pages stale | |
--no-drift | Skip pages that drifted before this change |
والحدث الذي يطلقه LaRecipe عند كل مشاهدة صفحة، لتحليلاتك الخاصة:
LaRecipe\Domains\Delivery\Events\PageViewed| Property | Type |
|---|---|
kind | string |
userAgent | ?string |
set | string |
page | LaRecipe\Domains\Content\DTOs\PageRef |
format | string |
| Listener | Runs |
|---|
أي المسارات والأحداث يجوز وصفها
يصف <Route> المسارات التي تسردها references.routes.allow، بالاسم أو بالرابط، مع * محرف بدل ('orders.*' و 'api/*'). ومع null، القيمة الافتراضية، يصف كل مسار يعرّفه تطبيقك: أما المسارات التي تسجّلها الحزم في vendor/، مثل لوحة إدارة أو شريط تصحيح، فتُستبعد، ما عدا مسارات LaRecipe نفسه. والقائمة تشمل مسارات الحزم التي تسمّيها. ويتبع larecipe:references:snapshot و larecipe:validate القائمة نفسها.
ويصف <Event> الأصناف الواردة في references.events.namespaces، وأي صنف آخر يسجّل له تطبيقك مستمعين. ويضيف هذا الموقع نطاقات أسماء أحداث LaRecipe إلى القائمة، وبهذا يُحلّ مرجع PageViewed.
والمسار الذي تستبعده قائمة السماح، والأمر المخفي، يُقرآن كما يُقرأ ما لا وجود له: الإشعار في الصفحة، وخطأ references.missing من أداة التحقق.
ما الذي تقرؤه، وما الذي لا تفعله أبدًا
لا تقرأ المحلِّلات إلا البنية العامة لتطبيقك:
- Route يقرأ ما يعلنه تعريف المسار، ولا يعرض إلا الأسماء: كل middleware من دون معاملاته (
throttle، لاthrottle:5,1)، وكل حقل في الـ form request مع أسماء قواعده، لا وسائطها أبدًا (in، لا قائمة القيم). فوسائط القواعد ومعاملات الـ middleware كثيرًا ما تُبنى من الإعدادات، لذا لا تعرضها الصفحة أبدًا. ولا يُعرض نطاق المسار كذلك. ولا يُشغَّل المسار أبدًا ولا يُبنى المتحكّم الخاص به، لذا لا يظهر الـ middleware الذي يضيفه المتحكّم في دالة البناء. ويُنشأ الـ form request من دون الحاوية (container)، فلا يتحقق من أي شيء أبدًا. - Artisan يقرأ توقيع الأمر. لا يُشغَّل الأمر أبدًا، ولا تُوصف الأوامر المخفية أبدًا. ولا تظهر القيمة الافتراضية إلا حين تكون مكتوبة في
$signatureالخاص بالأمر: فالأمر الذي يبني خياراته وقت التشغيل، أو الأمر المعرّف بدالة مغلقة (closure)، قد يملأ قيمة افتراضية من الإعدادات، لذا تُستبعد قيمه الافتراضية. - Model يستخدم أداة فحص النماذج في Eloquent، التي تحتاج إلى اتصال بقاعدة البيانات لقائمة الأعمدة. وتُستبعد القيم الافتراضية للأعمدة: فهي قيم، والمرجع يعرض البنية.
- Event يسرد أسماء الخصائص وأنواعها، لا قيمها أبدًا.
كيف تُخزَّن مؤقتًا الصفحات التي فيها مراجع
تُخزَّن الصفحات المُصيَّرة مؤقتًا حسب محتواها، والصفحة التي فيها مراجع حية تُخزَّن أيضًا حسب بصمة لأجزاء التطبيق التي تقرؤها:
| النوع | تتغيّر البصمة حين |
|---|---|
| Route | يتغيّر ملف ذاكرة المسارات المؤقتة، أو، من دونه، اسم أي مسار أو طرقه أو رابطه أو نطاقه أو الـ middleware الخاص به أو إجراؤه |
| Artisan | يتغيّر توقيع أي أمر أو وصفه |
| Model | يتغيّر صنف نموذج مسموح به أو ملف ترحيل |
| Event | يتغيّر صنف حدث أو مستمعوه |
تغيير اسم مسار يعيد تصيير الصفحات التي تستخدم <Route> بالضبط، من دون ذاكرة مؤقتة تمسحها بيدك. والصفحة التي لا تُحلّ مراجعها لا تُخزَّن مؤقتًا على الإطلاق، فيظهر الإصلاح عند الطلب التالي.
CI من دون قاعدة بيانات
تُحلّ المسارات والأوامر كلما أقلع التطبيق. أما <Model> فيحتاج إلى مخطط قاعدة بيانات، ومعظم خطوط CI (pipelines) لديها واحد (فهي تشغّل الترحيلات على SQLite أو قاعدة بيانات اختبار). وحين لا يكون لديك ذلك، اكتب لقطة حيث يتوفّر المخطط:
larecipe:references:snapshotSnapshot what live references can read, for CI without a database
php artisan larecipe:references:snapshotيكتب الأمر كل مسار وأمر ونموذج مسموح به وحدث يستطيع التطبيق وصفه إلى bootstrap/cache/larecipe/references.json. ولا تستخدم المحلِّلات اللقطة إلا حين لا يستطيع التطبيق الإجابة، مثلًا حين يفشل الاتصال بقاعدة البيانات. والجواب الحي "هذا لم يعد موجودًا" يغلب دائمًا، فلا تستطيع لقطة قديمة أبدًا أن تخفي مرجعًا انكسر. ويعيش الملف في مجلد ذاكرة مؤقتة: أنشئه داخل خط CI بدلًا من إضافته إلى git.
المراجع الحية و sources:
تسمّي المراجع الحية أهدافها، لذا يقرؤها larecipe:sources:suggest مع الأصناف والأوامر وأسماء المسارات في الكود المضمّن لديك حين يقترح sources: لصفحة. راجع كيف يعمل إبقاء التوثيق محدّثًا.
التالي
- كتل الصلاحيات والتوثيق الخاص: محتوى لكل قارئ، في كل واجهة.
- المكوّنات: كل مكوّن مدمج.
- التحقق و doctor: ما الذي يتحقق منه
larecipe:validate.