logologo
เริ่มต้น
คู่มือ
การพัฒนา
ปลั๊กอิน
API
English
简体中文
日本語
한국어
Deutsch
Français
Español
Português
Русский
Italiano
Türkçe
Українська
Tiếng Việt
Bahasa Indonesia
ไทย
Polski
Nederlands
Čeština
العربية
עברית
हिन्दी
Svenska
เริ่มต้น
คู่มือ
การพัฒนา
ปลั๊กอิน
API
logologo

เริ่มต้นใช้งานฉบับย่อ

ภาพรวมการพัฒนาปลั๊กอิน
การเขียนปลั๊กอินแรกของคุณ
โครงสร้างไดเรกทอรีโปรเจกต์

การพัฒนาฝั่งเซิร์ฟเวอร์

ภาพรวม
ปลั๊กอิน
คอลเลกชัน
การดำเนินการฐานข้อมูล
การจัดการแหล่งข้อมูล
การจัดการทรัพยากร
การควบคุมการเข้าถึง (ACL)
มิดเดิลแวร์
แคช
เหตุการณ์
คอนเท็กซ์คำขอ
สคริปต์การย้ายข้อมูล
ล็อก
การทำให้เป็นสากล (I18n)
คำสั่ง
การจัดการงานที่กำหนดเวลา
การทดสอบ

การพัฒนาฝั่งไคลเอนต์

ภาพรวม
ปลั๊กอิน
คอนเท็กซ์
เราเตอร์
การควบคุมการเข้าถึง (ACL)
การจัดการแหล่งข้อมูล
ทรัพยากร
คำขอ
สไตล์และธีม
ล็อก
การทำให้เป็นสากล (I18n)
การทดสอบ

อื่นๆ

คู่มือการอัปเกรดปลั๊กอิน
รายการภาษา
การจัดการ Dependencies
การสร้าง
Previous Pageการควบคุมการเข้าถึง (ACL)
Next Pageแคช
TIP

เอกสารนี้แปลโดย AI หากมีข้อมูลที่ไม่ถูกต้อง โปรดดูเวอร์ชันภาษาอังกฤษ

#มิดเดิลแวร์ (Middleware)

มิดเดิลแวร์ของ NocoBase Server นั้น โดยพื้นฐานแล้วคือ Koa มิดเดิลแวร์ ครับ/ค่ะ คุณสามารถจัดการอ็อบเจกต์ ctx เพื่อประมวลผลคำขอและการตอบกลับได้เหมือนกับการใช้งานใน Koa เลยครับ/ค่ะ แต่เนื่องจาก NocoBase ต้องจัดการตรรกะในเลเยอร์ธุรกิจที่แตกต่างกัน หากมิดเดิลแวร์ทั้งหมดถูกรวมไว้ด้วยกัน จะทำให้การบำรุงรักษาและการจัดการทำได้ยากมากครับ/ค่ะ

ด้วยเหตุนี้ NocoBase จึงแบ่งมิดเดิลแวร์ออกเป็น สี่ระดับ ดังนี้ครับ/ค่ะ

  1. มิดเดิลแวร์ระดับแหล่งข้อมูล (Data Source Level Middleware): app.dataSourceManager.use() มีผลเฉพาะกับคำขอของ แหล่งข้อมูลใดแหล่งข้อมูลหนึ่ง เท่านั้น มักใช้สำหรับตรรกะที่เกี่ยวข้องกับการเชื่อมต่อฐานข้อมูล การตรวจสอบความถูกต้องของฟิลด์ หรือการจัดการธุรกรรมสำหรับแหล่งข้อมูลนั้นๆ ครับ/ค่ะ

  2. มิดเดิลแวร์ระดับทรัพยากร (Resource Level Middleware): app.resourceManager.use() มีผลเฉพาะกับทรัพยากร (Resource) ที่ถูกกำหนดไว้แล้ว เหมาะสำหรับการจัดการตรรกะระดับทรัพยากร เช่น สิทธิ์การเข้าถึงข้อมูล การจัดรูปแบบ เป็นต้น ครับ/ค่ะ

  3. มิดเดิลแวร์ระดับสิทธิ์ (Permission Level Middleware): app.acl.use() ทำงานก่อนการตรวจสอบสิทธิ์ ใช้เพื่อยืนยันสิทธิ์หรือบทบาทของผู้ใช้ครับ/ค่ะ

  4. มิดเดิลแวร์ระดับแอปพลิเคชัน (Application Level Middleware): app.use() จะทำงานกับทุกๆ คำขอ เหมาะสำหรับการบันทึก Log, การจัดการข้อผิดพลาดทั่วไป, การประมวลผลการตอบกลับ เป็นต้น ครับ/ค่ะ

#การลงทะเบียนมิดเดิลแวร์

โดยทั่วไปแล้ว มิดเดิลแวร์จะถูกลงทะเบียนในเมธอด load ของปลั๊กอินครับ/ค่ะ ตัวอย่างเช่น:

export class MyPlugin extends Plugin {
  load() {
    // มิดเดิลแวร์ระดับแอปพลิเคชัน
    this.app.use(async (ctx, next) => {
      console.log('App middleware');
      await next();
    });

    // มิดเดิลแวร์แหล่งข้อมูล
    this.app.dataSourceManager.use(async (ctx, next) => {
      console.log('DataSource middleware');
      await next();
    });

    // มิดเดิลแวร์สิทธิ์
    this.app.acl.use(async (ctx, next) => {
      console.log('ACL middleware');
      await next();
    });

    // มิดเดิลแวร์ทรัพยากร
    this.app.resourceManager.use(async (ctx, next) => {
      console.log('Resource middleware');
      await next();
    });

  }
}

#ลำดับการทำงาน

ลำดับการทำงานของมิดเดิลแวร์มีดังนี้ครับ/ค่ะ

  1. มิดเดิลแวร์สิทธิ์ที่เพิ่มด้วย acl.use() จะทำงานก่อน
  2. จากนั้น มิดเดิลแวร์ทรัพยากรที่เพิ่มด้วย resourceManager.use() จะทำงาน
  3. ต่อมา มิดเดิลแวร์แหล่งข้อมูลที่เพิ่มด้วย dataSourceManager.use() จะทำงาน
  4. สุดท้าย มิดเดิลแวร์ระดับแอปพลิเคชันที่เพิ่มด้วย app.use() จะทำงาน

#กลไกการแทรก before / after / tag

เพื่อให้ควบคุมลำดับของมิดเดิลแวร์ได้อย่างยืดหยุ่นมากขึ้น NocoBase มีพารามิเตอร์ before, after และ tag ให้ใช้งานครับ/ค่ะ

  • tag: ใช้สำหรับกำหนดแท็กให้กับมิดเดิลแวร์ เพื่อให้มิดเดิลแวร์ถัดไปสามารถอ้างอิงถึงได้
  • before: แทรกมิดเดิลแวร์ก่อนมิดเดิลแวร์ที่มีแท็กที่ระบุ
  • after: แทรกมิดเดิลแวร์หลังมิดเดิลแวร์ที่มีแท็กที่ระบุ

ตัวอย่าง:

// มิดเดิลแวร์ทั่วไป
app.use(m1, { tag: 'restApi' });
app.resourceManager.use(m2, { tag: 'parseToken' });
app.resourceManager.use(m3, { tag: 'checkRole' });

// m4 จะถูกจัดวางก่อน m1
app.use(m4, { before: 'restApi' });

// m5 จะถูกแทรกอยู่ระหว่าง m2 และ m3
app.resourceManager.use(m5, { after: 'parseToken', before: 'checkRole' });
TIP

หากไม่ได้ระบุตำแหน่ง มิดเดิลแวร์ที่เพิ่มเข้ามาใหม่จะมีลำดับการทำงานเริ่มต้นดังนี้ครับ/ค่ะ acl.use() -> resourceManager.use() -> dataSourceManager.use() -> app.use()

#ตัวอย่างโมเดล Onion (Onion Model)

ลำดับการทำงานของมิดเดิลแวร์เป็นไปตาม โมเดล Onion ของ Koa ครับ/ค่ะ ซึ่งหมายความว่าจะเข้าสู่ Stack ของมิดเดิลแวร์ก่อน และออกจาก Stack เป็นลำดับสุดท้าย

app.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(1);
  await next();
  ctx.body.push(2);
});

app.resourceManager.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(3);
  await next();
  ctx.body.push(4);
});

app.acl.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(5);
  await next();
  ctx.body.push(6);
});

app.resourceManager.define({
  name: 'test',
  actions: {
    async list(ctx, next) {
      ctx.body = ctx.body || [];
      ctx.body.push(7);
      await next();
      ctx.body.push(8);
    },
  },
});

ตัวอย่างลำดับการแสดงผลเมื่อเข้าถึง API ที่แตกต่างกัน:

  • คำขอทั่วไป: /api/hello ผลลัพธ์: [1,2] (ไม่ได้กำหนดทรัพยากร จึงไม่ทำงาน resourceManager และ acl มิดเดิลแวร์)

  • คำขอทรัพยากร: /api/test:list ผลลัพธ์: [5,3,7,1,2,8,4,6] มิดเดิลแวร์จะทำงานตามลำดับชั้นและโมเดล Onion

#สรุป

  • NocoBase Middleware เป็นส่วนขยายของ Koa Middleware
  • มีสี่ระดับ: แอปพลิเคชัน -> แหล่งข้อมูล -> ทรัพยากร -> สิทธิ์
  • สามารถใช้ before / after / tag เพื่อควบคุมลำดับการทำงานได้อย่างยืดหยุ่น
  • เป็นไปตามโมเดล Onion ของ Koa ซึ่งรับประกันว่ามิดเดิลแวร์สามารถประกอบและซ้อนกันได้
  • มิดเดิลแวร์ระดับแหล่งข้อมูลจะมีผลเฉพาะกับคำขอของแหล่งข้อมูลที่ระบุเท่านั้น และมิดเดิลแวร์ระดับทรัพยากรจะมีผลเฉพาะกับคำขอของทรัพยากรที่ถูกกำหนดไว้แล้ว