ایجاد مدل کاربران (Creating a Users Model)
در این بخش، نحوه ایجاد مدل کاربران (Users Model) را بررسی میکنیم. این شامل ساختار داده (Data Structure)، متدهای دسترسی (Access Methods) و عملیات پایگاه داده (Database Operations) میشود.
برای شروع، بیایید یک جدول کاربران (Users Table) در پایگاه داده (Database) خود ایجاد کنیم:
USE snippetbox; CREATE TABLE users ( id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, hashed_password CHAR(60) NOT NULL, created DATETIME NOT NULL ); ALTER TABLE users ADD CONSTRAINT users_uc_email UNIQUE (email);
چند نکته در مورد این جدول وجود دارد:
فیلد
idیک فیلد عدد صحیح خودافزایشی و کلید اصلی جدول است. این بدان معناست که مقادیر شناسه کاربر به صورت اعداد صحیح مثبت منحصر به فرد (1، 2، 3 و غیره) تضمین میشوند.نوع فیلد
hashed_passwordCHAR(60)است. این به این دلیل است که ما هشهای bcrypt از رمزهای عبور کاربران را در پایگاه داده ذخیره خواهیم کرد — نه خود رمزها — و هشها همیشه دقیقاً 60 کاراکتر طول دارند.ما همچنین یک محدودیت
UNIQUEبر روی ستونemailاضافه کردهایم و آن راusers_uc_emailنامگذاری کردهایم. این محدودیت تضمین میکند که ما با دو کاربر که آدرس ایمیل یکسانی دارند مواجه نخواهیم شد. اگر سعی کنیم رکوردی را در این جدول با ایمیل تکراری وارد کنیم، MySQL یک خطایERROR 1062: ER_DUP_ENTRYپرتاب خواهد کرد.
ساخت مدل در Go
سپس بیایید یک مدل تنظیم کنیم تا بتوانیم به راحتی با جدول جدید users کار کنیم. ما همان الگویی را که قبلاً در کتاب برای مدلسازی دسترسی به جدول snippets استفاده کردهایم، دنبال خواهیم کرد، بنابراین امیدواریم که این کار آشنا و ساده باشد.
ابتدا فایل internal/models/errors.go را که قبلاً ایجاد کردهاید باز کنید و چند نوع خطای جدید تعریف کنید:
package models import ( "errors" ) var ( ErrNoRecord = errors.New("models: no matching record found") // Add a new ErrInvalidCredentials error. We'll use this later if a user // tries to login with an incorrect email address or password. ErrInvalidCredentials = errors.New("models: invalid credentials") // Add a new ErrDuplicateEmail error. We'll use this later if a user // tries to signup with an email address that's already in use. ErrDuplicateEmail = errors.New("models: duplicate email") )
سپس یک فایل جدید در internal/models/users.go ایجاد کنید:
$ touch internal/models/users.go
…و یک ساختار جدید User (برای نگهداری دادههای یک کاربر خاص) و یک ساختار UserModel (با برخی متدهای جایگزین برای تعامل با پایگاه داده ما) تعریف کنید. به این صورت:
package models import ( "database/sql" "time" ) // Define a new User struct. Notice how the field names and types align // with the columns in the database "users" table? type User struct { ID int Name string Email string HashedPassword []byte Created time.Time } // Define a new UserModel struct which wraps a database connection pool. type UserModel struct { DB *sql.DB } // We'll use the Insert method to add a new record to the "users" table. func (m *UserModel) Insert(name, email, password string) error { return nil } // We'll use the Authenticate method to verify whether a user exists with // the provided email address and password. This will return the relevant // user ID if they do. func (m *UserModel) Authenticate(email, password string) (int, error) { return 0, nil } // We'll use the Exists method to check if a user exists with a specific ID. func (m *UserModel) Exists(id int) (bool, error) { return false, nil }
مرحله نهایی اضافه کردن یک فیلد جدید به ساختار application است تا بتوانیم این مدل را در دسترس هندلرهای خود قرار دهیم. فایل main.go را به صورت زیر بهروزرسانی کنید:
package main ... // Add a new users field to the application struct. type application struct { logger *slog.Logger snippets *models.SnippetModel users *models.UserModel templateCache map[string]*template.Template formDecoder *form.Decoder sessionManager *scs.SessionManager } func main() { ... // Initialize a models.UserModel instance and add it to the application // dependencies. app := &application{ logger: logger, snippets: &models.SnippetModel{DB: db}, users: &models.UserModel{DB: db}, templateCache: templateCache, formDecoder: formDecoder, sessionManager: sessionManager, } tlsConfig := &tls.Config{ CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256}, } srv := &http.Server{ Addr: *addr, Handler: app.routes(), ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError), TLSConfig: tlsConfig, IdleTimeout: time.Minute, ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } logger.Info("starting server", "addr", srv.Addr) err = srv.ListenAndServeTLS("./tls/cert.pem", "./tls/key.pem") logger.Error(err.Error()) os.Exit(1) } ...
اطمینان حاصل کنید که همه فایلها ذخیره شدهاند، سپس برنامه را اجرا کنید. در این مرحله باید متوجه شوید که بدون هیچ مشکلی کامپایل میشود.
واژهنامه اصطلاحات فنی
| اصطلاح فارسی | معادل انگلیسی | توضیح |
|---|---|---|
| مدل کاربران | Users Model | ساختار داده برای کاربران |
| ساختار داده | Data Structure | الگوی سازماندهی دادهها |
| متدهای دسترسی | Access Methods | توابع دسترسی به دادهها |
| عملیات پایگاه داده | Database Operations | دستورات کار با پایگاه داده |
| جدول کاربران | Users Table | جدول ذخیره اطلاعات کاربران |
| پایگاه داده | Database | محل ذخیرهسازی دادهها |
| رکورد کاربر | User Record | اطلاعات یک کاربر |
| درج داده | Data Insertion | افزودن داده جدید |
| بازیابی داده | Data Retrieval | خواندن داده از پایگاه داده |
| بهروزرسانی داده | Data Update | تغییر داده موجود |